JavaScript打飞机小游戏
又到了每日分享时间了,今天分享的内容为:JavaScript打飞机小游戏
效果图:
20191009101114.jpg实现逻辑:
第一步:实现页面的排版、布局
1.1 准备打飞机游戏需要使用到的图片
1.2 开始游戏界面
1.3 进入游戏的界面
1.3.1 己方飞机
1.3.2 敌方飞机
1.3.3 己方飞机发射的子弹
第二步:开始游戏
2.1 点击开始游戏按钮,进入到游戏界面
2.2 摁下空格键,实现己方飞机跟随鼠标的移动==》游戏的开始
2.3 第二次摁下空格键时,实现己方飞机的暂停移动==》游戏的暂停
2.4 以此类推,实现开始和暂停的交换
第三步:开始游戏之后的发射子弹
3.1 定时创建子弹:
3.1.1 单位时间内创建子弹的数量
3.1.2 开始游戏和暂停游戏时:暂停游戏后,不能再创建子弹;再次开始游戏时,不能存在多个创建子弹的定时器==》把上一次创建子弹的定时器给清除或者不再开启定时器
3.2 制造子弹
3.2.1 制造子弹时,确定子弹的位置
3.2.2 根据当前己方飞机的位置
3.2.3 把子弹追加到文档中去
3.3 子弹的运动
3.3.1 子弹的top值是-子弹的高度时,删除子弹,清除定时器
3.4 子弹消失
3.4.1 子弹飞出游戏界面
3.4.2 清除子弹==》每一颗飞出到游戏界面之外的子弹,肯定是第一个创建的子弹(当前子弹所在父元素下的第一个子元素)
第四步:开始游戏之后的创建敌机
4.1 定时创建敌机
4.1.1 单位时间内创建敌机的数量
4.1.2 暂停之后不能重复性的开启创建敌机的定时器
4.1.3 敌机的概率出现:大、中、小三种敌机
===》小:75% 中:20% 大:5%
4.2 制造敌机
4.3 敌机的运动
4.4 敌机的消失
第五步:实现游戏的暂停
5.1 敌机运动速度的控制
5.2 实现游戏的暂停
5.2.1 清除己方飞机的移动
5.2.2 清除创建敌机
5.2.3 清除创建子弹
5.2.4 清除每颗子弹上的运动
5.2.5 清除每架敌机上的运动
第六步:实现开始游戏之后的背景图的运动
6.1 改变的是背景图的background-position-y的值
6.2 游戏界面的高度568,每运动568px是一个循环
第七步:检测子弹和敌机的碰撞
7.1 每一个敌机都是运动的,每一颗子弹也是运动的==》在每一架敌机运动时,检测和所有游戏界面内存在的子弹的碰撞
7.2 创建全局变量:把当前游戏界面内存在的所有的子弹放入到该变量里
7.3 敌机运动的过程中,检测和每一颗子弹的碰撞
7.4 子弹和敌机发生碰撞时,子弹消失
7.4.1 把该子弹元素删除掉
7.4.2 把该子弹元素从全局变量集合里删除
7.5 敌机和子弹发生碰撞时,敌机血量减少==》每一颗子弹消耗的血量100
7.6 敌机的血量为0时,删除敌机元素???
第八步:实现敌机的爆炸效果
8.1 替换爆炸图片
8.2 区分存活的敌机和死亡敌机(爆炸过程中的敌机)==》标记每一架敌机的存活状态
8.3 延时删除敌机元素==》显示爆炸效果
8.4 在创建敌机时,删除敌机集合中的死亡敌机
第九步:实现游戏的得分
第十步:检测己方飞机和敌机的碰撞
10.1 一对多的关系:敌机运动,己方飞机运动
10.2 在每一架敌机运动的过程中检测
10.3 碰撞的原理
第十一步:游戏结束
11.1 清除掉当前页面上的所有的定时器
11.2 清除掉所有子弹上的定时器以及删除所有的子弹元素
11.3 清除掉素有敌机上的定时器以及删除所有的敌机元素
11.4 清空子弹和敌机的集合
11.5 删除己方飞机上的移动事件
11.6 回到游戏开始界面
一、html代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>javascript 原生打飞机游戏</title>
<link rel="stylesheet" href="style.css">
<script src="plane.js"></script>
</head>
<body>
<div id="game">
<div id="gameStart">
<span>开始游戏</span>
</div>
<div id="gameEnter">
<div id="myPlane">
<img src="image/my.gif" alt="">
</div>
<div id="bullets">
</div>
<div id="enemys"></div>
<div id="scores">
<p>得分:<span>0</span> 分</p>
</div>
</div>
</div>
</body>
</html>
二、css代码
*{
margin: 0;
padding: 0;
}
#game{
width: 320px;
height: 568px;
margin: auto;
overflow: hidden;
}
#gameStart{
width: 100%;
height: 100%;
background: url(image/ks.png);
position: relative;
/*display: none;*/
}
#gameStart span{
width: 160px;
height: 40px;
display: block;
background: rgba(196,201,202);
border: 4px solid #666;
box-sizing: border-box;
text-align: center;
line-height: 32px;
font-size: 24px;
font-weight: bolder;
position: absolute;
left: 80px;
bottom: 200px;
cursor: pointer;
}
#gameStart span:hover{
color: #fff;
}
#gameEnter{
width: 100%;
height: 100%;
background: url(image/background_1.png);
position: relative;
display: none;
}
#myPlane{
width: 66px;
height: 80px;
position: absolute;
left: 127px;
bottom: 0;
cursor: pointer;
}
#myPlane{
width: 66px;
height: 80px;
}
#myPlane img{
cursor: move;
}
#bullets,#enemys{
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
}
.b{
width: 6px;
height: 14px;
position: absolute;
}
.e{
position: absolute;
}
#scores{
width: 100%;
height: 40px;
line-height: 40px;
font-size: 24px;
font-weight: bolder;
padding: 0 20px;
}
#scores p{
text-align: right;
width: 80%;
}
三、js代码
;window.onload = function(){
// 获取标签元素的方法
function $(idName){
return document.getElementById(idName);
}
// 获取样式使用最终值的函数
function getStyle(ele,attr){
var res = null;
if(ele.currentStyle){
res = ele.currentStyle[attr];
}else{
res = window.getComputedStyle(ele,null)[attr];
}
return parseFloat(res);
}
// 获取需要使用到的标签元素
var game = $("game")
// 游戏开始的界面
, gameStart = $("gameStart")
// 进入游戏的界面
, gameEnter = $("gameEnter")
, myPlane = $("myPlane")
, bulletsP = $("bullets")
, enemysP = $("enemys")
, s = $("scores").firstElementChild.firstElementChild;
// 获取需要使用到的元素样式
// 1、获取游戏界面的宽高
var gameW = getStyle(game,"width")
, gameH = getStyle(game,"height");
// 2、游戏界面的左上外边距
var gameML = getStyle(game,"marginLeft")
, gameMT = getStyle(game,"marginTop");
// 3、获取己方飞机的宽高
var myPlaneW = getStyle(myPlane,"width")
, myPlaneH = getStyle(myPlane,"height");
// 4、子弹的宽高
var bulletW = 6
, bulletH = 14;
// 声明需要使用到的全局变量
var gameStatus = false // 当前的游戏状态
, a = null // 创建子弹的定时器
, b = null // 创建敌机的定时器
, c = null // 背景图运动的定时器
, backgroundPY = 0 // 背景图y轴的值
, bullets = [] // 所有子弹元素的集合
, enemys = [] // 所有敌机元素的集合
, scores = 0 // 得分
;
// 开始游戏
gameStart.firstElementChild.onclick = function(){
gameStart.style.display = "none";
gameEnter.style.display = "block";
// 给当前的文档添加键盘事件
document.onkeyup = function(evt){
var e = evt || window.event;
// 获取到键盘的键值
var keyVal = e.keyCode;
if(keyVal == 32){
if(!gameStatus){
// 初始化得分
scores = 0;
// 开始游戏
this.onmousemove = myPlaneMove;
// 实现开始游戏之后背景图的运动
bgMove();
// 实现射击
shot();
// 出现敌机
appearEnemy();
// 暂停游戏之后的开始游戏
// 子弹的继续运动
if(bullets.length != 0) reStart(bullets,1);
// 敌机的继续运动
if(enemys.length != 0) reStart(enemys);
}else{
// 暂停游戏
this.onmousemove = null;
// 清除创建敌机和创建子弹的定时器
clearInterval(a);
clearInterval(b);
clearInterval(c);
a = null;
b = null;
c = null;
// 清除所有子弹和所有敌机上的运动定时器
clear(bullets);
clear(enemys);
}
gameStatus = !gameStatus;
}
}
}
// 己方飞机的移动
function myPlaneMove(evt){
var e = evt || window.event;
// 获取鼠标移动时的位置
var mouse_x = e.x || e.pageX
, mouse_y = e.y || e.pageY;
// 计算得到鼠标移动时己方飞机的左上边距
var last_myPlane_left = mouse_x - gameML - myPlaneW/2
, last_myPlane_top = mouse_y - gameMT - myPlaneH/2;
// 控制飞机不能脱离当前的游戏界面
if(last_myPlane_left <= 0){
last_myPlane_left = 0;
}else if(last_myPlane_left >= gameW - myPlaneW){
last_myPlane_left = gameW - myPlaneW;
}
if(last_myPlane_top <= 0){
last_myPlane_top = 0;
}else if(last_myPlane_top >= gameH - myPlaneH){
last_myPlane_top = gameH - myPlaneH;
}
myPlane.style.left = last_myPlane_left + "px";
myPlane.style.top = last_myPlane_top + "px";
}
// 单位时间内创建子弹
function shot(){
if(a) return ;
a = setInterval(function(){
// 创建子弹
createBullet();
},100);
}
// 制造子弹
function createBullet(){
var bullet = new Image();
bullet.src = "image/bullet1.png";
bullet.className = "b";
// 创建每一颗子弹都需要确定己方飞机的位置:
var myPlaneL = getStyle(myPlane,"left")
, myPlaneT = getStyle(myPlane,"top");
// 确定创建子弹的位置
var bulletL = myPlaneL + myPlaneW/2 - bulletW/2
, bulletT = myPlaneT - bulletH;
bullet.style.left = bulletL + "px";
bullet.style.top = bulletT + "px";
bulletsP.appendChild(bullet);
bullets.push(bullet);
move(bullet,"top");
}
// 子弹的运动:运动函数(匀速运动)
function move(ele,attr){
var speed = -8;
ele.timer = setInterval(function(){
var moveVal = getStyle(ele,attr);
// 子弹运动出游戏界面:清除子弹的定时器,删除子弹元素
if(moveVal <= -bulletH){
clearInterval(ele.timer);
ele.parentNode.removeChild(ele);
bullets.splice(0,1);
}else{
ele.style[attr] = moveVal + speed + "px";
}
},10);
}
// 创建敌机数据对象
var enemysObj = {
enemy1: {
width: 34,
height: 24,
score: 100,
hp: 100
},
enemy2: {
width: 46,
height: 60,
score: 500,
hp: 800
},
enemy3: {
width: 110,
height: 164,
score: 1000,
hp: 2000
}
}
// 创建敌机的定时器
function appearEnemy(){
if(b) return ;
b = setInterval(function(){
// 制造敌机
createEnemy();
// 删除死亡敌机
delEnemy();
},1000);
}
// 制造敌机的函数
function createEnemy(){
// 敌机出现概率的数据
var percentData = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,3];
// 敌机的类型
var enemyType = percentData[Math.floor(Math.random()*percentData.length)];
// 得到当前随机敌机的数据
var enemyData = enemysObj["enemy" + enemyType];
// 创建敌机所在的元素
var enemy = new Image(enemyData.width,enemyData.height);
enemy.src = "image/enemy" + enemyType + ".png";
enemy.t = enemyType;
enemy.score = enemyData.score;
enemy.hp = enemyData.hp;
enemy.className = "e";
enemy.dead = false; // 敌机存活
// 确定当前敌机出现时的位置
var enemyL = Math.floor(Math.random()*(gameW - enemyData.width + 1))
, enemyT = -enemyData.height;
enemy.style.left = enemyL + "px";
enemy.style.top = enemyT + "px";
enemysP.appendChild(enemy);
enemys.push(enemy);
enemyMove(enemy,"top");
}
// 敌机的运动
function enemyMove(ele,attr){
var speed = null;
if(ele.t == 1){
speed = 1.5;
}else if(ele.t == 2){
speed = 1;
}else if(ele.t == 3){
speed = 0.5;
}
ele.timer = setInterval(function(){
var moveVal = getStyle(ele,attr);
if(moveVal >= gameH){
clearInterval(ele.timer);
enemysP.removeChild(ele);
enemys.splice(0,1);
}else{
ele.style[attr] = moveVal + speed + "px";
// 每一架敌机运动时,检测和每一颗子弹的碰撞
danger(ele);
// 检测碰撞
gameOver();
}
},10);
}
// 清除所有敌机和所有子弹上的运动定时器
function clear(childs){
for(var i=0;i<childs.length;i++){
clearInterval(childs[i].timer);
}
}
// 暂停游戏之后的开始游戏
function reStart(childs,type){
for(var i=0;i<childs.length;i++){
type == 1 ? move(childs[i],"top") : enemyMove(childs[i],"top");
}
}
// 开始游戏之后的背景图的运动
function bgMove(){
c = setInterval(function(){
backgroundPY += 0.5;
if(backgroundPY >= gameH){
backgroundPY = 0;
}
gameEnter.style.backgroundPositionY = backgroundPY + "px";
},10);
}
// 检测子弹和敌机的碰撞
function danger(enemy){
for(var i=0;i<bullets.length;i++){
// 得到子弹的左上边距
var bulletL = getStyle(bullets[i],"left")
, bulletT = getStyle(bullets[i],"top");
// 得到敌机的左上边距
var enemyL = getStyle(enemy,"left")
, enemyT = getStyle(enemy,"top");
// 得到敌机的宽高
var enemyW = getStyle(enemy,"width")
, enemyH = getStyle(enemy,"height");
var condition = bulletL + bulletW >= enemyL && bulletL <= enemyL + enemyW && bulletT <= enemyT + enemyH && bulletT + bulletH >= enemyT;
if(condition){
//子弹和敌机的碰撞:删除子弹
// 1、先清除碰撞子弹的定时器
clearInterval(bullets[i].timer);
// 2、删除元素
bulletsP.removeChild(bullets[i]);
// 3、从集合中删除子弹
bullets.splice(i,1);
// 4、子弹和敌机发生碰撞后,敌机血量减少,血量为0时,删除敌机
enemy.hp -= 100;
if(enemy.hp == 0){
// 删除敌机
clearInterval(enemy.timer);
// 替换爆炸图片
enemy.src = "image/bz" + enemy.t + ".gif";
// 标记死亡敌机
enemy.dead = true;
// 计算得分
scores += enemy.score;
s.innerHTML = scores;
}
}
}
}
// 在创建敌机时,延时删除掉集合和文档中的死亡敌机
function delEnemy(){
for(var i=enemys.length - 1;i>=0;i--){
if(enemys[i].dead){
(function(index){
// 从文档中删除死亡敌机元素
enemysP.removeChild(enemys[index]);
// 从集合中删除死亡敌机元素
enemys.splice(index,1);
})(i)
}
}
}
// 飞机碰撞,游戏结束
function gameOver(){
for(var i=0;i<enemys.length;i++){
if(!enemys[i].dead){ // 游戏机界面内存活的敌机
// 检测碰撞
// 1、获取敌机的左上边距
var enemyL = getStyle(enemys[i],"left")
, enemyT = getStyle(enemys[i],"top");;
// 2、获取敌机的宽高
var enemyW = getStyle(enemys[i],"width")
, enemyH = getStyle(enemys[i],"height");
// 3、获取己方飞机的左上边距
var myPlaneL = getStyle(myPlane,"left")
, myPlaneT = getStyle(myPlane,"top");
var condition = myPlaneL + myPlaneW >= enemyL && myPlaneL <= enemyL + enemyW && myPlaneT <= enemyT + enemyH && myPlaneT + myPlaneH >= enemyT;
if(condition){ // 己方飞机和敌机的碰撞
// console.log("碰撞了...");
// 清除定时器:创建子弹的定时器、创建飞机的定时器、游戏背景图的定时器
clearInterval(a);
clearInterval(b);
clearInterval(c);
a = null;
b = null;
c = null;
// 删除子弹和敌机元素
remove(bullets);
remove(enemys);
// 集合清空
bullets = [];
enemys = [];
// 清除己方飞机的移动事件
document.onmousemove = null;
// 提示得分:
alert("Game over: " + scores + "分");
// 回到游戏开始界面
gameStart.style.display = "block";
gameEnter.style.display = "none";
myPlane.style.left = "127px";
myPlane.style.top = gameH - myPlaneH + "px";
}
}
}
}
// 删除元素
function remove(childs){
for(var i = childs.length - 1;i>=0;i--){
clearInterval(childs[i].timer);
childs[i].parentNode.removeChild(childs[i]);
}
}
}
老规矩,附带教学视频:https://www.3mooc.com/front/couinfo/214