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

javascript+canvas实现Go To The Moon小游戏

2016-12-08 11:55 851 查看
第一次使用这个博客系统,所以还不知道怎么弄,代码一团乱。。。。这个demo70%的自写,30%的算法,但是核心就在算法,所以相当于转载了别人的文章,算法来自《Html+javascript动画核心基础》这本书,很推荐想做web动画的同学看看!

这个demo还有问题没有解决,最后的gameOver回调函数并没有按照预期的设想弹出提示,我改了很久,始终不知道错在哪儿,希望那大大们帮我指出来!谢谢啦!

最后的插入段是js部分!太乱了。。。

Go To The Moon

*{

margin: 0;

padding: 0;

font-family: Magneto;

font-size: 16px;

color: rgb(109,178,255);

}

body{

/background: rgba(59,61,64,0.7);/当渐变不被支持时,这是垫底的背景色*/

background-color: black;

}

h1{

display: block;

font-size: 2rem;

text-align: center;

width: 70%;

margin-left: 15%;

}

#txt{

position: absolute;

top: 50px;

left: 50px;

z-index: 999999;

}

#canvasGame{

/border: 1px solid green;/

position: absolute;

top: 40px;

left: 15px;

}

.moon{

box-shadow:0 0 50px rgba(225,221,200,0.7);

}

Go To The Moon

<script type="text/javascript">
//stars绘制在canvasBg之上,rocket,moon,stone皆绘制在canvasGame之上,
//rocket位置为x/y,stone为sx/sy以示区别
//检查stone和rocket的距离,如果两者collisionTimes=3,则游戏失败
//当rocket与moon距离小于两者半径之和时,游戏完成
var canvasGame=document.getElementById("canvasGame"),
canvasBg=document.getElementById("canvasBg"),
ctxGame=canvasGame.getContext("2d"),
ctxBg=canvasBg.getContext("2d");
//设置canvasBg的宽高为全屏幕
canvasGame.width=window.innerWidth-30;
canvasGame.height=window.innerHeight-50;
canvasBg.width=window.innerWidth-30;
canvasBg.height=window.innerHeight-50;
//rocket对象
//gameOver
var gameGoodOver=function(){
//clearInterval(timeId);
ctxGame.clearRect(0,0,canvasGame.width,canvasGame.height);
//window.cancelAnimationFrame(startGame);
ctxGame.font="60px 微软雅黑 blue";
ctxGame.textAlign="center";
ctxGame.textBaseline="minddle";
ctxGame.fillText("She is gone.....",canvasGame.width/2,canvasGame.height/2);

}
var gameBadOver=function(){
//clearInterval(timeId);
ctxGame.clearRect(0,0,canvasGame.width,canvasGame.height);
//window.cancelAnimationFrame();
ctxGame.font="60px 微软雅黑 blue";
ctxGame.textAlign="center";
ctxGame.textBaseline="minddle";
ctxGame.fillText("U lost urself and her love..",canvasGame.width/2,canvasGame.height/2);
}
//边界检测,rocket/stone碰到边界就弹回来
var checkBorder=function(obj){
var topBorder=0,
bottomBorder=canvasGame.height,
rightBorder=canvasGame.width,
leftBorder=0;
if((obj.x+obj.radius) > rightBorder){
//this.x=canvasGame.width-10;//rocket位置重置
obj.vx *=obj.bounce;//速度向相反方向反弹,同时逐渐减少
//alert("超出右边界");
}
if((obj.x-obj.radius) < leftBorder){
//  this.x=this.radius;
obj.vx *= obj.bounce;
//alert("超出左边界");
}
if((obj.y+obj.radius) > bottomBorder){
//  this.y=canvasGame.height-10;
obj.vy *= obj.bounce;
//alert("超出下边界");
}
if((obj.y-obj.radius) < topBorder){
//  this.y=10;
//alert("超出上边界");
obj.vy *= obj.bounce;
}
}
//碰撞检测,发生弹动
var checkCollision=function(obj1,obj2){
var dx = obj1.x - obj2.x,
dy = obj1.y - obj2.y;
var dist = Math.floor(Math.sqrt( dx*dx + dy*dy )),
minDist = obj1.radius + obj2.radius;
//document.getElementById("txt").innerHTML=distance;
if(dist < minDist){
var angle = Math.atan2(dy,dx);
var tx = obj2.x + Math.cos(angle)*minDist,
ty = obj2.y + Math.sin(angle)*minDist;
sax = (tx - obj1.x) * obj1.spring;
say = (ty - obj1.y) * obj1.spring;
//alert(ax+"/"+ay);
//两球互相相反方向运动
obj1.vx += sax;
obj1.vy += say;
obj2.vx -= sax;
obj2.vy -= say;
}
}
//颜色生成
var makeColor=function(){
var r=Math.floor(Math.random()*256+1);
var g=Math.floor(Math.random()*256+1);//g在r上下五个色素之内
var b=Math.floor(Math.random()*256+1);
var a=Math.random();
var color="rgba("+r+","+g+","+b+","+a+")";
return color;
}
//按键事件,←表示火箭向左转,→表示火箭向右转,↑表示火箭加速(pushPower)
window.addEventListener("keydown",function(event){
//ctx.clearRect(0,0,width,height);
switch(event.keyCode){
case 37:
vr=-3;break;//之所以用3是因为转向角的计算不算快也不会太慢。。。刚合适,试出来的
case 39:
vr=3;break;
case 38:
pushPower=0.1;
rocket.flame=true;
break;
}
},false);
//松开按键之后,停止旋转,rocket加速度停止,旋转加速度也停止
window.addEventListener("keyup",function(){
vr=0;
pushPower=0;
rocket.flame=false;
},false);

