首页 > 代码库 > 【整理】HTML5游戏开发学习笔记(3)- 抛物线运动

【整理】HTML5游戏开发学习笔记(3)- 抛物线运动

1.预备知识
(1)Canvas旋转的实现过程

			window.onload = function(){								var ctx = document.getElementById(‘canvas1‘).getContext(‘2d‘)				//旋转				ctx.save()				ctx.translate(200,200)//把(200,200)点作为临时的(0,0)点				ctx.rotate(30*Math.PI/180)//顺时针旋转30度所对应的弧度				ctx.fillRect(0,0,100,150)				ctx.restore()			}


(2)抛物线运动中的重力加速度的模拟实现模型

			/*				抛物线运动				这个版本做了修改,为了减少一次角度和弧度之间的转换计算(通过Math.atan2可以直接算出弧度),				构造参数中的角度改成了弧度				deleted:				angle = angle,								//初始角度				radians = angle*Math.PI/180,	//初始弧度				object ParabolicMotion					@velocity:初始速度					@radians:初始弧度					@gravity:初始加速度{x:0,y:2}			*/			function ParabolicMotion(velocity,radians,gravity){				var velocity = velocity, 						radians = radians, 						gravity = gravity	 				var offsetX = velocity*Math.cos(radians),						offsetY = -velocity*Math.sin(radians)				function next(offset,gravity){					var offset1 = offset					var offset2 = offset+gravity					return {offset:offset2,dv:(offset1+offset2)*.5}				}				return {					/*						获取运动轨迹到下一个时间点,x,y轴所偏移的距离					*/					moveNext : function(){						var offsetXD = next(offsetX,gravity.x)						var offsetYD = next(offsetY,gravity.y)												offsetX = offsetXD.offset						offsetY = offsetYD.offset						//console.log(offsetX+‘,‘+offsetY)												return {x:offsetXD.dv,y:offsetYD.dv}					}				}			}

 


2.实现思路
涉及的对象,包括球(Ball),弹弓(Slingshot),抛物线运动(ParabolicMotion)。
操作过程是,鼠标键按下拖拽小球,和弹弓的作用点成一定的角度,鼠标键按起后,小球做抛物线运动

3.主要代码

			/*弹弓*/			function Slingshot(){				var opts,						ctx,						crtBall,						ballSelected = false				function refresh(){					ctx.clearRect(0,0,opts.width,opts.height)					drawSling()					crtBall.draw()									}				function drawSling(){					var point = opts.actionPoint					ctx.beginPath()					ctx.moveTo(point.x,point.y)					ctx.lineTo(point.x,opts.height)					ctx.closePath()					ctx.stroke()					if(crtBall!=null&&ballSelected){						//绘制连接球和弹弓的"橡皮筋"						ctx.beginPath()						ctx.moveTo(point.x,point.y)						ctx.lineTo(crtBall.x,crtBall.y)						ctx.closePath()						ctx.stroke()					}				}				function isBallSelected(offsetX,offsetY){					var point = opts.actionPoint					var a = Math.abs(point.x-offsetX)					var b = Math.abs(point.y-offsetY)					//var c = Math.sqrt(a*a+b*b)					return (a*a+b*b)<=crtBall.radius*crtBall.radius				}				// 添加拉弹弓事件				function initEvents(){						var canvas = opts.canvas						/*							addEventListener函数的第3个参数,							false表示内层元素事件先触发,ture则表示外层的事件先触发														alert(e.offsetX+‘,‘+e.offsetY)							必须使用offsetX,offsetX是相对于canvas画布的距离(但firefox不支持)							事件参数e没有考虑浏览器兼容问题						*/						canvas.addEventListener(‘mousedown‘,function(e){																					// 判断球是否被选中							ballSelected = isBallSelected(e.offsetX,e.offsetY)														if(ballSelected){								crtBall.locate(e.offsetX,e.offsetY)								refresh()															}						},false)						canvas.addEventListener(‘mousemove‘,function(e){							if(ballSelected){								crtBall.locate(e.offsetX,e.offsetY)								refresh()							}						},false)						canvas.addEventListener(‘mouseup‘,function(e){							if(ballSelected){								ballSelected = false								crtBall.locate(e.offsetX,e.offsetY)								refresh()											//发射炮弹								fire(function(x,y){									//TODO 判断是否打中目标								})															}						},false)				}				function fire(onCompleted){					// 获取当前的炮弹发射速度和弧度					var velocity = ($.square(opts.actionPoint.y-crtBall.y)+$.square(opts.actionPoint.x-crtBall.x))/100					var radians = -Math.atan2(opts.actionPoint.y-crtBall.y,opts.actionPoint.x-crtBall.x)//30*Math.PI/180					var gravity = {x:0,y:2}					var parabolicMotion = new ParabolicMotion(velocity,radians,gravity)					var completed = false					var timer =	setInterval(function(){						// 在当前抛物线轨迹下,获取炮弹下一次单位时间内x,y轴需要偏移的单位长度						var offset = parabolicMotion.moveNext()						crtBall.move(offset.x,offset.y)						refresh()												// 检查是否超出画布边界						completed = (crtBall.x>=opts.width||crtBall.y>=opts.height)						if(completed){							clearInterval(timer)							if(typeof onCompleted==‘function‘){								onCompleted(crtBall.x,crtBall.y)							}									}										},100)									}				return {					init : function(options){						opts = $.extend(options,{							canvas : null,//画布							width : 1000,//画布长							height : 300,//画布高							actionPoint : {x:150,y:200}/*作用力点坐标*/						})						ctx = opts.canvas.getContext(‘2d‘)						drawSling()						// 添加拉弹弓事件						initEvents()						return this					},					loadBall : function(ball){						var point = opts.actionPoint						crtBall = ball.init({ctx:ctx,x:point.x,y:point.y})													.draw()							return this					}				}			}

 

			// app						window.onload = function(){								var canvas = document.getElementById(‘canvas1‘)				var ball = new Ball(10)				var slingshot = new Slingshot().init({canvas:canvas})							// 装载一个炮弹				slingshot.loadBall(ball)			}

 



4.优化和完善
(1)需实现球打中目标物体后,目标物体进行旋转
(2)可以实现同时有多个小球发射,就像游戏里发射子弹的效果

【整理】HTML5游戏开发学习笔记(3)- 抛物线运动