HTML5实验室
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

实验9 万有引力

简介

实验8是把物体看成质点,模拟了匀速直线运动。质点是一个理想化的物理模型,当把物体看成质点时,不需要考虑它的大小、形状和旋转。在 Canvas中,同样可以模拟一个匀加速运动,比如,重力场下的物体运动。由于地球的吸引而使物体受到的力,叫做重力(Gravity),生活中常把物体所受重力的大小简称物重。重力的方向总是竖直向下或指向地心的,如图2-4所示。

图2-4 重力

重力的单位是N,但是表示符号为G,公式为:G=mg。其中,m是物体的质量,g一般取9.8 N/kg。在一般使用中,常把重力近似看做等于万有引力。但实际上,重力是万有引力的一个分力。重力之所以是一个分力,是因为在地球上与地球一起运动,这个运动可以近似看成匀速圆周运动。做匀速圆周运动需要向心力,在地球上,这个力由万有引力的一个指向地轴的分力提供,而万有引力的另一个分力就是平时所说的重力了。

速度是加速度对时间的累积,即:

v=∫a dt

重力场下的永动机

想象一个弹性质量完美的小球,在重力场的作用下,碰撞地面(无能量损失),弹起,碰撞地面,弹起……无限循环下去,其代码实现:

        var canvas=document.getElementById("myCanvas");
        var cxt=canvas.getContext("2d");
        var ball={
                  x: 100,
                  y: 100,
                  r: 15,
                  vx: 0,
                  vy: 0
                };
        var cyc=10;
        var a=50;
        var moveAsync=eval(Jscex.compile("async", function () {
        while (true) {
                      cxt.fillStyle="rgba(0, 0, 0, .3)";
                      cxt.fillRect(0, 0, canvas.width, canvas.height);
                      cxt.fillStyle="#fff";
                      cxt.beginPath();
                      cxt.arc(ball.x, ball.y, ball.r, 0, Math.PI * 2, true);
                      cxt.closePath();
                      cxt.fill();
                      ball.y +=ball.vy * cyc / 1000;    \注:位移是速度对时间的累积。\
        if (ball.r+ball.y >=canvas.height) {
                        ball.vy *=-1;
                      }
        else {
                        ball.vy +=a;    \注:速度是加速度对时间的累积。\
                      }
                      $await(Jscex.Async.sleep(cyc));
                  }
                }))
                moveAsync().start();

耗能的重力场

想象一个弹性铁球,在重力场的作用下,碰撞地面(一部分动能转化为与地面碰撞产生的热能),弹起,碰撞地面,弹起……循环下去,最后静止,其代码实现:

        var canvas=document.getElementById("mycanvas");
        var cxt=canvas.getContext("2d");
        var ball={
                  x: 100,
                  y: 100,
                  r: 15,
                  vx: 0,
                  vy: 0
                };
                cxt.fillStyle="#030303";
                cxt.fillRect(0, 0, canvas.width, canvas.height);
                cxt.fillStyle="#fff";
                cxt.beginPath();
                cxt.arc(ball.x, ball.y, ball.r, 0, Math.PI * 2, true);
                cxt.closePath();
                cxt.fill();
        var hitCount=0 ,cyc=10, a=50;
        var moveAsync2=eval(Jscex.compile("async", function () {
        while (true) {
                        cxt.fillStyle="rgba(0, 0, 0, .3)";
                        cxt.fillRect(0, 0, canvas.width, canvas.height);
                        cxt.fillStyle="#fff";
                        cxt.beginPath();
                        cxt.arc(ball.x, ball.y, ball.r, 0, Math.PI * 2, true);
                        cxt.closePath();
                        cxt.fill();
                        ball.y +=ball.vy * cyc / 1000;
        if (ball.r+ball.y >=canvas.height) {
        if (ball.vy > 0) {
                              ball.vy *=-0.7;    \注:碰撞之后,一部分动能转化为与地面碰撞产生的热能,所以速度降低,方向相反。\
                              hitCount++;
                            }
                        }
        else {
                            ball.vy +=a;
                        }
        if (hitCount > 15) break;
                        $await(Jscex.Async.sleep(cyc));
                  }
                }))

在上面的代码中,假设碰撞之后损失了30%的速度,在真实的物理引擎当中,会为每个碰撞物体设定一个弹性系数,当然复杂一些的物理引擎会为物体的每个面设置一个弹性系数,然后根据接触面的弹性系数,计算出最后的速度大小。