likes
comments
collection
share

基于JQuery实现YoYo版 flybird,地狱级无人能通关!

作者站长头像
站长
· 阅读数 57

俗话讲叫一日不见如隔三秋 我一天不写文章也感觉浑身难受这不是,今天的文章,它来了

游戏说明

游戏灵感来源于之前玩儿过的一款游戏,名字忘记了,姑且就叫他飞鸟吧,游戏场景是2d的,玩家需要控制鸟儿上升下降,来穿越一个一个的柱子,撞柱就凉凉

本游戏规则

左上角预设了五个难度,分别是洒水级,普通级,勇士级,王者级,地狱级,每个级别对应需要穿过的柱子以及柱子移动的速度都不相同,等级越高,柱子移动速度越快,柱子越多,最高的地狱级需要穿过50根柱子,也就是满分是50分,为了给手残党【ps:作者本人】一点生存空间,我在开局为我们的鸟儿yoyo提供了3秒的无敌保护,样式就是一个血红血红的光圈,无敌消失光圈会变白,玩家需要通过上下箭头控制鸟儿yoyo移动,穿越柱子的缝隙,每穿过一个柱子加1分。

游戏涉及的关键技术点

  • 背景滚动动画
  • 键盘keydown与keyup事件

游戏实现

  • 创建场景,场景采用的是边框拼装的方式来实现,外层通过拼装来实现一个伪立体效果,内层采用一个宽度为1000vw的容器来承载柱子及游戏场景
// 忽略掉鸟儿的部分
<div class="bird-wall">
  <div class="scroll"></div>
  <div class="bird"></div>
</div>
// 样式
 html,body{
    width: 100%;
    height: 100%;
    overflow: hidden;
  }
  .bird-wall{
    width: 100%;
    height: 80vh;
    position: absolute;
    top: 0;
    bottom: 0;
    margin: auto;
    background: cyan;
    border-left: 10vw solid cornflowerblue;
    border-right: 10vw solid cornflowerblue;
    border-bottom: 10vh solid sandybrown;
    overflow: hidden;
  }
  .scroll{
    width: 1000vw;
    height: 100%;
    position: relative;
    background: cyan;
  }
  • 实现随机位置的柱子,随机位置的柱子我们依然通过随机数的方式产生,并且还有一些关键判断需要添加,来保证游戏本身的可玩性,首先是随机生成柱子的算法,柱子我们可以认为是由中间宽度固定的两个div来组成,他们的left值相等,高度通过随机数产生,来实现不同高度的效果,这里我们当然也可以继续增加难度比如将中间的宽度继续进行随机,但是那样难度就太大了,有兴趣的可以继续基于我的代码提升难度,这里需要注意的点: 1. left值不可重复,否则就会出现重叠的柱子 2. left值之间不能小于柱子的宽度,否则会出现重叠而使游戏本身不可玩 3. top值不能小于某个值,这里我是4vh,这样做的目的是避免出现0的高度导致无法穿越,下面是随机柱子的具体实现
let MAP_INFO = {}
let range = [] 
// 这里range的作用可有可无,我也是写文章的时候才发现的,因为之前MAP_INFO内存储的key是top_left,无法直接获取left,所以才引入了range数组,下面的代码是改造后的,完全可以判断MAP_INFO[left]是否存在即可
function randomWall () {
  let top = null
  let left = null
  do {
    top = Math.floor(Math.random()*60)
    left = Math.floor(Math.random()*1000)
  } while (MAP_INFO[left] || range.find(v => Math.abs(v-left) <= 10) || top < 4)
  range.push(left)
  let div = $('<div>')
  div.addClass('wall')
  div.css('top', 0)
  div.css('height', top + 'vh')
  div.css('left', left + 'vw')
  $('.scroll').append(div)
  let div1 = $('<div>')
  div1.addClass('wall')
  div1.css('bottom', 0)
  div1.css('height', 60-top + 'vh')
  div1.css('left', left + 'vw')
  MAP_INFO[left] = {
    top: div,
    bottom: div1
  }
  $('.scroll').append(div1)
}
  • 等级切换 等级切换通过原生的select元素来实现,通过监听select的change事件来更新我们的难度等级level
let level = 10
 $('#sel').change(function () {
      level = Number($(this).val())
      init()
    })
  • 生成对应难度的柱子
function init () {
      $('.score').html('得分: 0')
      $('.scroll').empty()
      MAP_INFO = {}
      range = []
      len = 0
      score = 0 
      if (t) {
        clearInterval(t)
        t = null
        $('.btn').show()
      }
      for (let i=0;i<level;i++) {
        randomWall()
      }
    }
  • 实现鸟儿yoyo的上下移动, 这里需要判断移动的边界,大于0 小于容器高度
document.onkeydown = function (e) {
      if(ut) {
        clearInterval(ut)
        ut = null
      }
      let top = Number($('.bird').css('top').split('px')[0])
      if (e.key === 'ArrowUp') {
        ut = setInterval(function () {
          top-=5
          if(top<=0) {
            top = 0
          }
          $('.bird').css('top',top+'px')
        }, 10)
      } else if (e.key === 'ArrowDown') {
        ut = setInterval(function () {
          top+=5
          if(top>=$('.scroll').height()) {
            top = $('.scroll').height()
          }
          $('.bird').css('top',top+'px')
        }, 10)
      }
    }
    document.onkeyup = function (e) {
      if(ut) {
        clearInterval(ut)
        ut = null
      }
    }
  • 让柱子动起来,实现无敌、加分、判断碰撞等逻辑,为开始游戏按钮添加逻辑
let t = null
let len = 0
let level = 10
let ut = null
let score = 0
let scHeight = $('.scroll').height() // 容器高度
 function play () {
    //初始化
      init()
      $('.btn').hide()
      // 添加无敌
      $('.bird').addClass('protect')
      let tm  = setInterval(function () {
        $('.bird').removeClass('protect')
      },3000)
      t = setInterval(function () {
        len++
        let wall = range.find(v => v === len)
        if (wall) {
          let birdTop = Number($('.bird').css('top').split('px')[0])
          let safeTop = Number(MAP_INFO[wall].top.css('height').split('px')[0])
          let safeBottom = Number(MAP_INFO[wall].bottom.css('height').split('px')[0])
          let safeHeight = scHeight - safeBottom
          // 判断碰撞
          if (birdTop < safeTop || birdTop > safeHeight) {
            if (!$('.bird').hasClass('protect')) {
              $('.btn').show()
              clearInterval(t)
            }
          }
          score++
          $('.score').html(`得分: ${score}`)
        }
        if(len>=1000) {
          $('.btn').show()
          clearInterval(t)
        }
        console.log()
        $('.scroll').css('transform', `translateX(-${len}vw)`)

      }, 60-level) 
    }
    $('.btn').click(play)

转载自:https://juejin.cn/post/7150998132522745893
评论
请登录