html5仿大炮炮弹的自由落体实现
html5的魅力相信大家不会陌生,希望各位大大浏览器们早点支持这个特性哦,,还有先吐槽一句,微信的那个broser简直弱爆了就简单的动画,比如滑动,就jquery的show(1000),hide(1000)都卡的不行,还是qq浏览器的内核,qq浏览器,,,算了,,我先冷静下。。。。
还有就是前几天看到的这个!!!
都不支持要他干嘛?????
回归主题大炮
整体思路就是将每个打出来的炮弹看做一个对象,他的x,y转换成canvas的x,y,其中vecior就是个控制力度的一个选项后文会提到。
var cannonBall = function (x,y,vector){ var gravity=0,
that={ x: x, y: y, removeMe:false, move: function (){
vector.vy += gravity;
gravity += 0.1; //模拟加速度
that.x+=vector.vx;
that.y+=vector.vy; if(that.y > canvas.height -150){
that.removeMe=true;
}
}, draw: function (){
ctx.beginPath();
ctx.arc(that.x,that.y,5,0,Math.PI * 2);
ctx.fill();
ctx.closePath();
}
};其中大炮炮弹的对象势必涉及到了向量计算,自己封装了个个方法,,有现成的Vector.js,但觉得太重(对于我们后端每次前端说不用模板,说太重,我们心里都默想重你妹呀,,哈哈哈),很简单,实现简单功能可以,大型游戏强烈建议使用现成的。
var vector2d= function (x,y){ var vec={ vx:x, vy:y, scale: function (scale){
vec.vx*=scale;
vec.vy*=scale;
}, add:function (vec2){
vec.vx+=vec2.vx;
vec.vy+=vec2.vy;
}, sub:function (vec2){
vec.vx-=vec2.vx;
vec.vy-=vec2.vy;
}, negate: function(){
vec.vx=-vec.vx;
vec.vy=-vec.vy;
}, length:function (){ return Math.sqrt(vec.vx * vec.vx + vec.vy * vec.vy);
}, normalize:function (){ var len=this.length(); if(len){
vec.vx /=len;
vec.vy /=len;
} return len;
}, rotate:function (angle){ var vx = vec.vx; var vy = vec.vy;
vec.vx = vx * Math.cos(angle) - vy * Math.sin(angle)
vec.vy = vx * Math.sin(angle) + vy * Math.cos(angle);
}, toString:function(){ return '(' + vec.vx.toFixed(3) + ',' + vec.vy.toFixed(3) + ')' ;
}
}; return vec;
};好了,接着就是个计算角度再加上setInterval了,,其他没啥说的,这里我着重说下canvas.save();和canvas.restore();这里稍微解释一下,
当我们对画布进行旋转,缩放,平移等操作的时候其实我们是想对特定的元素进行操作,比如图片,一个矩形等,但是当你用canvas的方法来进行这些操作的时候,其实是对整个画布进行了操作,那么之后在画布上的元素都会受到影响,所以我们在操作之前调用canvas.save()来保存画布当前的状态,当操作之后取出之前保存过的状态,这样就不会对其他的元素进行影响
全部代码
<!doctype html><html lang="en"><head>
<meta charset="UTF-8">
<meta author='gongbangwei'>
<title>大炮</title></head><body>
<div id='lidu'>
<span>选择大炮的</span>
<input type="radio" checked='checked' value='25'>大 <input type="radio" value='20'>中 <input type="radio" value='15'>小 </div>
<canvas id='can' width="640" height="480" >no support html5</canvas>
<script src='vector2d.js'></script>
<script src='jquery/jquery-1.7.2.min.js'></script>
<script>
var gameObj=[],
canvas=document.getElementById('can'),
ctx=canvas.getContext('2d'); var cannonBall = function (x,y,vector){ var gravity=0,
that={ x: x, y: y, removeMe:false, move: function (){
vector.vy += gravity;
gravity += 0.1; //模拟加速度
that.x+=vector.vx;
that.y+=vector.vy; if(that.y > canvas.height -150){
that.removeMe=true;
}
}, draw: function (){
ctx.beginPath();
ctx.arc(that.x,that.y,8,0,Math.PI * 2);
ctx.fill();
ctx.closePath();
}
};
return that;
} var cannon= function (x,y,lidu){ var mx=0,
my=0,
angle=0,
that={ x: x, y: y, lidu:lidu, angle:0, removeMe:false, move:function (){
angle=Math.atan2(my-that.y,mx-that.x);
}, draw:function(){
ctx.save();
ctx.lineWidth=2;
ctx.translate(that.x,that.y); //平移,将画布的坐标原点向左右方向移动x,向上下方向移动y.canvas的默认位置是在(0,0)
ctx.rotate(angle); //画布旋转
ctx.strokeRect(0,-5,50,10);
ctx.moveTo(0,0);
ctx.beginPath();
ctx.arc(0,0,15,0,Math.PI * 2 );
ctx.fill();
ctx.closePath();
ctx.restore();
}
};//end that
canvas.onmousedown = function(){ //在这里调用向量的那个js
var vec = vector2d(mx-that.x,my-that.y);
vec.normalize(); //console.log(lidu);
vec.scale(lidu);
gameObj.push(cannonBall(that.x,that.y,vec));
}
canvas.onmousemove = function (event){ var bb= canvas.getBoundingClientRect();
mx=(event.clientX - bb.left);
my=(event.clientY - bb.top);
}; return that;
}; //画蓝田和草地
var drawSkyAndGrass = function (){
ctx.save();
ctx.globalAlpha= 0.4; var linGrad=ctx.createLinearGradient(0,0,0,canvas.height);
linGrad.addColorStop(0,'#00BFFF');
linGrad.addColorStop(0.5,'white');
linGrad.addColorStop(0.5,'#55dd00');
linGrad.addColorStop(1,'white');
ctx.fillStyle=linGrad;
ctx.fillRect(0,0,canvas.width, canvas.height);
ctx.restore();
} ///////main/////////////
var lidu=$('#lidu').find("input:checked").val();
gameObj.push(cannon(50,canvas.height-150,lidu));
$('#lidu').click(function (event){ var cl=event.target;
$(this).find('input').each(function(){
$(this).attr('checked',false)
});
$(cl).attr('checked',true);
lidu=$(cl).val();
gameObj.splice(0,gameObj.length);
gameObj.push(cannon(50,canvas.height-150,lidu));
})
setInterval( function (){
drawSkyAndGrass(); var gameObj_fresh=[]; for (var i = 0; i < gameObj.length; i++) {
gameObj[i].move();
gameObj[i].draw(); if(gameObj[i].removeMe === false){
gameObj_fresh.push(gameObj[i]);
}
}
gameObj=gameObj_fresh;
},50); </script></body></html>结束语
一个真正的前端绝不是ui,一个前端游戏工程师也绝对是个数学家。
作者:michaelgbw
链接:https://www.jianshu.com/p/0275332a894b