目录
本篇博文将分享一篇基于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;
-
else
-
return 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;
-
else
-
return 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;
-
};
。。。。。。。。。。。。。。。。。
版权原因,完整文章,请参考如下:基于HTML的飞机射击游戏