1. 项目概述
这个游戏要求玩家控制飞机发射子弹,消灭下降的幽灵,如果全部消灭了则游戏成功,否则,游戏失败。
最终效果图:

2. 项目结构

这个项目主要是通过 JS+CSS+HTML 实现的,HTML 主要负责界面结构显示,CSS 主要是负责修改样式,JS 负责动态渲染。plane 文件夹内主要有三个文件夹,css 文件夹是用来存放 CSS 样式文件,imgs 文件是用来存放项目有关图片素材,js 文件夹主要用来存放 JS 文件。
3. 项目实战
3.1 页面渲染
3.1.1 初始页面渲染
首先,我们要有一个初始界面,这个界面里面的内容,我们可以通过 JS 进行动态渲染。
HTML 结构部分如下。
首先,最外面应该会有一个大盒子用来装我们游戏所有的东西,比如说,不同的页面、图片等,在这个大盒子里面有一个盒子,这个盒子,我们就可以把它当做是我们的战场。如下图分析。

用 HTML 代码描述上图结构:
<div class="wrap">
<div id="box" class="box"></div>
</div>
对应 CSS 代码如下:
body{ background-color: black; }
/* 游戏外盒子 */
.wrap{ width: 300px; height: 500px; border: 10px solid #fff; margin: 10px auto; }
/* 战场盒子 */
.box{ width: 100%; height: 100%;}
接着,我们通过 JS 渲染,在 box 盒子里面增加标题以及不同等级的按钮,当鼠标移到每一个按钮的时候,按钮背景颜色由白色变成 #d3c940 这种颜色。
效果图如下:

对应 JS 代码:
let oBox=document.querySelector("#box");//获取战场盒子
// 初始化页面
function init(){
// 设置背景图片 注意:路径要以html文件作为参照
oBox.style.cssText="background:url('imgs/bg_2.jpg') no-repeat center/cover;"
// 创建标题
let h1=document.createElement("h1");
h1.className='title' ; //给标题添加class 演示属性
h1.innerHTML="霹雳战机v1.0"; //给标题添加文字
oBox.appendChild(h1); //给战场盒子增加标题节点
// 创建游戏入口
let optionArr=['简单模式','中级难度','高级难度'];
optionArr.forEach(function(option,b){
let oDiv=document.createElement('div');
oDiv.innerText=option;
oDiv.className='option';
oBox.appendChild(oDiv);
}) }
init(); //运行
3.2 布置战场页面
当点击任意等级入口按钮的时候,要清扫战场盒子现有的东西,比如说,现在战场上的盒子、战场上的按钮。
//给每一个按钮都添加点击事件,进入不同的等级
oDiv.onclick=function(ev){
oBox.innerHTML="";
startGame();//开始游戏
};
oDiv.className='option';
oBox.appendChild(oDiv);
}) }
init(); //运行
4. 游戏部分
游戏开始的时候会出发创建敌军军队与我军军队:
// 游戏部分
function startGame(){
enemyAirs(); //创建敌军军队
ownAirs(); //创建我军军队
}
4.1 敌军生成
最终效果图:

根据不同的等级控制创建敌机数量的速度(效果图如下):

enemyAirs 函数中使用定时器生成幽灵军队:

创建怪兽图片节点,设置怪兽图片参数,将怪兽图片添加到战场上。

修改怪兽图片的开始位置,实现产生所有的怪兽图片都在屏幕顶部的地方,采用父相子绝的方法,给战场盒子添加相对定位,给每个怪兽图片添加绝对定位。

CSS 文件添加两处代码:

通过随机设置怪兽图片在顶部水平方向位置生成。

注意,为什么盒子的宽度是 300,却是要乘以 260 而不是 300. 因为,飞机自身有宽度的,而飞机的自身宽度会影响影响效果,因此要在 300 基础上减去飞机自身宽度,所以是 260。

设置飞机下降,飞机就下降这个动作就会涉及到一个下降的速度,有些飞机下降比较快,有些飞机下降比较慢,如何去描述呢?我们可以使用随机函数来描述。

在 JS 里面我们可以添加如下代码:

但是,还是有一个问题,就是飞机超出了战场,我们需要限定飞机下降的最长距离。

