plane game
前言
此文章帮助初学者学习制作一个简单小游戏
目标
利用css,html,js制作出飞机大战的简略版
前置准备
1. 绝对定位与相对定位
这里除了背景都设置为绝对定位,使飞机和敌机相对于背景定位。具体区别请看之前的帖。
2. setTimeout 与 clearTimer
建立子弹与敌机的定时器并且在他们消失时清除定时器
下面为敌机设置的例子
// 启动定时器,每一秒执行一次moveEnemy
function startEnemyInterval() {
enemyIntervalId = setInterval(moveEnemy, 100);
}
// 清除定时器
function stopEnemyInterval() {
clearInterval(enemyIntervalId);
}
// 碰撞时消失
if (xcrashFlag === true && ycrashFlag === true) {
// 横纵轴碰撞
// 飞机和敌人消失
let domEnemy = document.querySelector("#enemy");
if (domEnemy !== null) {
domEnemy.remove();
stopEnemyInterval();// 调用清除定时器
}
gameOver();
}
3. 碰撞计算原理
这里其实是个难点,拿子弹与敌机相撞举例:先判断敌机与子弹谁在左侧,再以他们的绝对距离比较较左者的宽度,若绝对距离大则横轴不相碰,反之,横轴相碰。而再以子弹与顶部的距离减去敌机与顶部的距离则是他们上下的绝对距离,当绝对距离小于0时纵轴相碰。当横纵轴都相碰时,子弹与敌机碰撞。
4. querySelector
这里需要利用dom来操纵元素,使js与html连接
5. bullet 对象数组
设置bullet为一个空数组,创造一个对象以获得每个子弹的index,top,left,来为判断子弹与敌机相碰提供数据。
6. ps 绘图
这里使用了ps绘图引入飞机,敌机与子弹的图片,以透明色为底。如下图为飞机
7. console.log 查问题
编写的过程中难免遇上各种预料外的问题,如果发现不了问题的原因,则可以利用console.log打印一些地方,以检测代码是否运行,null情况是否return等的情况
思路
- 编写背景板
在css中设置背景板样式,html中引入
.screen {
position: relative;
display: flex;
height: 700px;
width: 700px;
background-image: url("background.webp");
background-size: cover;
background-repeat: no-repeat;
border: 10px solid blue;
border-top: url("top.png");
}
<div class="screen" id="screen">
- 在背景板中写一个 div 作为 plane,写一个 div 作为 enemy
在背景板下写plane与enemy的div
<div class="screen" id="screen">
<div id="plane" class="move-plane"></div>
</div>
- 利用 top left 来上下左右移动 plane
top:到顶部的距离;left:到最左侧的距离。设置初始飞机top和left,再设置可移动的范围。
let positionTop = 660; // 初始飞机top
let positionLeft = 330; // 初始飞机left
// 向上移动自身一次
function moveUp() {
if (positionTop <= 0) {
gameOver();
return;
}
let dom = document.querySelector("#plane");
positionTop -= step;
dom.style.top = `${
positionTop}px`;
}
// 向下移动自身一次
function moveDown() {
if (positionTop >= 660) {
gameOver();
return;
}
let dom = document.querySelector("#plane");
positionTop += step;
dom.style.top = `${
positionTop}px`;
}
// 向左移动自身一次
function moveLeft() {
if (positionLeft <= 0) {
gameOver();
return;
}
let dom = document.querySelector("#plane");
positionLeft -= planeStep;
dom.style.left = `${
positionLeft}px`;
}
// 向右移动自身一次
function moveRight() {
if (positionLeft >= 660) {
gameOver();
return;
}
let dom = document.querySelector("#plane");
positionLeft += planeStep;
dom.style.left = `${
positionLeft}px`;
}
- 利用 setTimeout 来持续向下移动 enemy
通过定时器每一秒执行一次moveEnemy
// 向上移动子弹一次
function moveBullet(bullet) {
if (bullet.top <= 0) {
bullet.dom?.remove();
bullet.stop();
}
if (bullet.dom === null) {
return;
}
const bulletTop = parseInt(bullet.top);
bullet.top = bulletTop - step;
bullet.dom.style.top = bulletTop + "px";
enemyAndBulletCrash(bullet);
}
// 启动定时器,每一秒执行一次moveBullet
function startBulletInterval(bullet) {
bulletIntervalId = setInterval(() => {
moveBullet(bullet);
}, 100);
return bulletIntervalId;
}
- 编写碰撞规则
通过设置横纵两轴碰撞条件,当两轴都碰撞时,则碰撞生效
// 判断飞机和敌人碰撞
function planeAndEnemyCrash() {
const enemyDom = document.querySelector(`#enemy`);
if (enemyDom === null) {
return;
}
const enemyLeft = parseInt(enemyDom.style.left);
const enemyTop = parseInt(enemyDom.style.top);
let peLeftDistance = enemyLeft - positionLeft;
let peAbsoluteLeftDistance = Math.abs(peLeftDistance);
let peAbsoluteTopDistance = positionTop - enemyTop - 40;
let xcrashFlag = false;
let ycrashFlag = false;
if