目录

1、游戏设计思路

2、飞机射击游戏设计步骤


本篇博文将分享一篇基于HTML的简单的飞机射击游戏,下方是玩家飞机,可按空格键能不断地发射子弹,上方是随机出现的敌方飞机。玩家可以通过键盘的方向键控制自己飞机的移动,当玩家飞机的子弹碰到敌方飞机时,敌方飞机出现爆炸效果。游戏运行效果如下图所示:

1、游戏设计思路

1、游戏素材

游戏程序中用到敌方飞机、我方飞机、子弹、敌机被击中的爆炸图片等,分别使用如下图所示:

2、地图滚动的原理实现

举个简单的例子,大家都坐过火车吧,坐火车的时候都遇到过自己的火车明明是停止的,但是旁边铁轨的火车在向后行驶,会有一种错觉感觉自己的火车是在向前行驶。飞行射击类游戏的地图原理和这个完全一样。玩家在控制飞机在屏幕中飞行的位置,背景图片一直向后滚动从而给玩家一种错觉自己控制的飞机在向前飞行。

如下图所示地图图片在屏幕背后交替滚动,这样就会给玩家产生自己控制的飞机在向前移动的错觉。

地图滚动的相关代码,如下所示:

function updateBg() {/** 更新游戏背景图片实现向下滚动效果**/mBitposY0 += 5;//第一张地图map_0.png的纵坐标下移5个像素mBitposY1 += 5;//第二张地图map_1.png的纵坐标下移5个像素if (mBitposY0 == mScreenHeight) { //超过游戏屏幕的底边mBitposY0 = -mScreenHeight;//回到屏幕上方}if (mBitposY1 == mScreenHeight) {//超过游戏屏幕的底边mBitposY1 = -mScreenHeight; //回到屏幕上方}}

3、飞机和子弹的实现

游戏中使用到的飞机、子弹均采用对应的类实现。因为子弹的数量会有很多,敌机的数量也会很多,所以每一颗子弹须要用一个对象来记录这当前子弹在屏幕中的X,Y坐标。每一架敌机也是一个对象,也记录着它在屏幕中的X,Y坐标。这样在处理碰撞的时候通过遍历子弹对象与敌机对象就可以计算出碰撞的结果,从而拿到碰撞的敌机对象播放死亡爆炸动画。

游戏过程中每隔3秒添加一架敌机,玩家按空格键发射子弹并初始化其位置坐标在玩家飞机前方。在定时事件中不断更新游戏背景图片位置,下移5个像素,实现向下滚动效果,同时更新每发子弹位置每次上移1个像素,更新敌机位置(每次1个像素),最后检测子弹与敌机的碰撞。

这样在处理碰撞的时候其实就是每一颗子弹的矩形区域与每一架敌机的矩形区域的碰撞。通过遍历子弹对象与敌机对象就可以计算出碰撞的结果,从而得到碰撞的敌机对象并播放死亡爆炸动画。

2、飞机射击游戏设计步骤

1、设计子弹类

创建一个的Bullet类,用于表示子弹,实现子弹坐标更新,绘制子弹动画效果并上移1个像素。子弹是有4帧组成,每10个时间间隔(每个间隔为1000/60=16.67毫秒)换一帧。代码如下所示:

//子弹类var Bullet = function (image, x, y) {this.image = image;this.x = x;this.y = y;this.width = image.width/4;this.height = image.height ;this.frm = 0;  //当前是第几帧this.dis = 0;  //多少时间间隔};

检测点(x, y)是否在子弹区域内(本游戏没有使用),代码如下所示:

Bullet.prototype.testPoint = function (x, y) {var betweenX = (x >= this.x) && (x <= this.x + this.width);var betweenY = (y >= this.y) && (y <= this.y + this.height);return betweenX && betweenY;};

move改变子弹位置,代码如下所示:

Bullet.prototype.move = function (dx, dy) {this.x += dx;this.y += dy;};

draw绘制子弹动画效果并上移1个像素。每10个间隔换一帧,子弹共4帧(图14-7所示)。子弹坐标更新主要修改y坐标(垂直方向)值,每次1个像素。当然也可以修改x坐标(水平方向)值,这里为了简单化没修改x坐标值(水平方向),代码如下所示:

Bullet.prototype.draw = function (ctx) {ctx.save();ctx.translate(this.x, this.y);ctx.drawImage(this.image, this.frm *this.width, 0 , this.width, this.height, 0, 0, this.width, this.height);//绘制子弹对应this.frm帧ctx.restore();this.y--;    //上移1个像素this.dis++;if (this.dis >= 10) {//10个间隔换一帧this.dis = 0;this.frm++;if (this.frm >= 4) this.frm = 0;}}; 

hitTestObject判断子弹与飞机是否碰撞,代码如下所示:

 Bullet.prototype.hitTestObject = function (planobj) {if(isColliding(this.x,this.y,this.width,this.height,planobj.x,planobj.y,planobj.width,planobj.height))//发生碰撞return true;elsereturn false;}

isColliding全局函数是前面分析的第二种碰撞检测方法,代码如下所示:

function  isColliding( ax, ay, aw, ah,  bx,  by,  bw,  bh){ if(ay > by + bh || by > ay + ah || ax > bx + bw || bx > ax + aw) return false; elsereturn true; }

2、设计飞机类

在项目中创建一个Plan类,用于表示敌机和己方的飞机,实现飞机坐标更新,绘制功能。功能与子弹类相似。

构造函数中image是飞机图片,(x, y)是飞机位置坐标,而最后一个参数n是本飞机图是几帧动画,例如己方飞机是6帧动画,敌机是2帧动画,效果如下所示:

玩家飞机和敌机

实现代码如下所示:

var Plan = function (image, x, y, n) {this.image = image;this.x = x;this.y = y;this.originX = x;this.originY = y;this.width = image.width / n;    //每帧飞机宽度this.height = image.height;    //每帧飞机高度this.frm = 0;this.dis = 0;this.n = n;};Plan.prototype.testPoint = function (x, y) {var betweenX = (x >= this.x) && (x <= this.x + this.width);var betweenY = (y >= this.y) && (y <= this.y + this.height);return betweenX && betweenY;};Plan.prototype.move = function (dx, dy) {this.x += dx;this.y += dy;};Plan.prototype.Y = function ( ) {return this.y;};

draw (ctx)不断下移地画飞机,同时水平方向也有位移,采用正弦移动,实现代码如下所示:

Plan.prototype.draw = function (ctx) {ctx.save();ctx.translate(this.x, this.y);ctx.drawImage(this.image, this.frm *this.width, 0 , this.width, this.height,
0, 0, this.width, this.height);ctx.restore();this.y++;       //下移1个像素this.x = this.originX + 20 * Math.sin(Math.PI / 100 * this.y);//水平方向正弦移动this.dis++;if (this.dis >= 3) {//3个间隔换图this.dis = 0;this.frm++;if (this.frm >= this.n) this.frm = 0;}};

draw2 (ctx)原地不动画飞机,因为己方飞机是人工控制移动的,所以需要此函数,实现代码如下所示:

Plan.prototype.draw2 = function (ctx) {ctx.save();ctx.translate(this.x, this.y);ctx.drawImage(this.image, this.frm *this.width, 0 , this.width, this.height,
0, 0, this.width, this.height);ctx.restore();this.dis++;if (this.dis >= 3) {//3个间隔换图this.dis = 0;this.frm++;if (this.frm >= this.n) this.frm = 0;}};//飞机之间碰撞检测//如果重叠则说明飞机碰撞。Plan.prototype.hitTestObject = function (planobj) {if(isColliding(this.x,this.y,this.width,this.height,planobj.x,planobj.y,planobj.width,planobj.height))    //发生碰撞return true;elsereturn false;}

3、爆炸类

爆炸动画被叫简单,只需原地绘制爆炸的6帧就可以,效果如下所示:

敌机爆炸的6帧图像

实现代码如下所示:

//爆炸动画var Bomb= function (image, x, y) {this.image = image;this.x = x;this.y = y;this.width = image.width/6;this.height = image.height ;this.frm = 0;this.dis = 0;};Bomb.prototype.draw2 = function (ctx) {ctx.save();ctx.translate(this.x, this.y);if (this.frm >= 6) return ;//6帧绘制就结束了ctx.drawImage(this.image, this.frm *this.width, 0 , this.width, this.height, 0, 0, this.width, this.height);ctx.restore(); this.dis++;if (this.dis >= 10) {//10个间隔换图this.dis = 0;this.frm++;}};

 4、设计主程序

用于实现游戏背景界面,加载游戏相关图片,完成子弹发射、敌机移动,碰撞检测等功能,实现代码如下所示:

 var canvas = document.getElementById("myCanvas");var context = canvas.getContext("2d");document.addEventListener("keydown", onkeydown);var plans = [];         //敌机对象数组var bullets = [];        //子弹对象数组var bombs = [];        //爆炸对象数组var score=0;var overflag = false; //游戏是否结束,true为结束var mBitposY0, mBitposY1; /** 屏幕的宽高* */var mScreenWidth = 320;var mScreenHeight = 480var myplane;//己方飞机var image = new Image();var image2 = new Image();var image3 = new Image();var image4 = new Image();var image5 = new Image();
//以下游戏背景的两张图片var background0 = new Image();background0.src = "map_0.png";var background1 = new Image();background1.src = "map_1.png";

init()初始化游戏背景的两张图片的初始位置,updateBg()通过这两张背景图片的不断下移和切换实现游戏背景动态移动效果,实现代码如下所示:

function init() {/** 游戏背景* *//** 第一张图片津贴在屏幕(0,0)点,第二张图片在第一张图片上方* */mBitposY0 = 0;mBitposY1 = -mScreenHeight;        }function updateBg() {/** 更新游戏背景图片实现向下滚动效果**/mBitposY0 += 5;mBitposY1 += 5;if (mBitposY0 == mScreenHeight) {mBitposY0 = -mScreenHeight;}if (mBitposY1 == mScreenHeight) {mBitposY1 = -mScreenHeight;}}image.src = "plan.png";//自己飞机图片image.onload = function () {};image2.src = "bomb.png";//爆炸图片image2.onload = function () {};image3.src = "enemy.png";//敌机图片

图片加载成功后,通过定时每3秒产生1架敌机,在另一个定时器中不断更新背景图片位置,画自己方飞机和敌机,并检测是否敌机碰到玩家自己飞机(则游戏结束)或者子弹碰到敌机,最后绘制爆炸对象,实现游戏逻辑。

如果子弹碰撞到敌机,则产生爆炸对象,从敌机数组plans中删除该敌机,从子弹数组bullets中删除碰撞的子弹。如果没击中敌机,再判断子弹是否飞出屏幕上方,飞出屏幕上方则从数组bullets中删除碰撞的子弹。实现代码如下所示:

image3.onload = function () {myplane = new Plan(image, 300 * Math.random(), 400, 6); //6幅图片init(); //初始化背景地图位置plan_interval = setInterval(function () {plans.push(new Plan(image3, 300 * Math.random(), 20 * Math.random(), 2)); //2幅图片}, 3000); //3秒产生1架敌机setInterval(function () {context.clearRect(0, 0, 320, 480);//画地图//context.drawImage(background, 0, 0);context.drawImage(background0, 0, mBitposY0);context.drawImage(background1, 0, mBitposY1);updateBg();//更新背景图片位置//画自己方飞机if (!overflag)//游戏没有结束myplane.draw2(context); //原地不动//画敌人飞机for (var i = plans.length - 1; i >= 0; i--) {if (plans[i].Y() > 400) //敌机飞到底部则消失plans.splice(i, 1); //删除敌机elseplans[i].draw(context);}//画子弹for (var i = bullets.length - 1; i >= 0; i--) {if (bullets[i].Y() < 0)bullets.splice(i, 1); //删除子弹elsebullets[i].draw(context);}//碰撞检测//判断敌机碰到玩家自己飞机for (var i = plans.length - 1; i >= 0; i--) {e1 = plans[i];if (e1 != null && myplane != null && myplane.hitTestObject(e1)) {clearInterval(plan_interval); //清除定时器,不再产生敌机plans.splice(i, 1); //删除敌机bombs.push(new Bomb(image2, myplane.x, myplane.y));//bomb_interval=setInterval(function () {//    bomb.draw2(context);//原地不动//}, 1000 / 60);                   message_txt.innerHTML = "敌机碰到玩家自己飞机,游戏结束";overflag = true;}}//判断子弹碰到敌机for (var j = bullets.length - 1; j >= 0; j--) {var b1 = bullets[j];for (var i = plans.length - 1; i >= 0; i--) {e1 = plans[i];if (e1 != null && b1 != null && b1.hitTestObject(e1))//击中敌机{plans.splice(i, 1); //删除敌机bullets.splice(i, 1); //删除此颗子弹bombs.push(new Bomb(image2, b1.x, b1.y - 36));message_txt.innerHTML = "敌机被击中,加20分";score += 20;score_txt.innerHTML = "分数:" + score + "分";}}}//画爆炸for (var i = bombs.length - 1; i >= 0; i--) {if (bombs[i].frm >= 6)bombs.splice(i, 1); //删除爆炸elsebombs[i].draw2(context);}}, 1000 / 60);};image4.src = "bullet.png";//子弹图片image4.onload = function () {};

用户按键控制飞机上下左右移动,及空格发射子弹。onkeydown(e)响应用户的按键操作,修改玩家自己飞机的坐标,如下所示:

function onkeydown(e) {if (e.keyCode==32) {//空格//发射子弹bullets.push(new Bullet(image4, myplane.x, myplane.y-36));//}else if (e.keyCode==37) {//向左myplane.move(-10,0);}else if (e.keyCode==39) {//向右myplane.move(10,0);}else if (e.keyCode==38) {//向上myplane.move(0,-10);}else if (e.keyCode==40) {//向下myplane.move(0,10);}}

5、游戏页面

实现代码如下所示:

<!DOCTYPE html>
<html>
<head>
<title>飞机大战2017</title>
<meta charset="utf-8">
</head>
<body>
<canvas id="myCanvas" width="320" height="480" style="border:solid">
你的浏览器不支持canvas画布元素,请更新浏览器获得演示效果。
</canvas>
<div id="message_txt" style="display:block;">飞机大战</div>
<div id="score_txt" style="display:block;">分数:0分</div>
</body>
</html>

项目整理来源于:清华计算机学堂

项目源码下载:关注微信公众号,回复关键字:飞机射击游戏,获取项目资源~

基于HTML的飞机射击游戏相关推荐

  1. 有图有真相,分享一款网页版HTML5飞机射击游戏

    本飞机射击游戏是使用HTML5代码写的,尝试通过统一开发环境(UDE)将游戏托管在MM应用引擎,直接生成了网页版游戏,游戏简单易上手,非常适合用来当做小休闲打发时间. 游戏地址:http://flyg ...

  2. 有图有真相,网页版HTML5飞机射击游戏

    本飞机射击游戏是使用HTML5代码写的,尝试通过统一开发环境(UDE)将游戏部署托管在MM应用引擎,直接生成了网页版游戏,游戏简单易上手,非常适合用来当做小休闲打发时间.   游戏地址:http:// ...

  3. 基于Java的飞机大战游戏的设计与实现论文

    源码下载 http://www.byamd.xyz/hui-zong-1/ 摘 要 现如今,随着智能手机的兴起与普及,加上4G(the 4th Generation mobile communicat ...

  4. 基于Java的飞机大战游戏的设计与实现(含源文件)

    欢迎添加微信互相交流学习哦! 项目源码:https://gitee.com/oklongmm/biye 基于Java的飞机大战游戏的设计与实现 摘   要 现如今,随着智能手机的兴起与普及,加上4G( ...

  5. unity太空飞机射击游戏

    unity太空飞机射击游戏 有分数和生命值,飞机可以对其他飞行物进行射击,分数提高后飞机可以升级,具体情况如下图: 点我下载资源

  6. unity3D期末作业-太空飞机射击游戏

    unity3D期末作业-太空飞机射击游戏 unity 3D期末作业-太空飞机射击游戏,飞机可上下左右移动并发射子弹,有背景音乐,子弹有打击音效,有爆炸声,可以记录分数,飞机碰到障碍物时会爆炸游戏结束, ...

  7. 毕业设计 基于Java的飞机大战游戏的设计与实现

    文章目录 前言 一.项目设计 1. 模块设计 功能需求 游戏状态控制功能模块 游戏难度的调整模块 游戏界面绘画功能模块 玩家游戏控制功能模块 2. 实现效果 二.部分源码 项目源码 前言 今天学长向大 ...

  8. 基于Java的飞机大战游戏的设计与实现

    项目介绍 飞机大战主要需要我方飞机和敌方飞机,还有子弹,特殊nPC,开始背景,结束背景,以及背景音乐.我方飞机可以随意移动,敌方飞机无规律出现.游戏玩家通过鼠标移动控制飞机移动,我方飞机在游戏开始时就 ...

  9. 飞机大战游戏python_基于Python的飞机大战游戏

    基于 Python 的飞机大战游戏 杨铠 [期刊名称] <电脑迷> [年 ( 卷 ), 期] 2017(000)021 [摘要] 我们每天都享受到科技带来的好处 , 了解计算机编程对每个人 ...

最新文章

  1. ubuntu下配置华为交换机s2016
  2. Android NullPointerException解决方法(空指针异常)
  3. Report_报表中Ref Cursor数据源的概念和用法(案例)
  4. JDK 8 Javadoc调整了方法列表
  5. mysql3错误_第3行MYSQL语法错误
  6. SpringCloud介绍(一)
  7. Java与算法之(2) - 快速排序
  8. Spring整合MyBatis之SqlSession对象的产生
  9. python控制电机正反转_树莓派Python控制步进电机
  10. VirtualBox 安装增强功能
  11. 2020年10月最新免费加速下载百度网盘文件方法
  12. (转)Sublime Text 2 设置文件详解
  13. Excel数组与数组公式
  14. Android实现网络图片app
  15. java获取输入的地点的经纬度和编码等信息
  16. 基于微信小程序的师生答疑交流平台APP-计算机毕业设计
  17. python爬虫数据挖掘_Python网页爬虫文本处理科学计算机器学习数据挖掘兵器谱...
  18. webapi json返回值null替换为空字符串
  19. 闲鱼基于 Flutter 的移动端跨平台应用实践
  20. python关键词采集,(2017)新版爱站关键词采集Python脚本

热门文章

  1. qt QPF 字体各个字段的意义
  2. 印象笔记转移本地数据库文件的方法(挽救方法)
  3. 电脑初次开机不能上网,重启或者插拔网线才可以联网
  4. 【STM32单片机】2048游戏设计
  5. 酷日报:5月12日Web3业界日间重要消息大汇总
  6. 如何word/wps插入电子签名
  7. RoBERTa:A Robustly Optimized BERT Pretraining Approach(2019-7-26)
  8. 如何使用计算机闹铃,电脑闹钟小工具、电脑闹钟小工具怎么用
  9. doxygen 命令_学习用 doxygen 生成源码文档
  10. 软件开发人员如何与测试人员相处