目录
效果展示
HTML+CSS+JS做打飞机小游戏
开始界面 选择你喜欢的飞机开始游戏
按下空格键 开始/暂停
有三种敌机
可以设置飞机生命值,生命值耗尽,GAME OVER!
tips:背景是流动的,更有氛围感~~
源码
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="./new.css" />
<title>飞机大战</title>
</head>
<body>
<!-- 游戏界面 -->
<div id="game">
<!-- 游戏开始界面 -->
<div id="gameStart">
<p>请选择您的飞机</p>
<div id="mePlane">
<img id="0" src="./images/f1.png" alt="" />
<img id="1" src="./images/f2.png" alt="" />
<img id="2" src="./images/f3.png" alt="" />
<img id="3" src="./images/f4.png" alt="" />
<img id="4" src="./images/f5.png" alt="" />
<img id="5" src="./images/f6.png" alt="" />
</div>
<!-- 开始游戏按钮 -->
<div id="startBtn">
<img src="./images/start.png" alt="" />
</div>
</div>
<!-- 游戏进入界面 -->
<div id="gameEnter">
<div id="gameo"></div>
<!-- 我方飞机 66 x 80 -->
<div id="myPlane">
<img id="meBoom" src="./images/f1.png" />
</div>
<!-- 敌方飞机 -->
<div id="enemyPlaneBox">
<!-- <img src="./images/enemy1.png" /> -->
</div>
<!-- 子弹 -->
<div id="bulletsBox">
<!-- <img src="./images/bullet1.png" /> -->
</div>
</div>
<!-- 得分面板 -->
<div class="score-box">
<span>得分:</span>
<span id="score">0</span>
</div>
</div>
<script src="./plane.js">
</script>
</body>
</html>
CSS
* {
margin: 0;
padding: 0;
/* outline: 1px solid; */
}
#game {
width: 320px;
height: 568px;
margin-left: 200px;
position: relative;
overflow: hidden;
}
#gameStart {
width: 100%;
height: 100%;
background-image: url(./images/bg1.png);
background-size: 320px 568px;
position: absolute;
top: 0;
left: 0;
z-index: 1;
/* display: none; */
}
#startBtn {
width: 160px;
height: 40px;
/* border: 4px solid #666; */
/* background-color: aliceblue; */
display: flex;
justify-content: center;
align-items: center;
position: absolute;
top: 470px;
/* 水平居中 */
left: 50%;
transform: translateX(-50%);
}
#gameEnter {
width: 100%;
height: 100%;
background-image: url(./images/b4.jpg);
background-size: 400px 1000px;
position: absolute;
top: 0;
left: 0;
}
#myPlane {
width: 128px;
height: 128px;
position: absolute;
bottom: 0;
left: calc(50% - 64px)
/* transform: translateX(-50%); */
}
#enemyPlaneBox,
#bulletsBox {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
#startBtn:hover {
cursor: pointer;
}
.score-box {
position: absolute;
z-index: 999;
top: 10px;
left: 10px;
font-weight: bold;
color: yellow;
}
#mePlane>img {
width: 47.2px;
border: rgba(241, 214, 95, 0.5) 1px solid;
background-color: rgba(245, 250, 112, 0.2);
transition: 0.5s;
}
#mePlane>img:hover {
/* transform: scale(1.4); */
cursor: pointer;
}
#gameStart>p {
position: absolute;
top: 280px;
left: 100px;
line-height: 80px;
color: rgb(250, 161, 7);
font-weight: 600;
text-align: center;
}
#mePlane {
position: absolute;
top: 350px;
/* background-color:rgba(112,181,250,0.2); */
}
.active {
transform: scale(1.8);
border: red 1px solid;
}
#gameo{
height: 100%;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
}
JS
// 获取元素属性
function getStyleValue(dom, attr) {
return parseFloat(getComputedStyle(dom)[attr]);
}
// 获取元素节点
function $(idName) {
return document.getElementById(idName);
}
// 随机范围
function randomRange(min, max) {
return parseInt(Math.random() * (max - min + 1) + min);
}
// 创建id
let index = 0;
function createId() {
++index;
return index;
}
// 游戏
const mePlane = $("mePlane");
const game = $("game");
const gameMarginLeft = getStyleValue(game, "margin-left");
const gameMarginTop = getStyleValue(game, "margin-top");
const gameWidth = getStyleValue(game, "width");
const gameHeight = getStyleValue(game, "height");
const enemyPlaneBox = $("enemyPlaneBox");
const bulletsBox = $("bulletsBox");
const meBoom = $("meBoom");
// 游戏按钮
const startBtn = $("startBtn");
const gameStart = $("gameStart");
const gameEnter = $("gameEnter");
const score = $("score");
// 游戏的状态
let gameStatus = true;
// 所有的子弹
let allBullets = [];
// 所有的敌机
let allEnemyPlane = [];
// 创建子弹定时器
let createBulletsTimer = null;
// 创建敌机定时器
let createEnemyPlaneTimer = null;
// 检测碰撞定时器
let detectCollisionsTimer = null;
//背景定时器
let bgMoveTimer = null;
//敌机数据
enemyPlaneData = [
{
width: 34,
height: 38,
speed: 2,
hp: 2,
score: 2,
src: "./images/x.png",
fightSrc: "./images/小飞机挨.png",
bombSrc: "./images/xboom.png",
},
{
width: 97,
height: 75,
speed: 1.5,
hp: 5,
score: 5,
src: "./images/z.png",
fightSrc: "./images/中飞机挨.png",
bombSrc: "./images/zboom.png",
},
{
width: 110,
height: 164,
speed: 0.5,
hp: 10,
score: 10,
src: "./images/da.png",
fightSrc: "./images/大飞机挨.png",
bombSrc: "./images/daboom.png",
},
];
// console.log(enemyPlaneData[0])
/* 开始游戏 */
const myPlane = new MyPlane();
startBtn.onclick = function () {
// 让游戏开始界面隐藏
gameStart.style.display = "none";
// 进入游戏界面后 游戏才能开始
// 监听键盘按下
document.onkeyup = function (event) {
// 空格对应的key keyCode: 32
// 当按下空格键 游戏开始 再次点击空格 游戏停止
if (event.keyCode === 32) {
if (gameStatus) {
// 飞机跟随鼠标移动
myPlane.move();
// 定时创建子弹
createBullets();
// 定时创建飞机
createEnemyPlane();
// 恢复已创建子弹移动
restartBulletsMove();
restartAllEnemyPlaneMove();
detectCollisions();
bgMove();
} else {
gameStop();
}
gameStatus = !gameStatus;
}
};
};
function bgMove() {
const speed = 1;
bgMoveTimer = setInterval(() => {
const bgY = getStyleValue(gameEnter, "background-position-y");
const newY = bgY + speed;
gameEnter.style.backgroundPositionY = newY + "px";
}, 1000 / 60);
}
function bgStop() {
clearInterval(bgMoveTimer);
}
// 游戏停止
function gameStop() {
// 飞机停止移动
myPlane.stop();
// 停止所有子弹
stopBulletsMove();
stopAllEnemyPlaneMove();
// 停止创建子弹
stopCreateBullets();
stopCreateEnemyPlane();
stopDetectCollisions();
bgStop();
}
// 定时创建敌机
function createEnemyPlane() {
createEnemyPlaneTimer = setInterval(() => {
// allEnemyPlane.push(new EnemyPlane());
// 控制每种敌机数量
const plane = randomGetPlane();
allEnemyPlane.push(new EnemyPlane(plane));
}, 800);
}
//随机获取敌机 概率
function randomGetPlane() {
const arr = [];
//大飞机
arr.push(enemyPlaneData[2]);
//中飞机
for (let i = 1; i <= 4; i++) {
arr.push(enemyPlaneData[1]);
}
//小飞机
for (let i = 1; i <= 15; i++) {
arr.push(enemyPlaneData[0]);
}
// 随机下标
const randomIndex = randomRange(0, 19);
return arr[randomIndex];
// console.log(arr)
}
// 停止定时创建敌机
function stopCreateEnemyPlane() {
clearInterval(createEnemyPlaneTimer);
}
// 停止所有敌机运动
function stopAllEnemyPlaneMove() {
for (let i = 0; i < allEnemyPlane.length; ++i) {
const enemyPlane = allEnemyPlane[i];
enemyPlane.stop();
}
}
// 恢复所有敌机运动
function restartAllEnemyPlaneMove() {
for (let i = 0; i < allEnemyPlane.length; ++i) {
const enemyPlane = allEnemyPlane[i];
enemyPlane.move();
}
}
// 定时创建子弹
function createBullets() {
createBulletsTimer = setInterval(() => {
// 创建子弹
allBullets.push(new Bullet());
}, 150);
}
// 停止创建子弹
function stopCreateBullets() {
clearInterval(createBulletsTimer);
}
// 停止所有子弹运动
function stopBulletsMove() {
for (let i = 0; i < allBullets.length; ++i) {
const bullet = allBullets[i];
bullet.stop();
}
}
// 恢复所有子弹移动
function restartBulletsMove() {
for (let i = 0; i < allBullets.length; ++i) {
const bullet = allBullets[i];
bullet.move();
}
}
// console.log("1", meBoom.src);
//选择飞机
handleTabSwitching(0);
function handleTabSwitching(pIndex) {
// 把所有的tabs选中样式取消
const planeArr = document.querySelectorAll("#mePlane img");
for (let i = 0; i < planeArr.length; ++i) {
planeArr[i].className = "";
}
// tabs 选中
planeArr[pIndex].className = "active";
myPlane.dom.src = `./images/f${pIndex + 1}.png`;
meBoom.src = `./images/f${pIndex + 1}.png`;
}
mePlane.onclick = function (event) {
// 获取点中的目标
const target = event.target;
// 获取按钮的下标
const pIndex = parseInt(target.id);
handleTabSwitching(pIndex);
};
// 检测碰撞
function detectCollisions(pIndex) {
// 定制检测每一帧的画面
detectCollisionsTimer = setInterval(() => {
// 每一个敌机与子弹进行检测(多对多 双重循环)
for (let i = 0; i < allEnemyPlane.length; ++i) {
const enemyPlane = allEnemyPlane[i];
for (let j = 0; j < allBullets.length; ++j) {
const bullet = allBullets[j];
// 子弹和敌机 检测是否发生碰撞
const condition = collisions(bullet, enemyPlane);
// 当发生碰撞
if (condition) {
// console.log("碰撞");
// 敌机爆咋
enemyPlane.bomb();
// 删除子弹
bullet.remove();
}
}
// 判断敌机与我方飞机是否发生碰撞
const gameo=$("gameo")
const condition = collisions(myPlane, enemyPlane);
if (condition) {
// 处理碰撞后的逻辑 结束游戏
myPlane.bomb();
// console.log(myPlane.hp)
if (myPlane.hp === 0) {
let num = parseInt(myPlane.dom.src[10]);
console.log(num);
meBoom.src = `./images/fb${num}.png`;
// console.log("游戏结束");
gameo.innerHTML=`<img width="320px" src="./images/gameover.png" alt="" />`
setTimeout(() => {
gameOver();
}, 1000);
}
}
}
}, 1000 / 60);
}
// 检测是否碰撞的方法 返回Boolean
function collisions(bullet, enemyPlane) {
// 子弹和敌机 检测是否发生碰撞
const condition =
// 子弹left + 子弹宽度 > 敌机left
bullet.getLeft() + bullet.width > enemyPlane.getLeft() &&
// 子弹left < 敌机left + 敌机width
bullet.getLeft() < enemyPlane.getLeft() + enemyPlane.width &&
// 子弹top < 敌机top + 敌机高度
bullet.getTop() < enemyPlane.getTop() + enemyPlane.height &&
// 子弹top + 子弹高度 > 敌机top
bullet.getTop() + bullet.height > enemyPlane.getTop();
if (condition) {
return true; // 发生了碰撞
} else {
return false; // 没有发生碰撞
}
}
// 游戏结束(恢复到原来的样子)
function gameOver() {
// 回到游戏界面
gameStart.style.display = "block";
document.onkeyup = null;
// 游戏停止(清除所有定时器)
gameStop();
// 清除所有页面的飞机和子弹
enemyPlaneBox.innerHTML = "";
bulletsBox.innerHTML = "";
// 清除所有的飞机和子弹对象
allBullets = [];
allEnemyPlane = [];
// 游戏状态恢复
gameStatus = true;
// 处理分数
alert(`游戏结束,得分:${score.innerHTML}`);
score.innerHTML = 0;
gameEnter.style.backgroundPositionY = 0;
myPlane.hp = 20;
meBoom.src = myPlane.dom.src;
gameo.innerHTML=""
}
// 停止检测
function stopDetectCollisions() {
clearInterval(detectCollisionsTimer);
}
// 修改分数
function modifyScore(addScore) {
// 获取当前分数
let currentScore = parseInt(score.innerHTML);
// 修改当前分数
currentScore = currentScore + addScore;
// 把当前分数渲染到页面上
score.innerHTML = currentScore;
}
// 我方飞机的构造函数
function MyPlane(pIndex) {
this.hp = 20;
this.dom = $("myPlane");
this.dom.src = meBoom.src;
this.width = getStyleValue(this.dom, "width");
this.height = getStyleValue(this.dom, "height");
// 不能在创建对象的时候获取
// this.left = getStyleValue(this.dom, "left");
// this.top = getStyleValue(this.dom, "top");
// this.ph = 20000
// 实时获取left值
this.getLeft = function () {
return getStyleValue(this.dom, "left");
};
// 实时获取top值
this.getTop = function () {
return getStyleValue(this.dom, "top");
};
this.move = function () {
// 键盘控制
document.onkeydown = (event) => {
// console.log(event.key);
switch (event.key) {
case "a":
case "ArrowLeft":
// console.log(this.getLeft());
if (this.getLeft() <= 7) {
this.dom.style.left = 0;
return;
}
this.dom.style.left = this.getLeft() - 20 + "px"; //向左
break;
case "d":
case "ArrowRight":
// console.log(this.getLeft());
if (this.getLeft() >= gameWidth - this.width - 6) {
this.dom.style.left = gameWidth - this.width + "px";
return;
}
this.dom.style.left = this.getLeft() + 20 + "px"; //向右
break;
case "w":
case "ArrowUp":
// console.log(this.getTop());
if (this.getTop() <= 8) {
this.dom.style.top = 0;
return;
}
this.dom.style.top = this.getTop() - 20 + "px"; //向上
break;
case "s":
case "ArrowDown":
// console.log(this.getTop());
if (this.getTop() >= gameHeight - this.height - 12) {
this.dom.style.top = gameHeight - this.height + "px";
return;
}
this.dom.style.top = this.getTop() + 20 + "px"; //向下
break;
case " ":
default:
break;
}
};
// 监听mousemove
document.onmousemove = (event) => {
// 获取鼠标的位置
const mouseX = event.pageX;
const mouseY = event.pageY;
// 计算飞机的 top left
let left = mouseX - gameMarginLeft - this.width / 2;
let top = mouseY - gameMarginTop - this.height / 2;
/* 不能让飞机移出边界 */
if (left <= 0) {
left = 0;
}
if (left >= gameWidth - this.width) {
left = gameWidth - this.width;
}
if (top <= 0) {
top = 0;
}
if (top >= gameHeight - this.height) {
top = gameHeight - this.height;
}
this.dom.style.left = left + "px";
this.dom.style.top = top + "px";
};
};
this.stop = function () {
document.onkeydown = null;
// 如何暂停
document.onmousemove = null;
};
// 爆炸
this.bomb = () => {
// 每次被攻击后 血量减1
this.hp -= 1;
// 判断血量为0时才爆炸
if (this.hp === 0) {
// 切换成爆炸的图
this.dom.src = this.dom.src;
// // 延迟500ms再消失,这样用户才能看到爆炸的效果
// setTimeout(() => {
// // 500ms后才消失
// this.remove();
// }, 500);
}
};
}
// 子弹
function Bullet() {
// id
this.id = createId();
// 元素节点
this.dom = document.createElement("img");
this.width = 40;
this.height =40;
// 子弹的速度
this.speed = 4;
// 定时器
this.timer = null;
// 这样获取才是实时的
this.getLeft = function () {
return getStyleValue(this.dom, "left");
};
this.getTop = function () {
return getStyleValue(this.dom, "top");
};
// 渲染到页面上
this.render = function () {
this.dom.src = "./images/bullets.png";
this.dom.style.position = "absolute";
// 获取飞机的位置 left top
const myPlaneLeft = myPlane.getLeft();
const myPlaneTop = myPlane.getTop();
// 确定 top left 值
const left = myPlaneLeft + myPlane.width / 2 - this.width / 2;
const top = myPlaneTop - this.height;
this.dom.style.left = left + "px";
this.dom.style.top = top + "px";
// 渲染到页面
bulletsBox.appendChild(this.dom);
};
// 移动
this.move = function () {
// 改变top
this.timer = setInterval(() => {
// 获取子弹当前的top
const top = getStyleValue(this.dom, "top");
const newTop = top - this.speed;
// 当子弹飞出界面时删除
if (newTop <= this.height * -1) {
this.remove();
return;
}
this.dom.style.top = newTop + "px";
}, 1000 / 60);
};
// 暂停
this.stop = function () {
// 清除定时器
clearInterval(this.timer);
};
// 删除
this.remove = function () {
//修复bug
if (this.dom.parentNode === null) {
return;
}
// 删除dom 找父亲
this.dom.parentNode.removeChild(this.dom);
// 删除 allBullets 中的对象
for (let i = 0; i < allBullets.length; ++i) {
const bullet = allBullets[i];
if (bullet.id === this.id) {
allBullets.splice(i, 1);
}
}
// 删除定时器
this.stop();
};
// 初始化
this.constructor = function () {
this.render();
this.move();
};
this.constructor();
}
// 敌机
function EnemyPlane(options) {
this.id = createId();
this.dom = document.createElement("img");
this.width = options.width;
this.height = options.height;
// 飞机的速度
this.speed = options.speed;
// 定时器
this.timer = null;
// 血量
this.hp = options.hp;
this.src = options.src;
this.fightSrc = options.fightSrc;
this.bombSrc = options.bombSrc;
this.score = options.score;
// 这样获取才是实时的
this.getLeft = function () {
return getStyleValue(this.dom, "left");
};
this.getTop = function () {
return getStyleValue(this.dom, "top");
};
// 渲染到页面
this.render = function () {
this.dom.src = this.src;
this.dom.style.position = "absolute";
// 出生位置
const left = randomRange(0, gameWidth - this.width);
const top = this.height * -1;
this.dom.style.left = left + "px";
this.dom.style.top = top + "px";
enemyPlaneBox.appendChild(this.dom);
};
this.move = function () {
this.timer = setInterval(() => {
const top = getStyleValue(this.dom, "top");
const newTop = top + this.speed;
// 当敌机飞出界面就删除
if (newTop >= gameHeight) {
this.remove();
}
this.dom.style.top = newTop + "px";
}, 1000 / 60);
};
// 停止
this.stop = function () {
clearInterval(this.timer);
};
this.remove = function () {
//修复bug
if (this.dom.parentNode === null) {
return;
}
// 删除页面上的节点
this.dom.parentNode.removeChild(this.dom);
// 停止(删除定时器)
this.stop();
};
// 爆炸
this.bomb = function () {
// 每次被攻击后 血量减1
this.hp -= 1;
// 判断血量为0时才爆炸
if (this.hp < options.hp && this.hp > 0) {
this.dom.src = this.fightSrc;
}
if (this.hp === 0) {
// 分数+1
modifyScore(this.score);
// 切换成爆炸的图
this.dom.src = this.bombSrc;
// 延迟500ms再消失,这样用户才能看到爆炸的效果
setTimeout(() => {
// 500ms后才消失
this.remove();
}, 500);
}
};
this.constructor = function () {
this.render();
this.move();
};
this.constructor();
}
原图
链接自取
链接: https://pan.baidu.com/s/1xv0KtOa5epXLWZi7zPp80Q?pwd=wqgc 提取码: wqgc 复制这段内容后打开百度网盘手机App,操作更方便哦