4.2 加速度
加速度是改变速度大小及方向的一个属性,在物体受力的过程中,会产生加速度来改变速度的大小及方向。加速度的处理与速度的处理非常类似。
一维坐标系统下的加速度
一维坐标系统下加速度的实现很简单,我们仍然使用小球系统来模拟,为小球对象添加X轴与Y轴上的加速度属性。实现起来有两步:初始化加速度值,在每一帧开始时为速度增加加速度的值。如下:
ball.ax=INITIAL_ACCELERATE_VELOCITY; ball.vx+=ball.ax; //将此句放置于animationLoop中
二维坐标系统下的加速度
与二维坐标系统下的速度处理方式相同,二维坐标系统下的加速度处理如下:
ball.ax=INITIAL_ACCELERATE_VELOCITY_X; ball.ay=INITIAL_ACCELERATE_VELOCITY_Y; ball.vx+=ax; //将此两句放置于animationLoop中 ball.vy+=ay;
重力加速度
重力加速度是一种特殊的加速度。对其的处理可以当作一维坐标(Y轴)系统下的加速度来处理:
ball.vy+=gravity; //gravity是重力加速度常量
已知初始方向及大小的加速度
前面我们实现的都是已知两个正交坐标轴方向加速度大小的运动,但在实际应用中,这种情况很少见,更多的是已知加速度的大小及方向的运动。此时,我们就需要使用之前介绍的三角函数。常见的变换如下:
ax=Math.cos(angle)*A; ay=Math.sin(angle)*A;
我们对之前在速度处理中实现的鼠标跟随效果进行改进,在其中引入加速度处理,核心代码实现如下:
window.οnlοad=function(){ //初始化变量 var canvas=document.getElementById("canvas"); var context=canvas.getContext("2d"); var mouse=utils.captureMousePosition(canvas); var accelerateSpeed=1; //绘制箭头 var arrow=new Arrow(); arrow.x=canvas.width/2; arrow.y=canvas.height/2; (function animationLoop(){ window.requestAnimFrame(animationLoop,canvas); context.clearRect(0,0,canvas.width,canvas.height); //取得由箭头中心指向鼠标位置的向量方向,并旋转箭头 var dx=mouse.x-arrow.x; var dy=mouse.y-arrow.y; var angle=Math.atan2(dy,dx); arrow.rotation=angle; //通过三角函数求得加速度,并对应改变速度及位置 arrow.vx+=Math.cos(angle)*accelerateSpeed; arrow.vy+=Math.sin(angle)*accelerateSpeed; arrow.x+=arrow.vx; arrow.y+=arrow.vy; arrow.paint(context); })(); };
运行代码,会发现效果很像一个水平摆。
加速度实例——宇宙飞船
加速度一个很好的实例就是飞船的起飞和降落。我们会逐渐实现一个简易的飞船。如下,是一个用三角形构成的飞船模型:
function Ship(){ //定义飞船属性 this.x=0; this.y=0; this.vx=0; this.vy=0; this.rotation=0; this.width=25; this.height=20; this.showFlame=false; } Ship.prototype.paint=function(context){ context.save(); //定义画面属性 context.translate(this.x,this.y); context.rotate(this.rotation); context.lineWidth=1; context.strokeStyle='#ffffff'; //绘制飞船 context.beginPath(); context.moveTo(10,0); context.lineTo(-10,10); context.lineTo(-5, 0); context.lineTo(-10, -10); context.lineTo(10, 0); context.stroke(); //绘制喷火 if(this.showFlame){ context.beginPath(); context.moveTo(-7.5, -5); context.lineTo(-15, 0); context.lineTo(-7.5, 5); context.stroke(); } context.restore(); };
以上代码实现了一个简单的飞船模型,飞船在加速时会喷火,如下图:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>Arrow</title> <style type="text/css"> #canvas { border-bottom: 1px solid #ffffff; background-color: #000000; } </style> </head> <body> <canvas id="canvas" width="400" height="400"></canvas> <script type="text/javascript" src="utils.js"></script> <script type="text/javascript" src="ship.js"></script> <script type="text/javascript"> window.οnlοad=function(){ var canvas=document.getElementById("canvas"); var context=canvas.getContext("2d"); var ship=new Ship(); ship.x=canvas.width/2; ship.y=canvas.height/2; var vr=0; var f=0; //处理键盘事件 window.addEventListener("keydown",function(event){ console.log(event.keyCode); switch(event.keyCode){ case 37: //左,逆时针转 vr=-3; break; case 39: //右,顺时针转 vr=3; break; case 38: //上,加速 f=0.05; ship.showFlame=true; break; } }); //按键松开时恢复相关属性为默认值 window.addEventListener("keyup",function(event){ ship.showFlame=false; vr=0; f=0; },false); (function animationLoop(){ window.requestAnimFrame(animationLoop,canvas); context.clearRect(0,0,canvas.width,canvas.height); //通过角度和大小来确定加速度,从而确定飞船的速度与位置 ship.rotation+=vr*Math.PI/180; ship.vx+=Math.cos(ship.rotation)*f; ship.vy+=Math.sin(ship.rotation)*f; ship.x+=ship.vx; ship.y+=ship.vy; ship.paint(context); })(); }; </script> </body> </html>
如此,实现了一个利用加速度的飞船模型,左右箭头是用来控制旋转方向的,上箭头是用来加速的。但很快飞船就跑出画布了,之后我们会介绍如何来进行边界控制。