先に,JavaScript の学習環境を書いてみたのですが,講義で利用するために,プログラムのサンプルを書いてみています。以前に,重力場の中での運動を書いたので,それに衝突を入れてみました。
ソースを下記にあげます。少し説明を書きます。
(19行あたり) mx, my はクリックしたマウスの座標です。
(22行あたり) 運動するボールの座標などを記録するオブジェクトが並んでいます。
(26行あたり) 運動するボールを配列に格納。
(48行あたり) ボールをドキュメントに追加。
(52行あたり) 30 msec ごとに,ボールの座標値を計算する関数(updata)を起動。
(60行あたり) set_r_v は,座標と速度を計算する関数。重力の効果も取り入れいている。
(62行あたり) if_collision は,衝突の判断をする関数。衝突時の速度の計算など。50px 以内なら衝突と判断する。物体の質量はすべて同じとして計算している。衝突はもっとも近くにあるボールのみ考慮する。
(64行あたり) in_box は箱の壁で反射させる関数。
(66行あたり) move は最終的にボールを移動させる関数。
(153行あたり) mouseDown クリックしたマウスの位置を取得する関数。これがIEでしか動かない部分。
(170行あたり) set_v0 は,ボールの速度を再設定する関数。
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>first</title>
<style type="text/css">
body {
margin: 0px;
padding: 0px;
background-color: #ffffff;
}
</style>
<script type="text/javascript">
var mx = 0;
var my = 0;
var gray = {id:'maru',src:'maru.gif', x:150,y:150,vx:-1,vy:0};
var red = {id:'red', src:'red.gif', x:210,y:160,vx:1,vy:0};
var blue = {id:'blue', src:'blue.gif', x:30,y:100,vx:-3,vy:0};
var obj_ary = new Array (gray,red,blue);
var obj_ary_length = obj_ary.length;
function startup() {
for (var i in obj_ary) {
var tmpleft = Number(obj_ary[i].x) - 25;
var element = document.createElement('img');
element.setAttribute('id',obj_ary[i].id);
element.setAttribute('src',obj_ary[i].src);
element.style.position = 'absolute';
element.style.left = tmpleft;
element.style.top = '125px';
element.style.height = '50px';
var tmpid = document.getElementById("box")
tmpid.appendChild(element);
}
var step = setInterval(updata,30);
}
function updata() {
for (var i in obj_ary) {
set_r_v(obj_ary[i]);
if_collision(i,obj_ary[i]);
in_box(obj_ary[i]);
move(obj_ary[i]);
}
}
function set_r_v(tmpobj) {
tmpobj.vy = tmpobj.vy + 0.05;
tmpobj.x = tmpobj.x + tmpobj.vx;
tmpobj.y = tmpobj.y + tmpobj.vy;
return;
}
function if_collision(i,tmpobj) {
var i = Number(i);
min_distance = 1000;
min_j = 10001;
var x1 = tmpobj.x;
var y1 = tmpobj.y;
for (var j = i + 1; j < obj_ary_length; j = j + 1) {
var x2 = obj_ary[j].x;
var y2 = obj_ary[j].y;
var distance = Math.sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2));
if (distance < min_distance) {
min_distance = distance;
min_j = j;
}
} // loop for j
if (min_distance*min_distance < 1) {
min_distance = 1;
}
if (min_distance < 50) {
//alert('collision');
var x2 = obj_ary[min_j].x;
var y2 = obj_ary[min_j].y;
var overlap = (50 - min_distance)/1;
var e1 = {x: (x1 - x2)/min_distance,y:(y1 - y2)/min_distance};
var e2 = {x:-(y1 - y2)/min_distance,y:(x1 - x2)/min_distance};
var v1 = {x:obj_ary[i].vx,y:obj_ary[i].vy};
var v2 = {x:obj_ary[min_j].vx,y:obj_ary[min_j].vy};
obj_ary[i].vx = inner_product(v2,e1) * e1.x + inner_product(v1,e2) * e2.x;
obj_ary[i].vy = inner_product(v2,e1) * e1.y + inner_product(v1,e2) * e2.y;
obj_ary[min_j].vx = inner_product(v1,e1) * e1.x + inner_product(v2,e2) * e2.x;
obj_ary[min_j].vy = inner_product(v1,e1) * e1.y + inner_product(v2,e2) * e2.y;
obj_ary[i].x = obj_ary[i].x + overlap * e1.x;
obj_ary[min_j].x = obj_ary[min_j].x - overlap * e1.x;
obj_ary[i].y = obj_ary[i].y + overlap * e1.y;
obj_ary[min_j].y = obj_ary[min_j].y - overlap * e1.y;
}
}
function inner_product(v1,v2) {
return v1.x * v2.x + v1.y * v2.y;
}
function mouseDown() {
var theEvent = window.event;
mx = theEvent.clientX - 10;
my = theEvent.clientY - 10;
//alert("mx = " + mx + " my = " + my);
for (var i in obj_ary) {
set_v0(obj_ary[i]);
}
}
function set_v0(tmpobj) {
var kyori = Math.sqrt((mx - tmpobj.x)*(mx - tmpobj.x) + (my - tmpobj.y)*(my - tmpobj.y));
if (kyori < 1) {
return;
} else {
tmpobj.vx = 3*(mx - tmpobj.x) / kyori;
tmpobj.vy = 3*(my - tmpobj.y) / kyori;
}
}
function move(tmpobj) {
var tmpid = document.getElementById(tmpobj.id);
tmpid.style.left = tmpobj.x - 25;
tmpid.style.top = tmpobj.y - 25;
}
function in_box(tmpobj) {
if ((tmpobj.x < 25) || (275 < tmpobj.x)) {
tmpobj.vx = - tmpobj.vx;
if (tmpobj.x < 25) {
tmpobj.x = 25 + (25 - tmpobj.x);
} else {
tmpobj.x = 275 - (tmpobj.x - 275);
}
}
if ((tmpobj.y < 25) || (275 < tmpobj.y)) {
tmpobj.vy = - tmpobj.vy;
if (tmpobj.y < 25) {
tmpobj.y = 25 + (25 - tmpobj.y);
} else {
tmpobj.y = 275 - (tmpobj.y - 275);
}
}
return;
}
</script>
</head>
<!--<body>-->
<body onload="startup();">
<div id="box" style="position: absolute; left: 10px; top: 10px; width: 300px; height: 300px; border-width: 1px; border-color: black; border-style: solid; " onclick='mouseDown();'>
</div>
<div style="position: absolute; left: 30px; top: 500px; width: 300px; height: 100px; border-width: 0px; border-color: black; border-style: solid; ">
<strong>(参考2) 衝突を取り入れました</strong><br />
ときどき計算間違いをしています。<br />
</div>
</body>
</html>