canvas实现雷电系列游戏

本人第一次写博文,如有表达不当或是书写不规范的地方请大家细心指出.

 

1.首先确定游戏上的元素-飞机,子弹. 我把它们 归为一类 -飞行单位类:

force-势力方

type-单位类型

x,y- 坐标

valid-是否有效,在删除单位时有用

damage-撞击后造成的伤害

hp-单位血量

fireType-如果是飞机 则可以发射的子弹类型

fireInterval-发射子弹的间隔

interval-发射子弹的当前间隔

 

//飞行单位
var Fly=function(force,type){
	var self=this;
	self.force=force;
	self.type=type;
	self.x=0;
	self.y=0;
	self.valid=true;
	self.damage=0;
	self.hp=0;
	self.fireType=-1;
	self.fireInterval=-1;
	switch(type.toString()){
		case '0':
			self.damage=100;
			self.hp=1;
			self.fireType=101;
			self.fireInterval=35;
			self.interval=35;
			self.range=5;
			break;
		case '2':
			//controller
			self.damage=100;
			self.hp=20;
			self.fireType=100;
			self.fireInterval=35;
			self.interval=35;
			self.range=10;
			break;
		case '3':
			self.damage=100;
			self.hp=15;
			self.fireType=104;
			self.fireInterval=100;
			self.interval=100;
			self.range=25;
			break;
		case '4':
			self.damage=10;
			self.hp=5;
			self.fireType=101;
			self.fireInterval=40;
			self.interval=40;
			self.range=20;
			break;
		case '5':
			//boss
			self.damage=1000;
			self.hp=100;
			self.fireType=105;
			self.fireInterval=20;
			self.interval=20;
			self.range=100;
			break;
		case '100':
			self.damage=1;
			self.hp=1;
			break;
		case '101':
			self.damage=1;
			self.hp=1;
			break;
		case '104':
			self.damage=10;
			self.hp=2;
			break;
		case '105':
			self.damage=10;
			self.hp=1;
			break;
	}
}

 

 

2.针对飞行单位,有以下方法:

  1)初始化坐标

  2)绘制单位

  3)死亡动画

  4)自动移动过程

 

Fly.prototype={
	initPos:function(x,y){
		if(this.force==1){
			this.x=gameWidth/2;
			this.y=gameHeight-30;
		}else{
			this.x=x||(gameWidth/2);
			this.y=y-(this.range||0)||-50;
		}
	},
	draw:function(){
		if(!this.valid)return;
		switch(this.type.toString()){
			case '0'://实心圆
				ctx.strokeStyle = "#000000";
				ctx.fillStyle = "#000000";
				ctx.beginPath();
				ctx.arc(this.x, this.y, 5, 0, Math.PI*2, true); 
				ctx.closePath();
				ctx.fill();
				break;
			case '2'://正三角
				ctx.drawImage(imgList[0], this.x-26, this.y-25);
				break;
			case '3':
				//61 26
				ctx.drawImage(imgList[1], this.x-30, this.y-13);
				break;
			case '4':
				ctx.drawImage(imgList[2], this.x-20, this.y-20);
				break;
			case '5':
				ctx.drawImage(imgList[3],this.x-100,this.y-100);
				break;
			case '100'://竖形子弹
			case '101'://竖形子弹
				ctx.fillStyle="Red";
				ctx.fillRect(this.x-1,this.y-2,2,4);
				break;
			case '104':
				ctx.fillStyle="#126116";
				ctx.beginPath();
				ctx.moveTo(this.x-5,this.y);
				ctx.lineTo(this.x+5,this.y);
				ctx.lineTo(this.x,this.y+6);
				ctx.lineTo(this.x-5,this.y);
				ctx.closePath();
				ctx.fill();
				break;
			case '105':
				ctx.drawImage(imgList[4],this.x-7,this.y-7);
				break;
			default:
				break;
		}
	},
	die:function(){
		this.valid=false;
		//动画
		//略过
		if(this.type==101)
			return;
		ctx.fillStyle="#FF0000";
		ctx.beginPath();
		ctx.arc(this.x,this.y,6,0,Math.PI*2,true);
		ctx.closePath();
		ctx.fill();
		var self=this;
		var time=0;
		var i=setInterval(function(){
			var tm=(Math.floor(255*time/10)).toString(16);
			ctx.fillStyle='#FF'+tm+tm;
			ctx.beginPath();
			ctx.arc(self.x,self.y,6+time/8,0,Math.PI*2,true);
			ctx.closePath();
			ctx.fill();
			if(time++==80)
				clearInterval(i);
		},13);
	},
	autoMove:function(){
		switch(this.type.toString()){
			case '0':
			case '2':
			case '3':
			case '4':
				if(this.force=='1'){
				
				}else{
					this.y+=2;
					if(this.y>gameHeight+10)
						this.valid=false;
				}	
				break;
			case '5':
				//boss
				if(this.y<50){
					this.y+=2;
				}else{
					this.x=gameWidth/2+gameWidth/3*Math.sin((bossMoveTimer++)/30);
				}
				break;
			case '100':
				this.y-=10;
					if(this.y<-10)
						this.valid=false;
				break;
			case '101':
			case '104':
				if(this.force=='1'){
					this.y-=3;
					if(this.y<-10)
						this.valid=false;
				}else{
					this.y+=5;
					if(this.y>gameHeight+10)
						this.valid=false;
				}
				break;
			case '105':
				if(this.force=='1'){
					//[*]
				}else{
					this.y+=4;
					this.x+=Math.sin((bulletMoveTimer++)/50)*10;
					if(this.y>gameHeight+10)
						this.valid=false;
				}
				break;
			default:
				break;
		}
	}
}

 

 