但是,问题又来了,怪兽超出了的部分显示出来了,接下来要隐藏掉超过的部分。

4.2 我军生成
最终效果图如下:

在战场上新建一个图片元素,设置这个图片元素的长度和宽度分别是 50px。


现在的飞机在左上角(如上图显示),接下来,我们要把飞机放置到底部的正中间的位置,分别求出飞机距离顶部的距离,以及飞机距离左边的距离,要记得减去飞机自身的高度以及二分之一的自身的宽度。

现在的飞机是无法移动的,接下来,我们要想方法让飞机随着键盘左右方向进行移动,要注意的是,飞机在上下左右移动的时候是不允许超出战场的哦,效果图如下:

对应的 JS 代码如下:

4.3 子弹生成

新建一个生成子弹的函数,原理跟敌机差不多,因为子弹是随着我军飞机的行动的,所以,子弹要在我军飞机生成的时候生成,然后就是定位的时候以我军飞机位置作为参考。

4.4 检测碰撞
要判断两个物体是否碰撞,前提要计算这两个物体的位置关系,我们只需要判断矩形 1 和矩形 2 是否存在距离,我们可以看下面的图:

从上图中,我们可以看到矩形 1 和矩形 2 之间有四种可能没有发生碰撞:
- 矩形 2 的右侧和矩形 1 的左侧有一定的距离
- 矩形 2 的左侧和矩形 1 的右侧有一定的距离
- 矩形 2 的底部和矩形 1 的顶部有一定的距离
- 矩形 2 的顶部和矩形 1 的底部有一定的距离
当符合上面其中一种情况,则两个矩形没有发生碰撞。
在飞机发生碰撞这件事情当中,我们要考虑两种情况,一种是飞机跟幽灵之间的碰撞,另外一种是子弹跟幽灵之间发生的碰撞,这时,我们可以碰撞这个事件提炼成为一个函数。

4.1 判断子弹是否跟幽灵发生碰撞
在创建子弹的过程中,就要判断每一粒的子弹是够跟幽灵发生碰撞,如果发生碰撞了,则要删除相关的节点以及相关的动画。

在添加删除当前子弹的动画的时候,要在创建子弹的时候,用一个变量存储当前的子弹的动画。

4.2 判断幽灵是够跟我军发生碰撞
在敌军下落的过程中,要判断幽灵是否跟我军发生碰撞,如果发生碰撞了,也要删除相关的动画以及节点。


4.3 碰撞动画优化
现在,我们对碰撞动画进一步优化。
当我军不存在的时候,发射出去的子弹与剩下的幽灵运动变为静止。


当子弹碰到幽灵的时候,会产生烟雾效果,当我军碰到幽灵的时候,会产生火焰效果。
首先,创建一个爆炸函数:

接着在以下两处碰撞添加爆炸参数:


注意,在添加函数过程中,函数要在移除节点之前插入,因为,节点移除了,就找不到节点了。
5. 游戏结果
我军爆炸后,会显示一个游戏结果界面,游戏结果界面会显示 Game over 以及重新开始的按钮。
首先,我们要创建一个结果函数,在这个结果函数里面,我们会新建一个结果界面 div。

对应的 CSS 代码如下:

玩游戏少不了分数统计,我们可以给 oBox 添加一个分数属性,在子弹击中幽灵的时候可以进行分数累加:

在结果界面上面添加一个段落元素,用来显示分数,该段落的 JS 代码与 CSS 代码如下。
JS 代码:

CSS 代码:
.oscore{
margin-top: 20px;
text-align: center;
font-size: 20px;
color: #fff;}
源码链接:
提取码:ypmy
这里发布一条官宣:如果对 JavaScript 基础知识不是很熟悉或者学习完 JavaScript 知识后想完成个人博客系统项目的宝宝们,可以关注老司机,老司机正在编写一系列课程,名字叫《Node.js 项目实战 01:JavaScript 快速开发博客网站前后端》,文中还会涉及到更多的案例,比如小球圆周运动、无缝图片轮播、仿朋友圈发表、推箱子游戏等等,最终还会图解使用 Node 框架开发个人博客系统,干货满满,请多多支持哦!
本文首发于 GitChat,未经授权不得转载,转载需与 GitChat 联系。