基于JQuery实现YoYo版 flybird,地狱级无人能通关!
俗话讲叫一日不见如隔三秋 我一天不写文章也感觉浑身难受
这不是,今天的文章,它来了
游戏说明
游戏灵感来源于之前玩儿过的一款游戏,名字忘记了,姑且就叫他飞鸟吧,游戏场景是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