3.游戏的主流程是一个循环控制过程.

 

//循环 函数
	function step() {
		gameTime+=30;
		controllerManager();
		enemyManager();
		bulletManager();
		damageManager();
		ReDraw();
	}

 

 

  其中controllerManager()进行控制者操作,如方向的移动,子弹的发射等.

 

//控制者处理
function controllerManager(){
	//方向
	if(direction.l){
		controller.x-=2;
	}
	if(direction.r){
		controller.x+=2;
	}
	if(direction.t){
		controller.y-=2;
	}
	if(direction.d){
		controller.y+=2;
	}
	if(direction.l==direction.r&&direction.t==direction.d)
		return;
}

 

  enemyManager()进行地方单位的操作,如添加敌方单位,敌方单位子弹发射,敌方单位的位置移动等.我用了一个json结构来表示游戏进程,key-是游戏的时间,value-是加入的地方单位的类型

 

//敌方单位处理
function enemyManager(){
	var tm=Process[Math.floor(gameTime/1000)];
	if(tm){
		//添加敌方单位
		for(var i in tm){
			var e=new Fly(2,tm[i]);
			e.initPos(gameWidth/(tm.length+1)*(parseInt(i)+1));
			enemy.push(e);
		}
		Process[Math.floor(gameTime/1000)]=null;
	}
	for(var i in enemy){
		if(enemy[i]){
			enemy[i].autoMove();
			if(!enemy[i].valid){
				enemy[i]=null;
			}else{
				//fire
				if(enemy[i].y<10)
					return;
				if(enemy[i].fireType!=-1&&--enemy[i].interval==0){
					enemy[i].interval=enemy[i].fireInterval;
					var tm=new Fly(enemy[i].force,enemy[i].fireType);
					tm.initPos(enemy[i].x,enemy[i].y+enemy[i].range);
					bullet.push(tm);
				}
			}
		}
	}
	//清理数组
	while(enemy.length>0&&enemy[0]==null){
		enemy.shift();
	}
}

 

  bulletManager()用来控制子弹的移动.

 

//子弹处理
function bulletManager(){
	if(openFire&&--fireInterval==0){
		var tm=new Fly(1,100);
		tm.x=controller.x;
		tm.y=controller.y-7;
		bullet.push(tm);
		fireInterval=5;
	}
	for(var i in bullet){
		if(!bullet[i])continue;
		bullet[i].autoMove();
		if(!bullet[i].valid){
			bullet[i]=null;
		}
	}
	//清理数组
	while(bullet.length>0&&bullet[0]==null){
		bullet.shift();
	}
}

 

  damageManager()用来进行单位的撞击判断,以及计分的刷新,失败的判断都在里面.

 

//撞击判断
function damageManager(){
	for(var i in bullet){
		for(var j in enemy){
			if(!bullet[i]||!enemy[j])continue;
			if(bullet[i].force==enemy[j].force)continue;
			if(Math.abs(bullet[i].x-enemy[j].x)>enemy[j].range||Math.abs(bullet[i].y-enemy[j].y)>enemy[j].range)continue;
			enemy[j].hp-=bullet[i].damage;
			if(enemy[j].hp<=0)
				enemy[j].die();
			bullet[i].die();
		}
		if(!bullet[i])continue;
		if(bullet[i].force==controller.force)continue;
		if(Math.abs(bullet[i].x-controller.x)>controller.range||Math.abs(bullet[i].y-controller.y)>controller.range)continue;
		controller.hp-=bullet[i].damage;
		if(controller.hp<=0){
			controller.die();
			//失败
			Fail();
		}
		bullet[i].die();
		refreshScore();
	}
	for(var j in enemy){
		if(!enemy[j])continue;
		if(Math.abs(controller.x-enemy[j].x)>enemy[j].range||Math.abs(controller.y-enemy[j].y)>enemy[j].range)continue;
		controller.hp-=enemy[j].damage;
		if(controller.hp<=0){
			controller.die();
			//失败
			Fail();
		}
		enemy[j].die();
		refreshScore();
	}
}

 

  ReDraw()用来对canvas进行重绘.

 

//重绘
function ReDraw(){
	ctx.clearRect(0,0,gameWidth,gameHeight);
	//controller
	controller.draw();
	//enemy
	for(var e in enemy){
		if(enemy[e])
			enemy[e].draw();
	}
	//bullet
	for(var b in bullet){
		if(bullet[b])
			bullet[b].draw();
	}
}

预览:

100/100
posted @ 2010-07-20 10:47  yanboy  阅读(892)  评论(2)    收藏  举报