var vr=0,//rocket的按键控制属性,vr用来控制旋转的角度
pushPower=0;//rocket推力

var Rocket=function(){
//rocket位置
this.x=0;
this.y=0;
this.vx=0;
this.vy=0;
//vr旋转速度向量,vx水平速度,ax水平加速度,vy竖直速度,ay竖直加速度,pushPower火箭向上的动力速度
//rocket旋转角度
this.rotation=0;
//rocket是否点火,默认没有点火
this.flame=false;
//rocket与border碰撞之后的反弹力
this.bounce=-0.7;
this.radius=15;
}
//绘制rocket
Rocket.prototype.drawRocket=function(ctx){
ctx.save();
//rocket的位置偏移
ctx.translate(this.x,this.y);
ctx.rotate(this.rotation);
ctx.lineWidth=1;
ctx.strokeStyle="white";
ctx.beginPath();
ctx.moveTo(0,0);
ctx.lineTo(-5,-5);
ctx.lineTo(0,-10);
ctx.lineTo(20,0);
ctx.lineTo(0,10);
ctx.lineTo(-5,5);
ctx.lineTo(0,0);
//如果flame为true,则表示此时加速,画出火焰
if(this.flame){
ctx.moveTo(-3,-3);
ctx.lineTo(-8,0);
ctx.lineTo(-3,3);
}
ctx.closePath();
ctx.stroke();
ctx.restore();
}
Rocket.prototype.chekcStone=function(stone){
var collisionTimes=0;
var dx = this.x - stone.x;
var dy = this.y - stone.y;
var dist = Math.sqrt(dx*dx + dy*dy);
var minDist = this.radius + stone.radius;
if(dist < minDist){
collisionTimes++;//碰撞三次之后游戏结束
if(collisionTimes==3){
clearInterval(timeId);
//window.cancelAnimationFrame(gameBadOver);
gameBadOver();
}
}
}
//绘制小行星
//star对象
var Star=function(){
this.x=Math.floor(Math.random()*canvasBg.width+1);
this.y=Math.floor(Math.random()*canvasBg.height+1);
}
Star.prototype.drawStar=function(ctx,color){
ctx.save();
ctx.fillStyle=color;
ctx.lineWidth=1;
ctx.beginPath();
//ctx.arc(this.x,this.y,5,0,Math.PI*2,false);
ctx.moveTo(this.x-2,this.y-2);
ctx.lineTo(this.x,this.y-5);
ctx.lineTo(this.x+2,this.y-2);
ctx.lineTo(this.x+5,this.y);
ctx.lineTo(this.x+2,this.y+1);
ctx.lineTo(this.x+3,this.y+3);
ctx.lineTo(this.x,this.y+2);
ctx.lineTo(this.x-3,this.y+3);
ctx.lineTo(this.x-2,this.y+1);
ctx.lineTo(this.x-5,this.y);
ctx.lineTo(this.x-2,this.y-2);
//ctx.closePath();
//ctx.stroke();
ctx.fill();
ctx.restore();
}
//border和star的碰撞检测,与rocket的检测
var stars=[];//存放star
var starNum=Math.floor(Math.random()*150+100);//star最少有100个,最多有250个
for(var star , i = 0 ; i < starNum ; i++ ){
star=new Star();
//star.id="star"+i;
star.x=Math.floor(Math.random()*canvasBg.width+1);
star.y=Math.floor(Math.random()*canvasBg.height+1);
stars.push(star);
}
for(var i=0;i<stars.length;i++){
stars[i].drawStar(ctxBg,makeColor());
}
//stone陨石,从左至右,从右至左
var Stone=function(){
this.color="gray";//"rgb(86,84,73)";垫底色
this.x=0;
this.y=0;
this.vx=0;
this.vy=0;
this.radius=0;
this.bounce=-0.9;//边界反弹力
this.spring=0.03;//两球碰撞反弹力
}
Stone.prototype.drawStone=function(ctx){
ctx.save();
ctx.fillStyle=this.color;
ctx.shadowColor="gray";
ctx.shadowBlur=this.radius/2;
ctx.beginPath();
ctx.arc(this.x,this.y,this.radius,0,Math.PI*2,false);
ctx.fill();
ctx.restore();
}
var stones = [];
var stoneNum = 10;//Math.floor(Math.random()*15);
for(var stone,i = 0 ; i < stoneNum ; i++){
stone = new Stone();
stone.x = Math.random()*(canvasGame.width-100)+20;
stone.y = Math.random()*(canvasGame.height-100)+20;
stone.vx = Math.random()*1-0.5;
stone.vy = Math.random()*1-0.5;
stone.radius = Math.floor(Math.random()*10+2);
stone.color = makeColor();
//stone.rotation=Math.atan2(vx,vy);
stones.push(stone);

}
//调用drawStone绘制stone
var stoneMove=function(stone){
stone.x += stone.vx;
stone.y += stone.vy;
checkBorder(stone);//检查边界,碰撞反弹
stone.drawStone(ctxGame);
}
var showStone=function(){
//window.requestAnimationFrame(showStone);
ctxGame.clearRect(0,0,canvasGame.width,canvasGame.height);
//碰撞检测
for(var i=0;i<stones.length;i++){
stoneMove(stones[i]);
}
//showStone();
};
//moon
var moon=new Stone();
moon.color="rgb(122,114,48)";
moon.x=canvasGame.width-50;
moon.y=50;
moon.vy=0;
moon.vx=0;
moon.radius=100;
moon.color=makeColor();
//moon.drawStone(ctxGame);
//rocket
var rocket=new Rocket();
rocket.x=100;
rocket.y=canvasGame.height-100;
rocket.drawRocket(ctxGame);
var timeId=null;
var startGame=function(){
//window.requestAnimationFrame(startGame);
clearInterval(timeId);
timeId=setInterval(function(){
ctxGame.clearRect(0,0,canvasGame.width,canvasGame.height);
//绘制stone
//showStone();
//碰撞检查
for(var i=0 ; i < stones.length ; i++){
//var obj1=stones[i];
//stone和moon相碰。。
for(var j=i+1;j<stones.length; j++){
//var obj2=stones[j];
checkCollision(stones[i],moon);
checkCollision(stones[i],rocket);
rocket.chekcStone(stones[i]);
checkCollision(stones[i],stones[j]);
checkCollision(stones[j],moon);
checkCollision(stones[j],rocket);
rocket.chekcStone(stones[j]);
showStone();
}
}
//rocket旋转角度,角度值
rocket.rotation += (vr*Math.PI/180);
var angle=rocket.rotation;
//水平加速度
rocket.ax=Math.cos(angle)*pushPower;
//竖直加速度
rocket.ay=Math.sin(angle)*pushPower;
//alert(ax+":"+ay);
//速度等于加速度加上之前的速度
rocket.vx += rocket.ax;
rocket.vy += rocket.ay;
//位置等于现在位置加上速度
rocket.x += rocket.vx;
rocket.y += rocket.vy;
checkBorder(rocket);
//检查rocket与moon位置,接触则游戏完成
if(Math.sqrt((rocket.x - moon.x)*(rocket.x - moon.x)+(rocket.y - moon.y)*(rocket.y - moon.y)) < moon.radius){
//window.cancelAnimationFrame(gameGoodOver);
clearInterval(timeId);
gameGoodOver();
}
//document.getElementById("txt").innerHTML="rocket.rotation:"+rocket.x+":"+rocket.y;
rocket.drawRocket(ctxGame);
//startGame();
//绘制moon
moon.drawStone(ctxGame);
//startGame();
},1000/60)
};
startGame();
</script>
</html>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  javascript canvas html5