您现在的位置是:网站首页> 编程资料编程资料
canvas实现飞机打怪兽射击小游戏的示例代码H5 canvas实现贪吃蛇小游戏html5 canvas-2.用canvas制作一个猜字母的小游戏
2023-10-16
395人已围观
简介 这篇文章主要介绍了canvas实现飞机打怪兽射击小游戏的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
接触 canvas 也只有一个多月,第一次完整实现一个游戏流程,收获还是挺大的。

射击游戏截图
先上 demo:https://littleyljy.github.io/demo/shootgame/
游戏规则
要求玩家控制飞机发射子弹,消灭会移动的怪兽,如果全部消灭了则游戏成功,如果怪兽移动到底部则游戏失败。
- 使用 ← 和 → 操作飞机
- 使用空格(space)进行射击
- 需有暂停功能
- 多关卡
场景切换
游戏分为几个场景:
- 开始游戏(.game-intro)
- 游戏中(#canvas)
- 游戏失败(.game-failed)
- 游戏成功(.game-success)
- 游戏通关(.game-all-success)
- 暂停(.game-stop)
实现场景切换,其实是先把所有场景 display: none , 然后通过 js 控制 data-status 分别为 start 、playing 、failed 、success 、all-success 、stop 来实现对应场景 display: block 。
HTML 和 CSS 如下:
射击游戏
这是一个令人欲罢不能的射击游戏,使用 ← 和 → 操作你的飞机,使用空格(space)进行射击,使用回车(enter)暂停游戏。一起来消灭宇宙怪兽吧!
当前Level: 1
游戏结束
最终得分:
游戏成功
通关成功
游戏暂停
分数:
#game{ width: 700px; height: 600px; position: relative; left: 50%; top: 40px; margin: 0 0 0 -350px; background: linear-gradient(-180deg, #040024 0%, #07165C 97%); } .game-ui{ display: none; padding: 55px; box-sizing: border-box; height: 100%; } [data-status="start"] .game-intro { display: block; padding-top: 180px; background: url(./img/bg.png) no-repeat 430px 180px; background-size: 200px; } [data-status="playing"] .game-info { display: block; position: absolute; top:0; left:0; padding:20px; } [data-status="failed"] .game-failed, [data-status="success"] .game-success, [data-status="all-success"] .game-all-success, [data-status="stop"] .game-stop{ display: block; padding-top: 180px; background: url(./img/bg-end.png) no-repeat 380px 190px; background-size: 250px; } 面向对象

整个游戏可以把怪兽(Enemy)、飞机(Plane)、子弹(Bullet)都当作对象,另外还有配置对象(CONFIG)和控制游戏逻辑的游戏对象(GAME)。
游戏相关配置
/** * 游戏相关配置 * @type {Object} */ var CONFIG = { status: 'start', // 游戏开始默认为开始中 level: 1, // 游戏默认等级 totalLevel: 6, // 总共6关 numPerLine: 7, // 游戏默认每行多少个怪兽 canvasPadding: 30, // 默认画布的间隔 bulletSize: 10, // 默认子弹长度 bulletSpeed: 10, // 默认子弹的移动速度 enemySpeed: 2, // 默认敌人移动距离 enemySize: 50, // 默认敌人的尺寸 enemyGap: 10, // 默认敌人之间的间距 enemyIcon: './img/enemy.png', // 怪兽的图像 enemyBoomIcon: './img/boom.png', // 怪兽死亡的图像 enemyDirection: 'right', // 默认敌人一开始往右移动 planeSpeed: 5, // 默认飞机每一步移动的距离 planeSize: { width: 60, height: 100 }, // 默认飞机的尺寸, planeIcon: './img/plane.png' }; 定义父类
因为怪兽(Enemy)、飞机(Plane)、子弹(Bullet)都有相同的 x, y, size, speed 属性和 move() 方法,所以可以定义一个父类 Element,通过子类继承父类的方式实现。
/*父类:包含x y speed move() draw()*/ var Element = function (opts) { this.opts = opts || {}; //设置坐标、尺寸、速度 this.x = opts.x; this.y = opts.y; this.size = opts.size; this.speed = opts.speed; }; Element.prototype.move = function (x, y) { var addX = x || 0; var addY = y || 0; this.x += addX; this.y += addY; }; //继承原型的函数 function inheritPrototype(subType, superType) { var proto = Object.create(superType.prototype); proto.constructor = subType; subType.prototype = proto; } move(x, y) 方法根据传入的 (x, y) 值自叠加。
定义怪兽
怪兽包含特有属性:怪兽状态、图像、控制爆炸状态持续的 boomCount ,和 draw()、down()、direction()、booming() 方法。
/*敌人*/ var Enemy = function (opts) { this.opts = opts || {}; //调用父类属性 Element.call(this, opts); //特有属性状态和图像 this.status = 'normal';//normal、booming、noomed this.enemyIcon = opts.enemyIcon; this.enemyBoomIcon = opts.enemyBoomIcon; this.boomCount = 0; }; //继承Element方法 inheritPrototype(Enemy, Element); //方法:绘制敌人 Enemy.prototype.draw = function () { if (this.enemyIcon && this.enemyBoomIcon) { switch (this.status) { case 'normal': var enemyIcon = new Image(); enemyIcon.src = this.enemyIcon; ctx.drawImage(enemyIcon, this.x, this.y, this.size, this.size); break; case 'booming': var enemyBoomIcon = new Image(); enemyBoomIcon.src = this.enemyBoomIcon; ctx.drawImage(enemyBoomIcon, this.x, this.y, this.size, this.size); break; case 'boomed': ctx.clearRect(this.x, this.y, this.size, this.size); break; default: break; } } return this; }; //方法:down 向下移动 Enemy.prototype.down = function () { this.move(0, this.size); return this; }; //方法:左右移动 Enemy.prototype.direction = function (direction) { if (direction === 'right') { this.move(this.speed, 0); } else { this.move(-this.speed, 0); } return this; }; //方法:敌人爆炸 Enemy.prototype.booming = function () { this.status = 'booming'; this.boomCount += 1; if (this.boomCount > 4) { this.status = 'boomed'; } return this; } - draw() 主要是根据怪兽的状态绘制不同的图像。
- down() 调用父类 move() 方法,传入 y 值控制怪兽向下移动。
- direction() 根据传入的方向值控制左/右移动。
- booming() 让爆炸状态持续4帧,4帧后再消失。
定义子弹
子弹有 fly() 、draw() 方法。
/*子弹*/ var Bullet = function (opts) { this.opts = opts || {}; Element.call(this, opts); }; inheritPrototype(Bullet, Element); //方法:让子弹飞 Bullet.prototype.fly = function () { this.move(0, -this.speed); return this; }; //方法:绘制子弹 Bullet.prototype.draw = function () { ctx.beginPath(); ctx.strokeStyle = '#fff'; ctx.moveTo(this.x, this.y); ctx.lineTo(this.x, this.y - CONFIG.bulletSize); ctx.closePath(); ctx.stroke(); return this; }; - fly() 调用父类 move() 方法,传入 y 值控制子弹向上移动。
- draw() 因为子弹其实就是一条长度为 10 的直线,通过绘制路径的方式画出子弹。
定义飞机
飞机对象包含特有属性:状态、宽高、图像、横坐标最大最小值,有 hasHit()、draw()、direction()、shoot()、drawBullets() 方法。
/*飞机*/ var Plane = function (opts) { this.opts = opts || {}; Element.call(this, opts); //特有属性状态和图像 this.status = 'normal'; this.width = opts.width; this.height = opts.height; this.planeIcon = opts.planeIcon; this.minX = opts.minX; this.maxX = opts.maxX; //子弹相关 this.bullets = []; this.bulletSpeed = opts.bulletSpeed || CONFIG.bulletSpeed; this.bulletSize = opts.bulletSize || CONFIG.bulletSize; }; //继承Element方法 inheritPrototype(Plane, Element); //方法:子弹击中目标 Plane.prototype.hasHit = function (enemy) { var bullets = this.bullets; for (var i = bullets.length - 1; i >= 0; i--) { var bullet = bullets[i]; var isHitPosX = (enemy.x < bullet.x) && (bullet.x < (enemy.x + enemy.size)); var isHitPosY = (enemy.y < bullet.y) && (bullet.y < (enemy.y + enemy.size)); if (isHitPosX && isHitPosY) { this.bullets.splice(i, 1); return true; } } return false; }; //方法:绘制飞机 Plane.prototype.draw = function () { this.drawBullets(); var planeIcon = new Image(); planeIcon.src = this.planeIcon; ctx.drawImage(planeIcon, this.x, this.y, this.width, this.height); return this; }; //方法:飞机方向 Plane.prototype.direction = function (direction) { var speed = this.speed; var planeSpeed; if (direction === 'left') { planeSpeed = this.x < this.minX ? 0 : -speed; } else { planeSpeed = this.x > this.maxX ? 0 : speed; } console.log('planeSpeed:', planeSpeed); console.log('this.x:', this.x); console.log('this.minX:', this.minX); console.log('this.maxX:', this.maxX); this.move(planeSpeed, 0); return this;//方便链式调用 }; //方法:发射子弹 Plane.prototype.shoot = function () { var bulletPosX = this.x + this.width / 2; this.bullets.push(new Bullet({ x: bulletPosX, y: this.y, size: this.bulletSize, speed: this.bulletSpeed })); return this; }; //方法:绘制子弹 Plane.prototype.drawBullets = function () { var bullets = this.bullets; var i = bullets.length; while (i--) { var bullet = bullets[i]; bullet.fly(); if (bullet.y <= 0) { bullets.splice(i, 1); } bullet.draw(); } }; - hasHit() 判断飞机发射的子弹是否击中怪兽,主要是判断子弹的横坐标是否在[怪兽横坐标,怪兽横坐标+怪兽高度]范围内,同时子弹的纵坐标在[怪兽纵坐标,怪兽纵坐标+怪兽宽度]范围内,击中返回 true,并移除该子弹。
- draw() 绘制子弹和飞机。
- direction() 因为飞机移动范围有左右边界,需要判断飞机横坐标是否到达边界,如果到达边界 planeSpeed 为 0,不再移动。
- shoot() 创建子弹对象,保存到 bullets 数组,子弹横坐标为飞机横坐标加上飞机宽度的一半。
- drawBullets() 绘制子弹,从数组最后往回遍历子弹对象数组,调用子弹 fly() 方法,如果子弹向上飞出屏幕,则移除这颗子弹。
定义键盘事件
键盘事件有以下几种状态:
- keydown:用户在键盘上按下某按键时发生。一直按着某按键则会不断触发(opera 浏览器除外)。
- keypress:用户按下一个按键,并产生一个字符时发生(也就是不管类似 shift、alt、ctrl 之类的键,就是说用户按了一个能在屏幕上输出字符的按键 keypress 事件才会触发)。一直按着某按键则会不断触发。
- keyup:用户释放某一个按键是触发。
因为飞机需要按下左键(keyCode=37)右键(keyCode=39)时(keydown)一直移动,释放时 keyup 不移动。按下空格(keyCode=32)或上方向键(keyCode=38)时(keydown)发射子弹,释放时 keyup 停止发射。另外按下回车键(keyCode=13)暂停游戏。所以,需要定义一个 KeyBoard 对象监听 onkeydown 和 onkeyup 是否按下或释放某个键。
因为左右键是矛盾的,为保险起见,按下左键时需要把右键 设为 false。右键同理。
//键盘事件 var KeyBoard = function () { document.onkeydown = this.keydown.bind(this)
相关内容
- 你可能不熟练的十个前端HTML5经典面试题前端HTML+CSS笔试题面试题腾讯前端面试题相关知识点集锦这是今年前端最常见的面试题,你都会了吗(推荐)前端常见面试题总结1 前端高频面试题最全的前端面试题 前端面试题集合BAT及各大互联网公司2014前端笔试面试题(Html,Css篇)面试官一问一答式的前端面试题
- canvas学习笔记之绘制简单路径html5实现点击弹出图片功能html5 录制mp3音频支持采样率和比特率设置html5表单的required属性使用html5调用摄像头实例代码HTML5页面音频自动播放的实现方式Html5大屏数据可视化开发的实现html实现弹窗的实例HTML5来实现本地文件读取和写入的实现方法HTML 罗盘式时钟的实现HTML5简单实现添加背景音乐的几种方法
- Html5如何唤起百度地图App的方法html5唤起app的方法
- 详解通过变换矩阵实现canvas的缩放功能html5实现点击弹出图片功能html5 录制mp3音频支持采样率和比特率设置html5表单的required属性使用html5调用摄像头实例代码HTML5页面音频自动播放的实现方式Html5大屏数据可视化开发的实现html实现弹窗的实例HTML5来实现本地文件读取和写入的实现方法HTML 罗盘式时钟的实现HTML5简单实现添加背景音乐的几种方法
- canvas绘制文本内容自动换行的实现代码html5实现点击弹出图片功能html5 录制mp3音频支持采样率和比特率设置html5表单的required属性使用html5调用摄像头实例代码HTML5页面音频自动播放的实现方式Html5大屏数据可视化开发的实现html实现弹窗的实例HTML5来实现本地文件读取和写入的实现方法HTML 罗盘式时钟的实现HTML5简单实现添加背景音乐的几种方法
- 浅谈pc和移动端的响应式的使用html5实现点击弹出图片功能html5 录制mp3音频支持采样率和比特率设置html5表单的required属性使用html5调用摄像头实例代码HTML5页面音频自动播放的实现方式Html5大屏数据可视化开发的实现html实现弹窗的实例HTML5来实现本地文件读取和写入的实现方法HTML 罗盘式时钟的实现HTML5简单实现添加背景音乐的几种方法
- 天天炫斗15冲16段连招全面解析_手机游戏_游戏攻略_
- 节奏大师新手必看攻略_节奏大师最全新手指南_各种名词图解_手机游戏_游戏攻略_
- 节奏大师最新版本所有隐藏歌曲一览_节奏大师最新版本隐藏歌曲_手机游戏_游戏攻略_
- 天天炫斗酷比近距离打法攻略心得_手机游戏_游戏攻略_
点击排行
本栏推荐
