415 lines
13 KiB
JavaScript
415 lines
13 KiB
JavaScript
class bird {
|
||
// 游戏的默认状态 false 未开始 true 开始游戏
|
||
gameStatus = false;
|
||
innerHeight = window.innerHeight;
|
||
innerWidth = window.innerWidth;
|
||
// 获取当前页面的宽和高
|
||
|
||
// 鸟的下落速度
|
||
birdDownSpeed = 8;
|
||
|
||
// 鸟的上升速度
|
||
birdUpSpeed = 40;
|
||
|
||
// 地板的移动速度
|
||
groundSpeed = 5;
|
||
|
||
// 上下水管的间隙
|
||
WaterPipeClearance = 150
|
||
|
||
// 水管的左右间隙
|
||
WaterPipeLeftRightClearance = 300
|
||
|
||
// 生成水管的X轴位置
|
||
WaterPipeX = 0
|
||
|
||
// 一秒创建多少个水管
|
||
createdWaterPipeXTime = 1000
|
||
|
||
// 总分
|
||
TotalScore = 0
|
||
|
||
|
||
// 鸟的样式
|
||
birdThem = "yellowbird"
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
constructor() {
|
||
|
||
console.log(this.innerWidth);
|
||
this.bindEvent();
|
||
this.birdAction();
|
||
this.groundAction();
|
||
this.resultAction();
|
||
|
||
this.changSubject()
|
||
|
||
setInterval(() => {
|
||
if (this.gameStatus) {
|
||
this.createdWaterPipe();
|
||
}
|
||
}, this.createdWaterPipeXTime)
|
||
// this.createdWaterPipe();
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
bindEvent() {
|
||
click(".play", () => {
|
||
_(".sg").forEach(v => {
|
||
this.WaterPipeMove(v)
|
||
})
|
||
|
||
$(".ks").play()
|
||
// 点击play让所有水管元素运动
|
||
this.changeGameStatus()
|
||
// 点击play调用changeGameStatus()更改游戏的状态
|
||
})
|
||
click(".difficultyMode", () => {
|
||
_(".sg").forEach(v => {
|
||
this.WaterPipeMove(v)
|
||
})
|
||
|
||
$(".ks").play()
|
||
// 点击play让所有水管元素运动
|
||
this.changeGameStatus()
|
||
// 点击play调用changeGameStatus()更改游戏的状态
|
||
this.difficulty()
|
||
})
|
||
|
||
|
||
click(".pause", () => {
|
||
this.changeGameStatus()
|
||
|
||
_(".sg").forEach(v => {
|
||
clearInterval(v.time)
|
||
})
|
||
$(".ks").pause()
|
||
// 点击pause让所有水管元素暂停
|
||
})
|
||
}
|
||
|
||
//困难模式
|
||
difficulty() {
|
||
|
||
// 鸟的下落速度
|
||
this.birdDownSpeed = 10;
|
||
|
||
// 鸟的上升速度
|
||
this.birdUpSpeed = 40;
|
||
|
||
// 地板的移动速度
|
||
this.groundSpeed = 10;
|
||
|
||
// 上下水管的间隙
|
||
this.WaterPipeClearance = 100
|
||
|
||
// 水管的左右间隙
|
||
this.WaterPipeLeftRightClearance = 200
|
||
|
||
// 生成水管的X轴位置
|
||
this.WaterPipeX = 0
|
||
|
||
// 一秒创建多少个水管
|
||
this.createdWaterPipeXTime = 1000
|
||
|
||
// 总分
|
||
this.TotalScore = 0
|
||
|
||
|
||
|
||
|
||
}
|
||
|
||
|
||
|
||
//计算总分
|
||
resultAction() {
|
||
var TotalScoreArr = String(this.TotalScore).split("")
|
||
//定义一个存放总分的数组并且让数组都为字符串样式
|
||
$(".result").innerHTML = ""
|
||
//每次开始都清除
|
||
TotalScoreArr.forEach(v => {
|
||
$(".result").innerHTML += `<img src="./img/${v}.png" alt="">`
|
||
})
|
||
//遍历数组向其中添加分数的图片
|
||
}
|
||
|
||
|
||
// 换主题
|
||
changSubject() {
|
||
click(".yellow", () => {
|
||
|
||
this.birdThem = "yellowbird"
|
||
$(".bird").style.animation = `${this.birdThem} 0.4s linear infinite`
|
||
console.log("黄色");
|
||
})
|
||
|
||
click(".blue", () => {
|
||
this.birdThem = "bluebird"
|
||
$(".bird").style.animation = `${this.birdThem} 0.4s linear infinite`
|
||
|
||
})
|
||
click(".red", () => {
|
||
this.birdThem = "redbird"
|
||
$(".bird").style.animation = `${this.birdThem} 0.4s linear infinite`
|
||
|
||
})
|
||
}
|
||
|
||
changeGameStatus()
|
||
// 更改游戏状态
|
||
{
|
||
if (this.gameStatus)
|
||
// 如果游戏状态未开始
|
||
{
|
||
$(".start").remove("hidden")
|
||
$(".pause").add("hidden")
|
||
|
||
this.gameStatus = false
|
||
// 让.start里面类容显示 并给.pause添加隐藏
|
||
} else {
|
||
$(".niao").add("hidden")
|
||
$(".result").remove("hidden")
|
||
// 点击开始显示分数
|
||
|
||
$(".bird").style.animation = `${this.birdThem} 0.4s linear infinite`
|
||
$(".start").add("hidden")
|
||
$(".pause").remove("hidden")
|
||
this.gameStatus = true
|
||
// 否则反之,并且给小鸟添加animation动画属性覆盖之前游戏未开始的动画
|
||
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
birdAction()
|
||
// 小鸟的动画属性
|
||
{
|
||
var clcikTime = 0, currentTime = 0;
|
||
// 设置鸟的初始位置
|
||
$(".bird").style.top = `${this.innerHeight / 2 - 12}px`;
|
||
// 并且使小鸟位于屏幕中间 屏幕的高度除二并减去自身的一半
|
||
setInterval(() => {
|
||
if (this.gameStatus) {
|
||
$(".bird").style.top = `${parseInt($(".bird").style.top) + this.birdDownSpeed}px`
|
||
this.zhuangdiban($(".bird"), $(".ground"))
|
||
}
|
||
// 如果游戏已开始 设置小鸟掉落每次以小鸟本身离top的距离加上下落速度this.birdDownSpeed
|
||
}, 1000 / 16)
|
||
|
||
// 点击屏幕事件
|
||
click("body", () => {
|
||
if (this.gameStatus) {
|
||
// 如果游戏状态为ture
|
||
clcikTime = (new Date()).getTime()
|
||
// 设置个变量存放当前时间点击时间戳
|
||
$(".bird").add("up")
|
||
$(".bird").remove("down")
|
||
$(".bird").style.top = `${parseInt($(".bird").style.top) - this.birdUpSpeed}px`
|
||
// 给小鸟添加up属性移除down属性 并且让小鸟当前离top的值减去上升的值 也就是使小鸟向上移动
|
||
}
|
||
|
||
})
|
||
|
||
setInterval(() => {
|
||
|
||
if (this.gameStatus) {
|
||
currentTime = (new Date()).getTime();
|
||
// 获取当前时间戳
|
||
if (currentTime - clcikTime > 300) {
|
||
$(".bird").add("down")
|
||
$(".bird").remove("up")
|
||
}
|
||
// 如果当前时间比上一次点击时间大于300毫秒时给小鸟添加down属性移除up属性
|
||
}
|
||
}, 300)
|
||
}
|
||
|
||
// 地板运动
|
||
groundAction() {
|
||
$(".groundOne").style.left = '0px';
|
||
$(".groundTwo").style.left = `${this.innerWidth}px`;
|
||
// 两张图片已设置定位 一张起始位置屏幕左边 另一张起始位置屏幕宽度也就是右边 设置超出部分了隐藏
|
||
setInterval(() => {
|
||
$(".groundOne").style.left = `${parseInt($(".groundOne").style.left) - this.groundSpeed}px`
|
||
$(".groundTwo").style.left = `${parseInt($(".groundTwo").style.left) - this.groundSpeed}px`
|
||
|
||
// 使两张图片同时左边移动每次移动距离为当前图片在屏幕左边的距离减去地板移动的速度this.groundSpeed 也就是值越小就向左边移动
|
||
if (parseInt($(".groundOne").style.left) <= -this.innerWidth) {
|
||
$(".groundOne").style.left = `${this.innerWidth}px`
|
||
}
|
||
// 如果地板1的left的距离小于等于负屏幕宽度时(也就是地板1图片移出了屏幕)
|
||
// 让地板1 left距离重新为屏幕的宽度也就是放在屏幕的右边
|
||
|
||
if (parseInt($(".groundTwo").style.left) <= -this.innerWidth) {
|
||
$(".groundTwo").style.left = `${this.innerWidth}px`
|
||
}
|
||
// 如果地板2的left的距离小于等于负屏幕宽度时(也就是地板1图片移出了屏幕)
|
||
// 让地板2 left距离重新为屏幕的宽度也就是放在屏幕的右边
|
||
}, 1000 / 16)
|
||
}
|
||
|
||
// 创建水管
|
||
createdWaterPipe() {
|
||
var totalWaterPipeHeight = this.innerHeight - 112 - this.WaterPipeClearance;
|
||
// 定义一个变量totalWaterPipeHeight存放屏幕的高度减去地板的高度(112)再减去水管之间的间隙 this.WaterPipeClearance
|
||
// 这个变量是来控制两根水管的总高度
|
||
var TopWaterPipeHeight = Math.random() * ((totalWaterPipeHeight * 2 / 3) - (totalWaterPipeHeight * 1 / 3)) + (totalWaterPipeHeight * 1 / 3);
|
||
// 定义一个变量TopWaterPipeHeight 存放上水管的高度 上水管的高度为一个
|
||
|
||
var BottomWaterPipeHeight = totalWaterPipeHeight - TopWaterPipeHeight;
|
||
// 定义一个变量BottomWaterPipeHeight 存放下水管的高度 用水管的总高度减去上水管的高度
|
||
|
||
// 如果上水管高度小于等于总水管高度的2/3并且下水管高度小于等于总水管高度的2/3时 创建水管否则继续计算上水管高度
|
||
|
||
if (this.WaterPipeX == 0)
|
||
// 如果水管在x轴上的距离为0 也就是还没生成水管时
|
||
{
|
||
this.WaterPipeX = this.innerWidth
|
||
// 第一根水管在x轴的距离就为屏幕的宽度
|
||
} else {
|
||
this.WaterPipeX += this.WaterPipeLeftRightClearance
|
||
// 否则就为当前水管的x轴上的距离加上水管左右之间的间隙
|
||
}
|
||
|
||
|
||
var cretedImg = (type) =>
|
||
// 定义一个变量cretedImg 存放函数
|
||
|
||
{
|
||
var img = document.createElement("img");
|
||
// 定义一个img存放创建的元素img
|
||
img.src = `./img/${type == "top" ? 'sg_t' : 'sg_b'}.png`;
|
||
//img的地址为当tpye=top时地址为./img/sg_t 否则为./img/sg_b
|
||
img.className = "sg"
|
||
|
||
|
||
img.style = `
|
||
${type}: ${type == "top" ? 0 : 112}px;
|
||
height: ${type == "top" ? TopWaterPipeHeight : BottomWaterPipeHeight}px;
|
||
left: ${this.WaterPipeX}px
|
||
`;
|
||
//定义img 样式
|
||
|
||
return img
|
||
|
||
|
||
}
|
||
var TopWaterPipe = cretedImg("top")
|
||
var BottomWaterPipe = cretedImg("bottom")
|
||
//定义两个变量存放创建的上水管和下水管
|
||
|
||
$("body").appendChild(TopWaterPipe)
|
||
$("body").appendChild(BottomWaterPipe)
|
||
//添加上水管以及下水管
|
||
|
||
this.WaterPipeMove(TopWaterPipe)
|
||
this.WaterPipeMove(BottomWaterPipe)
|
||
}
|
||
|
||
//水管运动
|
||
WaterPipeMove(img) {
|
||
img.time = setInterval(() => {
|
||
|
||
img.style.left = `${parseInt(img.style.left) - this.groundSpeed}px`
|
||
// 让水管每次移动距离为当前的x轴距离减去地板移动的速度(保证水管和地板是同时运动的)
|
||
if (parseInt(img.style.left) <= -55) {
|
||
try {
|
||
clearInterval(img.time)
|
||
$("body").removeChild(img)
|
||
} catch (error) { }
|
||
|
||
// 如果水管的x轴距离小于他本身时 也就是全部移除屏幕时 删除定时器以及元素
|
||
|
||
} else {
|
||
this.collision($(".bird"), img)
|
||
// 否则就为它添加碰撞事件
|
||
}
|
||
|
||
}, 1000 / 16)
|
||
}
|
||
|
||
/**
|
||
* 碰撞检测
|
||
* @param {*} el1 鸟
|
||
* @param {*} el2 水管
|
||
*/
|
||
collision(el1, el2) {
|
||
if (el1.offsetLeft < el2.offsetLeft + el2.offsetWidth &&
|
||
el1.offsetLeft + el1.offsetWidth > el2.offsetLeft &&
|
||
el1.offsetTop < el2.offsetTop + el2.offsetHeight &&
|
||
el1.offsetHeight + el1.offsetTop > el2.offsetTop
|
||
) {
|
||
this.gameOver();
|
||
console.log("碰到了");
|
||
//碰撞上了就游戏结束
|
||
} else {
|
||
console.log("(el2.offsetLeft + el2.offsetWidth)", (el2.offsetLeft + el2.offsetWidth));
|
||
if ((el2.offsetLeft + el2.offsetWidth) == 101) {
|
||
this.TotalScore += 0.5
|
||
|
||
if (!String(this.TotalScore).includes(".")) {
|
||
console.log("==========分数=======: ", this.TotalScore);
|
||
$(".point").play()
|
||
this.resultAction()
|
||
// 就加一分调用this.resultAction()并添加音乐
|
||
if (this.TotalScore > 10) {
|
||
$("body").style.backgroundImage = "url(./img/hyback.png) ";
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
/**
|
||
* 碰撞检测
|
||
* @param {*} el1 鸟
|
||
* @param {*} el3 地板
|
||
*/
|
||
zhuangdiban(el1, el3) {
|
||
if (el1.offsetLeft < el3.offsetLeft + el3.offsetWidth &&
|
||
el1.offsetLeft + el1.offsetWidth > el3.offsetLeft &&
|
||
el1.offsetTop < el3.offsetTop + el3.offsetHeight &&
|
||
el1.offsetHeight + el1.offsetTop > el3.offsetTop
|
||
) {
|
||
this.gameOver();
|
||
console.log("碰到了");
|
||
//碰撞上了就游戏结束
|
||
}
|
||
|
||
}
|
||
gameOver() {
|
||
$(".hit").play()
|
||
// 添加碰撞声音
|
||
this.changeGameStatus()
|
||
// 改变游戏状态
|
||
_(".sg").forEach(v => clearInterval(v.time))
|
||
|
||
var gameOver = document.createElement("img")
|
||
gameOver.src = "./img/gameover.png"
|
||
// 添加新的img
|
||
|
||
$(".start").replaceChild(gameOver, $(".logo"))
|
||
// 替换开始的logo
|
||
$(".reset").remove("hidden")
|
||
click(".reset", () => location.reload())
|
||
// 点击开始重新刷新页面
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
}
|
||
|
||
new bird() |