用canvas,javascript制作"坦克大战"小游戏(1)

标签: 坦克大战  canvas  javascript

游戏简介

如题目所示,这是一个坦克大战的游戏,但是只是完成了一部分。目前的进度是玩家可以控制自己的坦克移动,攻击。敌方坦克我还没写,因为我还没有想好要怎么写敌方坦克的AI(手动滑稽)。所以就把整个小游戏拆成两部分了,一个是玩家坦克的功能,另一个是敌方坦克的功能。不过仅仅是写玩家对坦克的控制,也写了近300行的代码…(没办法,菜是原罪)

游戏截图

这个是目前游戏做出来的效果:

在这里插入图片描述
用到的图片资源:
在这里插入图片描述
这里把所有的坦克动画所需的图片,地形图片等放在了一张图中,使用的时候就可以通过截取一部分来使用。

游戏代码

话不多说,放码过来,下面就是整个游戏目前的代码,有什么建议或者不懂的可以评论,反正我现在也正好在学html的canvas和javascript。

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>坦克大战(1</title>
<script src="modernizr.js"></script>
<script type="text/javascript">
//当网页加载完毕后运行js代码
window.addEventListener('load', eventWindowLoaded, false);	
//运行canvasApp()函数
function eventWindowLoaded() {
	canvasApp();
}
function canvasSupport () {
  	return Modernizr.canvas;
}
function canvasApp(){
	if (!canvasSupport()) {
			 return;
  	}else{
	    var theCanvas = document.getElementById('canvas');	//将变量theCanvas与画布绑定
	    var context = theCanvas.getContext('2d');		//将变量context作为画布内容
	}
	var tileSheet=new Image();		//创建图片对象
	tileSheet.addEventListener('load', eventSheetLoaded , false);
	tileSheet.src="tanks_sheet.png";
	
	//地图属性
	var mapRows=10;
	var mapCols=10;
	var tileMap=[[32,31,31,31,1,31,31,31,31,32],
				 [1,1,1,1,1,1,1,1,1,1],
				 [32,1,1,26,1,1,1,26,1,32],
				 [32,1,26,26,26,1,26,26,1,32],
				 [32,1,1,26,1,1,1,1,1,32],
				 [32,1,1,1,1,1,26,26,1,32],
				 [32,1,26,1,26,1,26,1,1,32],
				 [1,1,26,1,26,1,1,1,1,1],
				 [32,1,1,1,1,1,1,1,1,32],
				 [32,31,31,31,1,31,31,31,31,32]];
				 
	//与坦克动画相关
	var animationFrames=[1,2,3,4,5,6,7,8];		//用来存储坦克移动动画的8张图片的下标
	var frameIndex=0;
	var tankImages=[[]];
	//与坦克属性有关,包括坐标,方向,是否移动
	var x=0;		//当前x坐标
	var y=32;		//当前y坐标
	var dx=4;		//x方向上的移动速度
	var dy=0;		//y方向上的移动速度
	var count=0;	//用于记录坦克动画执行的次数,到8后会清0,0代表着未执行动画,即没有移动
	var direction="right";		//当前方向
	var rotation=90;		//旋转角度
	var moveflag=false;		//是否移动
	
	//与子弹动画相关
	var bullets=[];		//用于存储子弹对象的数组
	//与子弹属性有关,如子弹的方向,飞行速度
	function Bullet(rotation,x,y,xspeed,yspeed,checkFlag){
		this.rotation=rotation;
		this.x=x;
		this.y=y;
		this.xspeed=xspeed;
		this.yspeed=yspeed;
		this.checkFlag=checkFlag;		//子弹是否碰撞的标志
	}
	
	//与爆炸动画有关
	var booms=[];
	//爆炸点的属性,主要是坐标值,爆炸动画由三张图片组成,需要记录当前帧播放的是哪张图片
	function Boom(x,y){
		this.x=x;
		this.y=y;
		this.nowpic=1;
	}
	
	//与游戏结束相关
	var gameover=false;		//游戏结束的标志
	var tt;			//运行动画的函数
	
	function eventSheetLoaded() {
		tt=setInterval(drawScreen, 50);
		window.addEventListener("keydown",changeDirection,true);	//添加键盘监听事件(键盘按下)——用于改变坦克运动方向
		window.addEventListener("keyup",createBullet,true);		//添加键盘监听事件(键盘松开)——用于产生子弹
	}
	
	function drawScreen() {
		//绘制背景
		context.fillStyle="#aaaaaa";
		context.fillRect(0,0,320,320);
		//绘制地图
		for(var rowCtr=0;rowCtr<mapRows;rowCtr++) { 
			for(var colCtr=0;colCtr<mapCols;colCtr++){ 
				var tileId = tileMap[rowCtr][colCtr]-1;
				var sourceX = Math.floor(tileId % 8) *32;
				var sourceY = Math.floor(tileId / 8) *32;
				context.drawImage(tileSheet, sourceX,sourceY,32,32,colCtr*32,rowCtr*32,32,32);
			} 
		}
		//玩家的坦克动画
		if(moveflag==true){		//如果moveflag==true,则进行移动
			x=x+dx;
			y=y+dy;
			count++;		//每一步,count加1
			frameIndex++;	//	调用下一张图片
			if (frameIndex ==animationFrames.length) {
			   frameIndex=0;		//下标清零,重新开始播放动画
			}
		}
		if(count==8){		//当count==8时,一次移动完毕,即移动了32px
			count=0;		//将count清零
			moveflag=false;	//令moveflag=false,停止移动
		}
		context.save();		//保存当前变换状态
		context.translate(x+16,y+16);		//平移原点坐标
		context.rotate(rotation * Math.PI / 180);		//旋转整个坐标系
		var sourceX=Math.floor(animationFrames[frameIndex] % 8) *32;
		var sourceY=Math.floor(animationFrames[frameIndex] / 8) *32;
		context.drawImage(tileSheet, sourceX, sourceY,32,32,-16,-16,32,32);
		context.restore();	//读取保存的变换状态
		//子弹飞行动画
		var bulletCount=bullets.length;
		for(var i=0;i<bulletCount;i++){
			//检测子弹碰撞的效果
			checkChase(i,bullets[i].x,bullets[i].y);
			//绘制子弹
			if(bullets[i].checkFlag==false){
				context.save();
				context.translate(bullets[i].x+16,bullets[i].y+16);
				context.rotate(bullets[i].rotation*Math.PI/180);
				context.drawImage(tileSheet,128,64,32,32,-16,-16,32,32);
				context.restore();
				//子弹前进
				bullets[i].x+=bullets[i].xspeed;
				bullets[i].y+=bullets[i].yspeed;
			}else{
				createBoom(bullets[i].rotation,bullets[i].x,bullets[i].y);	//产生一个爆炸动画对象
			}
		}
		for(var i=0;i<bulletCount;i++){
			if(bullets[i].checkFlag==true){
				bullets.splice(i,1);	//将该子弹对象从数组中移除并重排数组
				i--;
				bulletCount--;
			}
		}
		//子弹爆炸动画
		var boomCount=booms.length;
		for(var i=0;i<boomCount;i++){
			context.save();
			context.translate(booms[i].x,booms[i].y);
			context.drawImage(tileSheet,32*booms[i].nowpic,64,32,32,0,0,32,32);
			context.restore();
			booms[i].nowpic++;
		}
		for(var i=0;i<boomCount;i++){
			if(booms[i].nowpic==4){
				booms.splice(i,1);
				i--;
				boomCount--;
			}
		}
	}
	//键盘监听事件,用于改变玩家坦克的方向,同时修改坦克的一些数值
	function changeDirection(e){
		if(count==0){		//count==0代表着坦克的前一个动作执行完毕 
			var xindex=x/32;
			var yindex=y/32;
			switch(e.keyCode){
				case 37:
					if(tileMap[yindex][xindex-1]==1){
						direction="left";
						moveflag=true;
						rotation=-90;
						dx=-4;
						dy=0;
					}else if(tileMap[yindex][xindex-1]==undefined){
						direction="left";
						moveflag=true;
						rotation=-90;
						x=320;
						dx=-4;
						dy=0;
					}
					break;
				case 38:
					if(yindex-1==-1){
						direction="top";
						moveflag=true;
						rotation=0;
						y=320;
						dx=0;
						dy=-4;
					}else if(tileMap[yindex-1][xindex]==1){
						direction="top";
						moveflag=true;
						rotation=0;
						dx=0;
						dy=-4;
					}
					break;
				case 39:
					if(tileMap[yindex][xindex+1]==1){
						direction="right";
						moveflag=true;
						rotation=90;
						dx=4;
						dy=0;
					}else if(tileMap[yindex][xindex+1]==undefined){
						direction="right";
						moveflag=true;
						rotation=90;
						x=0;
						dx=4;
						dy=0;
					}
					break;
				case 40:
					if(yindex+1==10){
						direction="bottom";
						moveflag=true;
						rotation=180;
						y=0;
						dx=0;
						dy=4;
					}else if(tileMap[yindex+1][xindex]==1){
						direction="bottom";
						moveflag=true;
						rotation=180;
						dx=0;
						dy=4;
					}
			}
		}
	}
	//键盘监听事件,用于产生子弹,根据坦克当前方向和位置,产生子弹的方向,坐标,以及速度
	var time=0;
	function createBullet(e){
		if(count==0&&time==0){
			var newBullet;
			if(e.keyCode==32){
				switch(rotation){
					case -90:
						newBullet=new Bullet(-90,x-32,y,-32,0,false);
						break;
					case 0:
						newBullet=new Bullet(0,x,y-32,0,-32,false);
						break;
					case 90:
						newBullet=new Bullet(90,x+32,y,32,0,false);
						break;
					case 180:
						newBullet=new Bullet(180,x,y+32,0,32,false);
				}
				bullets.push(newBullet);
				time=1;
				setTimeout(retime,400);		//设置延时是为了不让子弹快速连发,快速连发会破坏游戏体验
				function retime(){
					time=0;
				}
			}
		}
	}
	//根据地图数组来检测子弹的碰撞,若子弹所在格子不为1,将播放子弹爆炸效果
	function checkChase(a,b,c){
		if(c/32>0&&c/32<9){
			if(tileMap[c/32][b/32]!=1){
				bullets[a].checkFlag=true;
			}
		}else{
			bullets[a].checkFlag=true;
		}
	}
	//产生一个爆炸动画,并根据子弹方向调整爆炸动画的坐标
	function createBoom(a,b,c){
		var newBoom;
		switch(a){
			case -90:
				newBoom=new Boom(b+16,c);
				break;
			case 0:
				newBoom=new Boom(b,c+16);
				break;
			case 90:
				newBoom=new Boom(b-16,c);
				break;
			case 180:
				newBoom=new Boom(b,c-16);
		}
		booms.push(newBoom);
	}
}


</script> 
</head>
<body>
<div style="position: absolute; top: 50px; left: 50px;">
<canvas id="canvas" width="320" height="320">
 Your browser does not support the HTML 5 Canvas. 
</canvas>
</div>
</body>
</html>
原文链接:加载失败,请重新获取