標籤:blog io os ar 使用 java sp div on
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 = offsetvar offset2 = offset+gravityreturn {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.offsetoffsetY = 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 = falsefunction refresh(){ctx.clearRect(0,0,opts.width,opts.height)drawSling()crtBall.draw()}function drawSling(){var point = opts.actionPointctx.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.actionPointvar 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 = falsecrtBall.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))/100var radians = -Math.atan2(opts.actionPoint.y-crtBall.y,opts.actionPoint.x-crtBall.x)//30*Math.PI/180var gravity = {x:0,y:2}var parabolicMotion = new ParabolicMotion(velocity,radians,gravity)var completed = falsevar 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.actionPointcrtBall = ball.init({ctx:ctx,x:point.x,y:point.y}).draw()return this}}}
// appwindow.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)- 拋物線運動