从零开始用js手写飞机大战全过程(附源码)

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等的情况

思路

  1. 编写背景板

在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">
  1. 在背景板中写一个 div 作为 plane,写一个 div 作为 enemy

在背景板下写plane与enemy的div

<div class="screen" id="screen">
        <div id="plane" class="move-plane"></div>
      </div>
  1. 利用 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`;
}
  1. 利用 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;
}
  1. 编写碰撞规则

通过设置横纵两轴碰撞条件,当两轴都碰撞时,则碰撞生效

// 判断飞机和敌人碰撞
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
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值