Canvas绘制曲线

转自:http://blessdyb.iteye.com/blog/1399090

2.游戏中的数学知识

  在游戏的开发中,数学知识特别是其中的三角函数使用特别广泛

2.1 角度

       在使用canvas来制作动画的过程中,我们使用到的角度都是以弧度为单位的,角度与弧度之间的换算单位如下:

Js代码   收藏代码
  1. radians=degrees*Math.PI/180  

 

同时,在canvas中的坐标系是以右上角为原点(0,0),向左为x轴增加方向,向下为y轴增加方向。因此,需要特别注意canvas中角度是以顺时针为方向的,这与我们在生活中角度为逆时针相反。如下图:


在三角函数中,最常用的有三个,Math.cos,Math.sin与Math.atan2,注意计算反正切的有两个函数Math.atan与Math.atan2,后者需要传入对边dy与邻边dx来求得精确的角度(在[-180,180]中正切值相同的角度会有两个)。如下:



 可以看出,对D角使用Math.atan2来得到的值将为-153.43。因此,如果我们需要求得任意一点P(x,y)与原点连线的角度,使用Math.atan2(y,x)即可。

2.2 旋转

      在游戏开发中,我们经常会碰到对于画布中对象的旋转,即使用到context.rotate方法,而其角度大多数情况下通过上述的Math.atan2(dy,dx)获得。计算一个动点与一个静点之间的实时角度,假设静点为originX,originY,动点为x,y.  则

Js代码   收藏代码
  1. α=Math.atan2(y-originY,x-originX)  

 

如果给静点的rotation方法传入α后重绘,就会出现实时地让静点指向动点。如下即为一个随着鼠标移动而随时指向鼠标的箭头实现。

Java代码   收藏代码
  1. //箭头类  
  2. function Arrow(){  
  3.         //定义位置属性  
  4.     this.x=0;  
  5.     this.y=0;  
  6.         //定义旋转角度及缩放  
  7.     this.rotation=0;  
  8.     this.scaleX=1;  
  9.     this.scaleY=1;  
  10.         //定义填充色及画笔宽度  
  11.     this.color='#00ff00';  
  12.     this.lineWidth=1;  
  13. }  
  14. //绘制方法  
  15. Arrow.prototype.paint=function(context){  
  16.         //保存场景  
  17.     context.save();  
  18.         //坐标系转换,缩放及旋转  
  19.     context.translate(this.x,this.y);  
  20.     context.scale(this.scaleX,this.scaleY);  
  21.     context.rotate(this.rotation);  
  22.         //定义填充色及画笔  
  23.     context.fillStyle=this.color;  
  24.     context.lineWidth=1;  
  25.         //绘制箭头  
  26.     context.beginPath();  
  27.     context.moveTo(-50,-25);  
  28.     context.lineTo(0,-25);  
  29.     context.lineTo(0,-50);  
  30.     context.lineTo(50,0);  
  31.     context.lineTo(0,50);  
  32.     context.lineTo(0,25);  
  33.     context.lineTo(-50,25);  
  34.     context.closePath();  
  35.         //填充  
  36.     context.fill();  
  37.     if(context.lineWidth>0){  
  38.         context.stroke();  
  39.     }  
  40.     context.restore();  
  41. }  

 

2.3 波动

    正弦与余弦的曲线都是一条规律性的波动曲线,游戏中很多对象的往复运动就是按正余弦规律来进行的。使用canvas我们很容易就能绘制出一条正弦曲线。如下:

 

