您的位置:首页 > Web前端 > HTML5

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

2014-10-23 12:39 579 查看
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)可以实现同时有多个小球发射,就像游戏里发射子弹的效果
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: