Canvas做简易的飞机大战

//首先创建canvas
<canvas id="canvas" width="480px" height="650px"></canvas>

根据游戏的特性我们将游戏分为5个阶段 利用构造函数进行编辑,首先需要定义五个阶段的常量

var canvas = document.getElementById("canvas");
	var context = canvas.getContext("2d");
	// 0 游戏初始化
	// 0.1 定义将游戏划分为的5个阶段常量
	const START = 0;		// 第一阶段
	const STARTTING = 1;	// 第二阶段
	const RUNNING = 2;		// 第三阶段
	const PAUSE = 3;		// 第四阶段
	const GAMEOVER = 4;		// 第五阶段 
	// 0.2 定义一个标示,表示当前游戏处在哪个阶段
	var state = START;
	// 0.3 定义当前画布的高度和宽度
	var WIDTH = 480;
	var HEIGHT = 650;
	// 0.4 定义游戏得分
	var score = 0;
	// 0.5 定义我方飞机的生命值
	var life = 3;

第一阶段首先将背景板构建出来

在这里插入图片描述

var bg = new Image();
	bg.src = "images/background.png";
	// 1.1.2 初始化背景的数据
	var BG = {
		imgs : bg,
		width : 480,
		height : 852
	}
	// 1.1.3 定义背景对象的构造器
	function Bg(config){
		this.imgs = config.imgs;
		this.width = config.width;
		this.height = config.height;
		// 定义绘制背景的坐标值
		this.x1 = 0;
		this.y1 = 0;
		this.x2 = 0;
		this.y2 = -this.height;
		// 定义绘制背景方法
		this.paint = function(){
			context.drawImage(this.imgs,this.x1,this.y1);
			context.drawImage(this.imgs,this.x2,this.y2);
		}
		// 定义背景运动方法
		this.step = function(){
			// 控制两张背景图片向下运动
			this.y1++;
			this.y2++;
			// 判断两张图片的临界点
			if(this.y1 == this.height){
				this.y1 = -this.height;
			}
			if(this.y2 == this.height){
				this.y2 = -this.height;
			}
		}
	}
	// 1.1.4 创建背景对象
	var sky = new Bg(BG);
	console.log(sky)
	// 1.2 加载LOGO图片
	var logo = new Image();
	logo.src = "images/start.png";

第二阶段绘制游戏过渡效果准备进入游戏

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

	// 2. 游戏过渡阶段
	// 2.1 加载过渡动画的图片
	var loadings = [];
	loadings[0] = new Image();
	loadings[0].src = "images/game_loading1.png";
	loadings[1] = new Image();
	loadings[1].src = "images/game_loading2.png";
	loadings[2] = new Image();
	loadings[2].src = "images/game_loading3.png";
	loadings[3] = new Image();
	loadings[3].src = "images/game_loading4.png";
	// 2.2 初始化动画图片的数据
	var LOADINGS = {
		imgs : loadings,
		length : loadings.length,
		width : 186,
		height : 38
	}
	// 2.3 定义动画效果的构造器
	function Loading(config){
		this.imgs = config.imgs;
		this.length = config.length;
		this.width = config.width;
		this.height = config.height;
		// 定义属性表示图片的索引值
		this.startIndex = 0;
		// 定义绘制图片
		this.paint = function(){
			context.drawImage(this.imgs[this.startIndex],0,HEIGHT-this.height);
		}
		// 定义表示速度
		this.time = 0;
		// 定义动画方法
		this.step = function(){
			this.time++;
			if(this.time%3 == 0){
				this.startIndex++;
			}
			if(this.startIndex == this.length){
				// 动画执行完毕,进入下一阶段
				state = RUNNING;
			}
		}
	}
	// 2.4 创建动画效果的对象
	var loading = new Loading(LOADINGS);
	// 2.5 为<canvas>元素绑定onclick事件
	canvas.onclick = function(){
		if(state == START){
			// 将游戏的第一阶段切换到第二阶段
			state = STARTTING;
		}
	}

第三阶段开始进行游戏的运行也是最麻烦的一个阶段

首先加载我方飞机的运动过程还有子弹运行方法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

	var heros = [];
	heros[0] = new Image();
	heros[0].src = "images/hero1.png";
	heros[1] = new Image();
	heros[1].src = "images/hero2.png";
	heros[2] = new Image();
	heros[2].src = "images/hero_blowup_n1.png";
	heros[3] = new Image();
	heros[3].src = "images/hero_blowup_n2.png";
	heros[4] = new Image();
	heros[4].src = "images/hero_blowup_n3.png";
	heros[5] = new Image();
	heros[5].src = "images/hero_blowup_n4.png";
	// 3.1.2 初始化我方飞机的数据
	var HEROS = {
		imgs : heros,
		length : heros.length,
		width : 99,
		height : 124,
		frame : 2
	}
	// 3.1.3 创建我方飞机的构造器
	function Hero(config){
		this.imgs = config.imgs;
		this.length = config.length;
		this.width = config.width;
		this.height = config.height;
		this.frame = config.frame;
		// 定义属性表示索引值
		this.startIndex = 0;
		// 定义绘制我方飞机的坐标值
		this.x = WIDTH/2-this.width/2;
		this.y = HEIGHT-150;
		// 新增标示 - 表示是否撞击
		this.down = false;//当前为没有撞击的状态
		// 新增标示 - 表示是否执行完毕
		this.candel = false;
		// 定义绘制方法
		this.paint = function(){
			context.drawImage(this.imgs[this.startIndex],this.x,this.y);
		}
		// 定义动画方法
		this.step = function(){
			if(!this.down){//如果没有被撞击
				// startIndex的值0和1之间切换
				/*
				this.startIndex++;
				this.startIndex = this.startIndex%2;
				*/
				if(this.startIndex == 0){
					this.startIndex = 1;
				}else{
					this.startIndex = 0;
				}
			}else{
				// 1 切换角标 0 1
				this.startIndex++;
				// 2 判断是否执行完毕
				if(this.startIndex == this.length){
					// life为1
					life--;
					if(life == 0){
						state = GAMEOVER;
						this.startIndex = this.length-1;
					}else{
						hero = new Hero(HEROS);
					}
				}
			}
		}
		this.time = 0;
		// 增加射击的方法
		this.shoot = function(){
			this.time++;
			if(this.time%3 == 0){
				bullets.push(new Bullet(BULLET));
			}
		}
		// 新增bang()方法
		this.bang = function(){
			this.down = true;
		}
	}
	// 3.1.4 创建我方飞机的对象
	var hero = new Hero(HEROS);
	// 3.1.5 为<canvas>绑定onmousemove事件
	canvas.onmousemove = function(event){
		if(state == RUNNING){
			// event.pageX/clientX/offsetX/x
			var x = event.offsetX;
			var y = event.offsetY;
			// 修改我方飞机的坐标值
			hero.x = x - hero.width/2;
			hero.y = y - hero.height/2;
		}
	}
	// 3.2 绘制子弹
	// 3.2.1 加载子弹的图片
	var bullet = new Image();
	bullet.src = "images/bullet1.png";
	// 3.2.2 初始化子弹的数据
	var BULLET = {
		imgs : bullet,
		width : 9,
		height : 21
	}
	// 3.2.3 创建子弹的构造器
	function Bullet(config){
		this.imgs = config.imgs;
		this.width = config.width;
		this.height = config.height;
		// 定义子弹绘制的坐标值
		this.x = hero.x + hero.width/2 - this.width/2;
		this.y = hero.y - this.height - 10;
		// 绘制方法
		this.paint = function(){
			context.drawImage(this.imgs,this.x,this.y);
		}
		// 运动方法
		this.step = function(){
			this.y-=10;
		}
		this.candel = false;
		// 新增方法 - 用于处理撞击后的逻辑
		this.bang = function(){
			this.candel = true;
		}
	}
	// 3.2.4 创建存储子弹的数组
	var bullets = [];
	// 3.2.5 创建函数,用于绘制所有子弹
	function bulletsPaint(){
		for(var i=0;i<bullets.length;i++){
			bullets[i].paint();
		}
	}
	// 3.2.6 创建函数,用于控制所有子弹运动
	function bulletsStep(){
		for(var i=0;i<bullets.length;i++){
			bullets[i].step();
		}
	}
	// 3.2.7 当子弹移动到画布之外时,删除该子弹
	function bulletsDel(){
		for(var i=0;i<bullets.length;i++){
			// 判断子弹的y值 < -子弹高度
			if(bullets[i].y < -bullets[i].height || bullets[i].candel){
				bullets.splice(i,1);
			}
		}
	}

然后绘制敌方飞机

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

	var enemy1 = [];// 小飞机
	enemy1[0] = new Image();
	enemy1[0].src = "images/enemy1.png";
	enemy1[1] = new Image();
	enemy1[1].src = "images/enemy1_down1.png";
	enemy1[2] = new Image();
	enemy1[2].src = "images/enemy1_down2.png";
	enemy1[3] = new Image();
	enemy1[3].src = "images/enemy1_down3.png";
	enemy1[4] = new Image();
	enemy1[4].src = "images/enemy1_down4.png";
	var enemy2 = [];// 中飞机
	enemy2[0] = new Image();
	enemy2[0].src = "images/enemy2.png";
	enemy2[1] = new Image();
	enemy2[1].src = "images/enemy2_down1.png";
	enemy2[2] = new Image();
	enemy2[2].src = "images/enemy2_down2.png";
	enemy2[3] = new Image();
	enemy2[3].src = "images/enemy2_down3.png";
	enemy2[4] = new Image();
	enemy2[4].src = "images/enemy2_down4.png";
	var enemy3 = [];// 大飞机
	enemy3[0] = new Image();
	enemy3[0].src = "images/enemy3_n1.png";
	enemy3[1] = new Image();
	enemy3[1].src = "images/enemy3_n2.png";
	enemy3[2] = new Image();
	enemy3[2].src = "images/enemy3_down1.png";
	enemy3[3] = new Image();
	enemy3[3].src = "images/enemy3_down2.png";
	enemy3[4] = new Image();
	enemy3[4].src = "images/enemy3_down3.png";
	enemy3[5] = new Image();
	enemy3[5].src = "images/enemy3_down4.png";
	enemy3[6] = new Image();
	enemy3[6].src = "images/enemy3_down5.png";
	enemy3[7] = new Image();
	enemy3[7].src = "images/enemy3_down6.png";
	// 3.3.2 初始化敌方飞机的数据
	var ENEMY1 = {
		imgs : enemy1,
		length : enemy1.length,
		width : 57,
		height : 51,
		type : 1,
		frame : 1,
		life : 1,
		score : 1
	}
	var ENEMY2 = {
		imgs : enemy2,
		length : enemy2.length,
		width : 69,
		height : 95,
		type : 2,
		frame : 1,
		life : 3,
		score : 3
	}
	var ENEMY3 = {
		imgs : enemy3,
		length : enemy3.length,
		width : 169,
		height : 258,
		type : 3,
		frame : 2,
		life : 20,
		score : 10
	}
	// 3.3.3 创建敌方飞机的构造器
	function Enemy(config){
		this.imgs = config.imgs;
		this.length = config.length;
		this.width = config.width;
		this.height = config.height;
		this.type = config.type;
		this.frame = config.frame;
		this.life = config.life;
		this.score = config.score;
		// 定义绘制敌方飞机的坐标值
		this.x = Math.random() * (WIDTH - this.width);// 0 - (画布宽-飞机宽)
		this.y = -this.height;
		// 定义数组角标
		this.startIndex = 0;
		// 新增属性 - 表示当前绘制的图片
		//this.img = this.imgs[this.startIndex];
		// 新增状态 - 表示敌机是否被撞击
		this.down = false;
		// 新增状态 - 表示敌机是否被删除
		this.candel = false;
		// 绘制方法
		this.paint = function(){
			context.drawImage(this.imgs[this.startIndex],this.x,this.y);
		}
		// 运动方法
		this.step = function(){
			if(!this.down){//正常
				/*
				 * 小、中飞机(1) - 角标为0
				 * 大飞机(2) - 角标在0和1之间切换
				 */
				this.startIndex++;
				this.startIndex = this.startIndex%this.frame;
				//this.img = this.imgs[this.startIndex];
				// 敌方飞机向下飞行动画
				this.y+=2;
			}else{// 爆破
				/*
				 * 小和中飞机 - 1
				 * 大飞机 - 2
				 */
				// 问题 - 刚进入爆破,只能执行一次
				this.startIndex++;
				//this.img = this.imgs[this.startIndex];
				if(this.startIndex == this.length){
					this.candel = true;
					this.startIndex = this.length-1;
				}
			}
		}
		// 增加用于检查敌机是否被撞击的方法
		this.checkHit = function(wo){
			// 参数wo - 1)我方飞机;2)子弹
			return wo.y + wo.height > this.y
			&& wo.x + wo.width > this.x
			&& wo.y < this.y + this.height
			&& wo.x < this.x + this.width;
		}
		// 新增方法bang() - 用于被撞击后的逻辑
		this.bang = function(){
			this.life--;
			if(this.life == 0){
				this.down = true;
				score += this.score;
			}
		}
	}
	// 3.3.4 创建数组 - 用于存储所有敌方飞机
	var enemies = [];
	// 3.3.5 创建函数 - 用于创建敌方飞机
	function enterEnemies(){
		/*
		 * 小、中、大飞机
		 * * 小飞机 - 相对数量是最多
		 * * 中飞机 - 相对数量是居中
		 * * 大飞机 - 相对数量是最少
		 */
		var rand = Math.floor(Math.random()*100);
		if(rand <= 7){
			// 小飞机
			enemies.push(new Enemy(ENEMY1));
		}else if(rand == 8){
			// 中飞机
			enemies.push(new Enemy(ENEMY2));
		}else if(rand == 9){
			// 大飞机 - 只允许数组的第一个元素为大飞机
			if(enemies[0].type != 3 && enemies.length > 0){
				enemies.splice(0,0,new Enemy(ENEMY3));
			}
		}
	}
	// 3.3.6 创建函数 - 用于绘制敌方飞机
	function paintEnemies(){
		for(var i=0;i<enemies.length;i++){
			enemies[i].paint();
		}
	}
	// 3.3.7 创建函数 - 用于控制敌方飞机运动
	function stepEnemies(){
		for(var i=0;i<enemies.length;i++){
			enemies[i].step();
		}
	}
	// 3.3.8 创建函数 - 用于删除敌方飞机
	function delEnemies(){
		for(var i=0;i<enemies.length;i++){
			// 敌方飞机的y值 > 画布的高度
			if(enemies[i].y > HEIGHT||enemies[i].candel){
				enemies.splice(i,1);
			}
		}
	}
	// 3.4 创建函数 - 用于检查撞击情况
	function hitEnemies(){
		for(var i=0;i<enemies.length;i++){
			// 我方飞机撞击敌方飞机
			if(enemies[i].checkHit(hero)){
				// 处理敌方飞机撞击后的逻辑
				enemies[i].bang();
				// 处理我方飞机撞击后的逻辑
				hero.bang();
			}
			// 子弹撞击敌方飞机
			for(var j=0;j<bullets.length;j++){
				if(enemies[i].checkHit(bullets[j])){
					// 处理敌方飞机撞击后的逻辑
					enemies[i].bang();
					// 处理子弹撞击后的逻辑
					bullets[j].bang();
				}
			}
		}
	}

绘制游戏得分与我方生命值

	function paintText(){
		context.font = "bold 24px 微软雅黑";
		context.fillText("SCORE: "+score,10,30);
		context.fillText("LIFE: "+life,390,30);
	}

第四阶段绘制暂停阶段

canvas.onmouseover = function(){
		// 从暂停恢复到运行
		if(state == PAUSE){
			state = RUNNING;
		}
	}
	canvas.onmouseout = function(){
		// 从运行切换到暂停
		if(state == RUNNING){
			state = PAUSE;
		}
	}
	var pause = new Image();
	pause.src = "images/game_pause_nor.png";

第五阶段绘制游戏结束画面

function paintOver(){
		context.font = "bold 48px 微软雅黑";
		context.fillText("GAME OVER",100,320);
	}

最后我们利用定时器将函数运动起来

	setInterval(function(){
		// 1 绘制背景图片
		sky.paint();
		// 2 控制背景运动
		sky.step();
		switch (state){
			case START:
				// 3 绘制logo图片
				context.drawImage(logo,20,0);
				break;
			case STARTTING:
				// 绘制动画效果
				loading.paint();
				// 切换动画图片
				loading.step();
				break;
			case RUNNING:
				// 绘制我方飞机
				hero.paint();
				// 我方飞机动画
				hero.step();
				// 我方飞机的射击
				hero.shoot();
				// 绘制子弹
				bulletsPaint();
				// 移动子弹
				bulletsStep();
				// 删除子弹
				bulletsDel();
//				 创建敌方飞机
				 enterEnemies();
				 // 绘制敌方飞机
				 paintEnemies();
				 // 控制敌方飞机运动
				 stepEnemies();
				 // 删除敌方飞机
				 delEnemies();
				 // 检查是否被撞击
				 hitEnemies();
				 // 绘制得分与生命值
				 paintText();
				break;
			case PAUSE:
				 hero.paint();
				 bulletsPaint();
				 paintEnemies();
				 paintText();
				context.drawImage(pause,10,10);
				break;
			case GAMEOVER:
				 hero.paint();
				 bulletsPaint();
				 paintEnemies();
				 paintText();
				 paintOver();
				break;
		}
	},100);
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值