写一个别踩白块小游戏来学习一下原生DOM

我正在参加掘金社区游戏创意投稿大赛个人赛,详情请看:游戏创意投稿大赛

大家好,我是一碗周,一个不想被喝(内卷)的前端。如果写的文章有幸可以得到你的青睐,万分有幸~

写在前面

记得在刚学习DOM的时候,当时使用原生JS操作DOM写了一个别踩白块的小游戏,游戏也非常的简单,示例效果如下:

demo.gif

在线体验:ywanzhou.github.io/white-block…

这个小游戏的代码比较少,适合新手学习,如果不感兴趣,请按【Ctrl/Command+W】

接下来进入正文。

HTML结构

HTML结构是下面这个样子的,代码如下:

<body>
  <!-- 计时器和分数 -->
  <div id="text">
    <h2>别踩白块儿</h2>

    <p>分数 : <stan id="span">0</stan></p>
  </div>
  <!-- 中间白块区域 -->
  <div id="container">
    <div class="line"><div></div></div>
  </div>
  <div id="instructions">
    <div class="arrow">
      <div>
        <img class="arrow-img inst-arrow-left" src="./imgs/direction.png" />
      </div>
      <div>
        <img class="arrow-img inst-arrow-down" src="./imgs/direction.png" />
      </div>
      <div>
        <img class="arrow-img inst-arrow-right" src="./imgs/direction.png" />
      </div>
    </div>
  </div>
  <div id="button">
    <button id="gameStart">游戏开始</button>
    <button id="gameEnd">游戏结束</button>
  </div>
</body>
复制代码

上面的每一个顶级<div>对应下图中的一个块,下图如下:

分析页面.png

然后编写对应的CSS代码,在这个例子中,我使用的是传统的布局方式,并没有使用Flex以及Grid,实现的代码比较臃肿。

脚本部分

我们的实现思路主要是通过无限生成黑块,然后下落并监听键盘按下的事件,进行实现,具体步骤如下:

  • 生成新的黑块,在视觉效果的以外生成一个新的黑块,这样显得不是很怪;
  • 黑块下落,在定时器中将黑块的top值次增,移动到视觉效果外将其通过Element.remove()方法删除掉;
  • 游戏开始的就是持续生成黑块,重复下落;
  • 游戏结束的时停止黑块的生成;
  • 通过keydown事件获取左、下、右三个按键,根据按键和最新一行的位置,匹配得分,否则游戏结束。

实现代码如下:

// 获取容器节点
var container = document.getElementById("container")
// 获取body 方便绑定事件
var body = document.body
var span = document.getElementById("span")
function CreBlackBlocks() {
  // 方块是否到达底部的标志
  this.flag = false
  // 创建一个新的黑块的方法
  this.creBlackBlockLine = function (container) {
    // 创建 div 节点
    var div = document.createElement("div")
    // 位置,表示当前方块在第几行
    var location
    container.appendChild(div)
    // 随机为 div 分配 class 属性
    var random = Math.random()
    if (random <= 0.33) {
      div.setAttribute("class", "test1")
      location = 0
    } else if (random > 0.33 && random <= 0.66) {
      div.setAttribute("class", "test2")
      location = 1
    } else {
      div.setAttribute("class", "test3")
      location = 2
    }
    return {
      // 返回一个对象,包含位置和节点
      myElement: div,
      myLocation: location,
    }
  }
  this.moveDownward = function (div) {
    // 获取有效属性
    var divStyles = window.getComputedStyle(div.myElement)
    // 获取内联样式样
    var divStyle = div.myElement.style
    var divStyleTop = parseInt(divStyles.top)
    var t = setInterval(() => {
      // 内联盖外联
      divStyleTop++
      divStyle.top = divStyleTop + "px"
      // 越界则删除
      if (divStyleTop >= 360) {
        clearInterval(t)
        div.myElement.remove()
      }
    }, 1)
  }
}
function Game(container) {
  // 存储创建每一行的返回值
  var newDiv
  // 存储创建的数组
  this.divElementArr = []
  // 每一行位置的数组
  this.divPosArr = []
  // 借助构造函数继承
  CreBlackBlocks.call(this, container)
  // 分数属性
  this.score = 0
  // 定义定义开始
  this.theGameStartsNow = function (game) {
    var t = setInterval(() => {
      newDiv = this.creBlackBlockLine(container)
      this.moveDownward(newDiv)
      game.divElementArr.push(newDiv.myElement)
      // 存储每一个方块第几行的数组
      game.divPosArr.push(newDiv.myLocation)
      // 没有按到方块结束的逻辑
      if (parseInt(window.getComputedStyle(this.divElementArr[0]).top) >= 357) {
        game.flag = true
      }
      // 结束执行的行为
      if (game.flag == true) {
        clearInterval(t)
        for (div in game.divElementArr) {
          game.divElementArr[div].remove()
        }
        alert("游戏结束!\n分数为:" + game.score)
        game.flag = false
        // 游戏数据初始化
        game.score = 0
        game.divElementArr = []
        game.divPosArr = []
      }
    }, 360)
    return t
  }
  // 定义游戏结束
  this.gameOver = function (t, game) {
    for (div in game.divElementArr) {
      game.divElementArr[div].remove()
    }
    clearInterval(t)
    alert("游戏结束!\n分数为:" + game.score)
    // 游戏数据初始化
    game.score = 0
    game.divElementArr = []
    game.divPosArr = []
  }
  // 键位点击做出相应的动作
  this.keyReaction = function (game, t) {
    body.addEventListener("keydown", function (event) {
      // 通过 switch 语句 根据当前的黑块的位置进入逻辑
      // Array.splice()方法 -> 作用,删除中的元素并返回一个数组,第一个参数 位置第二个参数数量
      switch (event.code) {
        case "ArrowLeft":
          game.removeBlock(game, t, 0)
          break
        case "ArrowDown":
          game.removeBlock(game, t, 1)
          break
        case "ArrowRight":
          game.removeBlock(game, t, 2)
          break

        default:
          break
      }
    })
  }
  this.removeBlock = function (game, t, val) {
    if (game.divPosArr[0] === val) {
      game.divPosArr.splice(0, 1)
      game.score += 10
      span.innerHTML = game.score
      game.divElementArr.splice(0, 1)[0].remove()
    } else {
      game.gameOver(t, game)
    }
  }
}

var game = new Game(container)
var t
// 游戏开始
var gameStart = document.getElementById("gameStart")
gameStart.addEventListener("click", function () {
  span.innerHTML = 0
  t = game.theGameStartsNow(game)
  game.keyReaction(game, t)
})
// 游戏结束
var gameEnd = document.getElementById("gameEnd")
gameEnd.addEventListener("click", function () {
  game.gameOver(t, game)
})
复制代码

这就是这个游戏的所有代码。

写在最后

文章中的代码是我刚学习DOM的时候写的,有些许bug还没有修复,以后有时间再说改写一下。

如果您觉得代码垃圾、游戏垃圾请轻喷。

猜你喜欢

转载自juejin.im/post/7079414945493811207
今日推荐