在上一个例子中,模拟了匀速直线运动,质点是一个理想化的物理模型,当把物体看成质点时,不需要考虑它的大小,形状和旋转。在Canvas中,同样可以模拟一匀加速运动,比如,重力场下的物体运动。由于地球的吸引而使物体受到的力,叫做重力,生活中常把物体所受重力的大小写简称物重,重力的方向总是竖直向下或者指向地心的。
重力场下的永动机:
想像一个弹性质量完美的小球,在重力场的作用下,碰撞到地面,弹起,碰撞,弹起……其代码如下:
var c = document.getElementById("myCanvas");
var cxt = c.getContext("2d");
var ball = {
position: { x: 100, y: 100 },
r: 15,
vx: 190,
vy: 110
};
var cyc = 10;
var a = 50;
var hitCount = 0;
var moveAsync = eval(Jscex.compile("async", function () {
while (true) {
cxt.fillStyle = "rgba(0,0,0,.3)";
cxt.fillRect(0, 0, c.width, c.height);
cxt.fillStyle = "#fff";
cxt.beginPath();
cxt.arc(ball.position.x, ball.position.y, ball.r, 0, Math.PI * 2, true);
cxt.closePath();
cxt.fill();
ball.position.y += ball.vy * cyc / 1000;
if (ball.r + ball.position.y >= c.height) {
ball.vy *= -1;
} else {
ball.vy += a;
}
$await(Jscex.Async.sleep(cyc));
}
}));
moveAsync().start();
运行效果如下:
耗能的重力场:
想像一个弹性的铁球,在重力的作用下,碰撞地面,弹起,碰撞,弹起,最后静止,其代码如下:
var moveAsync = eval(Jscex.compile("async", function () {
while (true) {
cxt.fillStyle = "rgba(0,0,0,.3)";
cxt.fillRect(0, 0, c.width, c.height);
cxt.fillStyle = "#fff";
cxt.beginPath();
cxt.arc(ball.position.x, ball.position.y, ball.r, 0, Math.PI * 2, true);
cxt.closePath();
cxt.fill();
ball.position.y += ball.vy * cyc / 1000;
if (ball.r + ball.position.y >= c.height) {
if (ball.vy > 0) {
ball.vy *= -0.8;
hitCount++;
}
} else {
ball.vy += a;
}
if (hitCount > 15)
break;
$await(Jscex.Async.sleep(cyc));
}
}));
在上面的代码中,假设碰撞之后损失了2%的速度,在真实的物理当中,会为每个碰撞物体设定一个弹性系数,当然复杂的物理引擎会为物体的每个面设置一个弹性系数,然后根据接触面的弹性系数,计算出最后的速度大小。
运行效果如下: