考验手眼协调能力的小游戏

435 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第8天,点击查看活动详情

本是无意穿堂风, 偏偏孤踞引山洪

游戏规则

游戏利用了最基本的鼠标mousedown和mouseup来实现,总共分为5个级别,不同级别需要通过的柱子数和搭桥的速度不同,玩家需要控制鼠标精准停在柱子中心且误差不超过4px才算通过,柱子需要依次通过不可跨越,考验的就是眼力和手速,手残党请勿好奇尝试,避免造成财产损失(手动狗头)

游戏实现

游戏采用基本的定位布局实现,随机生成柱子位置,不同难度不同速度通过调节自增的长度单位实现

  • 容器 容器就是简单的一个div加上地板组成
<div id="box"></div>
*{
    margin: 0;
    padding: 0;
    list-style: none;
    box-sizing: border-box;
  }
  #box{
    width: 100%;
    height: 80vh;
    background: cyan;
    border-bottom: 10vh solid sandybrown;
    overflow: hidden;
    position: absolute;
    top: 0;
    bottom: 0;
    margin: auto;
  }
  • 柱子, 柱子采用随机的方式生成,这里依然采用do while 来实现随机不重复left值,
let MAP_INFO = {}
let range = [] 
// 主要是判断两点 1 重不重复 2 新生成的坐标不能与旧坐标产生的柱子重叠
function randomWall () {
  let left = null
  do {
    left = Math.floor(Math.random()*$('#box').width()-44)
    if (left <0) left = 0
  } while (MAP_INFO[left] || range.find(v => Math.abs(v-left) <= 44))
  range.push(left)
  let div = $('<div>')
  div.addClass('wall')
  div.css('left', left + 'px')
  div.html('<div class="point"></div>')
  $('#box').append(div)
  MAP_INFO[left] = false
}
.wall{
    width: 42px;
    height: 60vh;
    position: absolute;
    background: #1e80ff;
    bottom: 0;
  }
  • 添加YoYo
let div = $('<div>')
div.addClass('yoyo')
div.css('left', range[0] + 'px')
$('#box').append(div)
 .yoyo{
    width: 42px;
    height: 42px;
    border-radius: 50%;
    position: absolute;
    bottom: 60vh;
    background-image: url('https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0a4ce25d48b8405cbf5444b6195928d4~tplv-k3u1fbpfcp-no-mark:0:0:0:0.awebp');
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
  }
  • 核心实现: 鼠标按下和抬起事件,以及加分和失败判断,YoYo移动动画。
  • 鼠标按下和抬起事件需要注册在开始游戏按钮上,因为不管是选择难度以及开始游戏均会触发事件,所以要在游戏开始后再进行注册
  • 加分判断很简单,注意看我们随机生成柱子的部分,我们维护了一个坐标的数组range,在init方法内 我们需要对初始化完成的range进行sort排序,这样他就是一个递增的数组了,通过一个下标inx来取出对应坐标,即可判断我们是否命中,是否跨越柱子
 function init () {
 // 初始化 得分 重复对象 下标数组以及游标inx
      $('.score').html('得分: 0')
      $('#box').empty()
      MAP_INFO = {}
      range = []
      score = 0
      inx = 1
      if (t) {
        clearInterval(t)
        t = null
        $('.btn').show()
      }
      // 随机生成柱子
      for (let i=0;i<level;i++) {
        randomWall()
      }
      对数组排序
      range = range.sort((a,b) => a-b)
    }
    function play () {
       // 初始化
      init()
      $('.btn').hide()
      // 这里是为了保证所有的柱子都已经渲染完成,手动写了一个异步队列
      setTimeout(function () {
        let div = $('<div>')
        div.addClass('yoyo')
        // 将YoYo放在第一根柱子上
        div.css('left', range[0] + 'px')
        $('#box').append(div)
        line = $('<div>')
        line.addClass('line')
        line.css('left', range[0]+ 21 + 'px')
        $('#box').append(line)
        document.body.onmousedown = function () {
        // 根据难度来增加桥的长度速度
          t = setInterval(function () {
            let len = $('.line').width()
            len+=level/20
            $('.line').width(len+'px')
            
          }, 10)
        }
        document.body.onmouseup = function () {
         if (t) {
          clearInterval(t)
         }
         // 将YoYo移动到桥的终点
         $('.yoyo').animate({left:  $('.line').width() + $('.line').offset().left - 42 + 'px'}, 500)
         // 判断绝对值  桥与柱子的红心点误差是否小于正负4
         if (Math.abs(range[inx]-range[inx-1] - $('.line').width()) <=4) {
          inx++
          score++
          $('.score').html(`得分: ${score}`)
          // 判断是不是最后一根柱子
          if (inx === range.length) {
            $('.score').html('恭喜通关,得分: 0')
            document.body.onmousedown = null
            document.body.onmouseup = null
            MAP_INFO = {}
            range = []
            score = 0
            if (t) {
              clearInterval(t)
              t = null
              $('.btn').show()
            }
          }
  
         } else {
         // 失败重置
          $('.score').html('游戏结束,得分: 0')
          document.body.onmousedown = null
          document.body.onmouseup = null
            MAP_INFO = {}
            range = []
            score = 0
            if (t) {
              clearInterval(t)
              t = null
              $('.btn').show()
            }
         }
        }
      }, 50)
    }
  • 游戏等级选择 很简单 select即可
<select name="" id="sel">
    <option value="3">洒水级</option>
    <option value="5">普通级</option>
    <option value="7">勇士级</option>
    <option value="9">王者级</option>
    <option value="20">地狱级</option>
  </select>
 $('#sel').change(function () {
      level = Number($(this).val())
      init()
    })

老规矩 码上掘金