Js代码   收藏代码
  1. //绘制Sin曲线,给定起始点坐标及波动高与宽  
  2. function getSinWave(context,x,y,width,height){  
  3.     context.save();  
  4.     context.translate(x,y);  
  5.     context.beginPath();  
  6.     for(var i=0;i<360;i+=0.1){   context.lineTo(i*width,Math.sin(i*width*Math.PI/180)*height);  
  7.     context.stroke();  
  8.     context.restore();  
  9. }  
  10.    

 弹簧振子往复运动 
        对于物理学中的弹簧振子来说,其在一个坐标轴中的运动就是正余弦曲线在Y轴上的投影。如下为一个小球的运动。

Js代码   收藏代码
  1. //小球类,给定半径及填充色  
  2. function Ball(radius,color){  
  3.         //设置球心及缩放,边缘线宽  
  4.     this.x=0;  
  5.     this.y=0;  
  6.     this.radius=radius||20;  
  7.     this.color=color||'#ffff00';  
  8.     this.scaleX=1;  
  9.     this.scaleY=1;  
  10.     this.lineWidth=1;  
  11. }  
  12. //定义绘制方法  
  13. Ball.prototype.paint=function(context){  
  14.     context.save();  
  15.         //坐标转换  
  16.     context.translate(this.x,this.y);  
  17.     context.scale(this.scaleX,this.scaleY);  
  18.     context.fillStyle=this.color;  
  19.     context.lineWidth=this.lineWidth;  
  20.     context.beginPath();  
  21.         //绘制球  
  22.     context.arc(0,0,this.radius,0,Math.PI*2,true);  
  23.     context.closePath();  
  24.     context.fill();  
  25.     if(context.lineWidth>0){  
  26.         context.stroke();  
  27.     }  
  28.     context.restore();  
  29. };  

 如下为具体的呈现HTML文档,在utils.js中定义了window.requestAnimFrame的实现类(详见分享一).

Html代码   收藏代码
  1. <!DOCTYPE html>  
  2. <html>  
  3.     <head>  
  4.         <meta charset="utf-8" />  
  5.         <title>Ball</title>  
  6.     </head>  
  7.     <body>  
  8.         <canvas id="canvas" width="400" height="400"></canvas>  
  9.         <script type="text/javascript" src="utils.js"></script>  
  10.         <script type="text/javascript" src="ball.js"></script>  
  11.         <script type="text/javascript">  
  12.             window.onload=function(){  
  13.                                //获取canvas标签引用及canvas绘图上下文context  
  14.                                 var canvas=document.getElementById("canvas");  
  15.                 var context=canvas.getContext("2d");  
  16.                                //实例化小球  
  17.                 var ball=new Ball();  
  18.                 ball.x=canvas.width/2;  
  19.                 ball.y=canvas.height/2;  
  20.                                 //初始化角度及角度增加系数  
  21.                 var angle=0;  
  22.                 var vr=1*Math.PI/180;  
  23.                 (function animationLoop(){  
  24.                     window.requestAnimFrame(animationLoop,canvas);  
  25.                     context.clearRect(0,0,canvas.width,canvas.height);  
  26.                                         //以60帧的速度来绘制弹簧振子小球的运动  
  27.                     ball.x=canvas.width/2*(1-Math.cos(angle));  
  28.                     angle+=vr;  
  29.                     ball.paint(context);  
  30.                 })();  
  31.             };  
  32.         </script>  
  33.     </body>  
  34. </html>  

 

线性垂直波动

    如果给以正余弦方式垂直运动的对象加上一个横向的线速度,那就会动态地绘制出一个正余弦曲线。我们为ball添加vx,vy属性。

Js代码   收藏代码
  1. (function aniamtionLoop(){  
  2.     window.requestAnimation(animationLoop,canvas);  
  3.     context.clearRect(0,0,canvas.width,canvas.height);  
  4.     ball.x+=ball.vx;  
  5.     angle+=ball.vy*Math.PI/180;  
  6.     ball.y=Math.cos(angle)*canvas.height/2;  
  7.     ball.paint(context);  
  8. })();  

 脉冲效果 
        除了为对象在X与Y轴方向上添加正余弦变化的速度外,也可以为对象的其它属性,    如尺寸添加一个按正弦变化的值,这将会产生一种脉冲效果。

Js代码   收藏代码
  1. ball.scaleX=ball.scaleY=Math.PI*angle/180;  

 此处使用的是同一个变化量,其实也可以为不同的属性指定不同的角度。

 

圆周运动 
       对一个圆周上运动的对象来说,其任意时刻在圆周上的位置可以使用半径与三角函数来表示。即P(x,y)=P(r1*cosα,r2*sinα)。如果r1=r2,则运动对象的轨迹为一个正圆,否则其轨迹为一个椭圆。

Js代码   收藏代码
  1. ball.x=canvas.width/2+Math.cos(angle)*radiusX;  
  2. ball.y=canvas.height/2+Math.sin(angle)*radiusY;  

三角函数在动画中计算坐标,最常见的一定是使用余弦Math.cos来计算横坐标x,使用正弦Math.sin来计算纵坐标y。

 

勾股定理及距离计算

       距离的计算相当常见,我们只需要在坐标系中使用勾股定理,即A(x0,y0)到B(x1,y1)之间的距离为

Js代码   收藏代码
  1. var dx=B.x-A.x;  
  2. var dy=B.y-A.y;  
  3. var distance=Math.sqrt(dx*dx+dy*dy);  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值