JS初學(xué)者往往有一個(gè)特點(diǎn):一聽就懂,一寫就懵个盆。
糾其原因:
1-代碼練習(xí)太少,導(dǎo)致根基不扎實(shí)
2-代碼練習(xí)太少做祝,導(dǎo)致經(jīng)驗(yàn)無積累。
3-代碼練習(xí)太少鸡岗,導(dǎo)致思路不清晰混槐。
所以代碼一定要多多練習(xí),無捷徑可尋轩性,希望通過以下個(gè)案例声登,可以對(duì)大家學(xué)習(xí)JS有所幫助。
1- 預(yù)覽與下載
2- 完成游戲樣式及基本結(jié)構(gòu)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
* {
pading: 0;
margin: 0;
}
body {
user-select: none;
}
/* 游戲舞臺(tái) */
#app {
position: relative;
width: 343px;
height: 480px;
background: url("./img/bg.jpg");
margin: 20px auto;
overflow: hidden;
}
/* 分?jǐn)?shù) */
#score {
position: absolute;
width: 100%;
left: 0;
top: 20px;
text-align: center;
font-size: 0;
z-index: 1;
}
/* 開場(chǎng)動(dòng)畫 */
.startAnimate {
width: 236px;
height: 77px;
background-image: url("./img/head.jpg");
position: absolute;
top: 150px;
left: calc(50% - 118px);
animation: startAnimate 1s alternate infinite;
z-index: 9;
}
@keyframes startAnimate {
from {
top: 120px;
}
to {
top: 150px;
}
}
.animate-bird {
position: absolute;
width: 40px;
height: 26px;
background-image: url("./img/bird0.png");
right: 0;
top: calc(50% - 13px);
animation: bird 1s alternate infinite;
z-index: 9;
}
@keyframes bird {
from {
background-image: url("./img/bird0.png");
}
to {
background-image: url("./img/bird1.png");
}
}
/*開始按鈕*/
#start {
position: 85px;
height: 29px;
position: absolute;
left: calc(50% - 42.5px);
top: 260px;
cursor: pointer;
z-index: 9;
}
/* 管道 */
.pipe {
width: 62px;
height: 423px;
position: absolute;
left: 200px;
bottom: 57px;
}
.pipe_up {
position: relative;
left: 0;
top: 0;
height:100px;
background: url("./img/up_mod.png") repeat-y;
}
.pipe_up img{
position: absolute;
bottom: 0;
}
.pipe_down {
position: absolute;
left: 0;
bottom: 0;
height:223px;
background: url("./img/down_mod.png") repeat-y;
}
</style>
</head>
<body>
<!-- 游戲舞臺(tái) -->
<div id="app">
<!-- 分?jǐn)?shù) -->
<div id="score">
<img src="./img/0.jpg" alt="">
<img src="./img/0.jpg" alt="">
<img src="./img/0.jpg" alt="">
</div>
<!-- 開場(chǎng)動(dòng)畫 -->
<div class="startAnimate">
<div class="animate-bird"></div>
</div>
<!-- 開始按鈕 -->
<img id="start" src="./img/start.jpg" alt="">
<!-- 管道 -->
<div class="pipe">
<!-- 上管道 -->
<div class="pipe_up">
<img src="./img/up_pipe.png" alt="">
</div>
<!-- 下管道 -->
<div class="pipe_down">
<img src="./img/down_pipe.png" alt="">
</div>
</div>
</div>
</body>
</html>
預(yù)覽效果:https://qianduanmao.com/demo/dom/xiaoniao/1.html
3- 點(diǎn)擊開始按鈕進(jìn)入游戲
- 由于管道需要需要后續(xù)動(dòng)態(tài)添加揣苏,所以可以將與管道相關(guān)的元素注釋掉悯嗓。
<!-- 游戲舞臺(tái) -->
<div id="app">
<!-- 分?jǐn)?shù) -->
<div id="score">
<img src="./img/0.jpg" alt="">
<img src="./img/0.jpg" alt="">
<img src="./img/0.jpg" alt="">
</div>
<!-- 開場(chǎng)動(dòng)畫 -->
<div class="startAnimate">
<div class="animate-bird"></div>
</div>
<!-- 開始按鈕 -->
<img id="start" src="./img/start.jpg" alt="">
<!-- 管道注釋掉,因?yàn)楣艿佬枰罄m(xù)動(dòng)態(tài)生成 -->
<!-- <div class="pipe">-->
<!-- <!– 上管道 –>-->
<!-- <div class="pipe_up">-->
<!-- <img src="./img/up_pipe.png" alt="">-->
<!-- </div>-->
<!-- <!– 下管道 –>-->
<!-- <div class="pipe_down">-->
<!-- <img src="./img/down_pipe.png" alt="">-->
<!-- </div>-->
<!-- </div>-->
</div>
- 點(diǎn)擊start按鈕卸察,隱藏開場(chǎng)動(dòng)畫及start按鈕
// 獲得開場(chǎng)動(dòng)畫元素
var startAnimate = document.querySelector('.startAnimate');
// 獲得開始按鈕
var start = document.querySelector('#start');
// 點(diǎn)擊按鈕
start.onclick = function(){
// 隱藏開場(chǎng)動(dòng)畫及開始按鈕
startAnimate.style.display = this.style.display = 'none';
}
預(yù)覽效果:https://qianduanmao.com/demo/dom/xiaoniao/2.html
4- 小鳥上升及加速下落
- 游戲舞臺(tái)中引入小鳥圖片
<img id="bird" src="./img/bird0.png" alt="">
- 為小鳥圖片增加樣式
/* 小鳥 */
#bird {
position: absolute;
left: 30px;
top: 50px;
display: none;
z-index: 10;
}
- JS代碼更改如下:
// 獲得開場(chǎng)動(dòng)畫元素
var startAnimate = document.querySelector('.startAnimate');
// 獲得開始按鈕
var start = document.querySelector('#start');
// +獲得小鳥元素
var bird = document.querySelector("#bird");
// +獲得后臺(tái)元素
var app = document.querySelector("#app");
// 點(diǎn)擊按鈕
start.onclick = function () {
// 隱藏開場(chǎng)動(dòng)畫及開始按鈕
startAnimate.style.display = this.style.display = 'none';
// + 小鳥顯示
bird.style.display = 'block';
// + 小鳥下落速度,正數(shù)向下速度脯厨,負(fù)數(shù)為向上速度
bird.speed = 0;
// + 允許下降最大距離:57為馬路的高度
bird.distanceMaxDecline = app.clientHeight - 57 - bird.offsetHeight;
// + 是否死亡,初始值為false
bird.isDie = false;
// + 增加定時(shí)器
bird.fly = setInterval(flyInterval.bind(bird), 20);
// + 為舞臺(tái)增加點(diǎn)擊事件
app.onclick = birderRise;
}
// + 單擊舞臺(tái)的處理函數(shù)
function birderRise() {
// 小鳥加速度設(shè)置為-5坑质,向上飛翔
bird.speed = -5;
}
// + 小鳥飛翔計(jì)時(shí)器
function flyInterval() {
// 加速度為0.5
this.speed += 0.5;
// 如果速度為正數(shù)合武,則下落临梗,正數(shù)上升,設(shè)置圖片
this.src = this.speed > 0 ? "./img/down_bird0.png":"./img/bird0.png";
// 小鳥下落的距離
var distanceDecline = this.offsetTop + this.speed;
// 如果觸地則死亡
if (distanceDecline > this.distanceMaxDecline) {
// 設(shè)置為下降最大距離
this.style.top = this.distanceMaxDecline + "px";
// 死亡
this.isDie = true;
// 關(guān)閉小鳥定時(shí)器
clearInterval(this.fly);
return;
}
// distanceDecline不允許小于0
if (distanceDecline < 0) distanceDecline = 0;
// 設(shè)置top值
this.style.top = distanceDecline + "px";
}
預(yù)覽效果:https://qianduanmao.com/demo/dom/xiaoniao/3.html
5- 隔3s生成一次管道
- 創(chuàng)建工具函數(shù)稼跳,用于生成指定范圍的整數(shù)
// 工具函數(shù):生成指定范圍的隨機(jī)整數(shù)
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
- 創(chuàng)建生成管道方法
// 創(chuàng)建管道
function createPipe(){
var pipe = document.createElement("div");
pipe.className = "pipe";
pipe.score = 1;// 指定增加分值
// 上管道寬度
var upHeight = getRandom(60,263);
// 下管道的高度
var downHeight = app.clientHeight-57-100-upHeight;
pipe.innerHTML = `
<div style="height:${upHeight}px" class="pipe_up">
<img src="./img/up_pipe.png" alt="">
</div>
<div style="height:${downHeight}px" class="pipe_down">
<img src="./img/down_pipe.png" alt="">
</div>
`;
// 將創(chuàng)建的管道放置在舞臺(tái)尾部
app.appendChild(pipe);
}
- 增加全局變量
// +記錄生成管道定時(shí)器
var pipeTimer;
- 在start按鈕的事件處理函數(shù)中增加定時(shí)器隔3秒調(diào)用一次createPipe
// 點(diǎn)擊按鈕
start.onclick = function () {
// 隱藏開場(chǎng)動(dòng)畫及開始按鈕
startAnimate.style.display = this.style.display = 'none';
// 小鳥顯示
bird.style.display = 'block';
// 小鳥下落速度,正數(shù)向下速度盟庞,負(fù)數(shù)為向上速度
bird.speed = 0;
// 允許下降最大距離:57為馬路的高度
bird.distanceMaxDecline = app.clientHeight - 57 - bird.offsetHeight;
// 是否死亡,初始值為false
bird.isDie = false;
// 增加定時(shí)器
bird.fly = setInterval(flyInterval.bind(bird), 30);
// +管道定時(shí)器
pipeTimer = setInterval(createPipe,3000);
// 為舞臺(tái)增加點(diǎn)擊事件
app.onclick = birderRise;
}
預(yù)覽效果:https://qianduanmao.com/demo/dom/xiaoniao/4.html
6- 管道均速移動(dòng)并統(tǒng)計(jì)分?jǐn)?shù)
- 由于管道要?jiǎng)討B(tài)生產(chǎn)汤善,需要將管道的初始位置調(diào)整為游戲舞臺(tái)右側(cè)什猖。
/* 管道 */
.pipe {
width: 62px;
height: 423px;
position: absolute;
left: 343px;/*修改為343*/
bottom: 57px;
}
- 增加全局變量
// +獲得分?jǐn)?shù)元素
var score = document.querySelectorAll("#score>img");
- 增加小鳥總分?jǐn)?shù)屬性
// 點(diǎn)擊按鈕
start.onclick = function () {
// 隱藏開場(chǎng)動(dòng)畫及開始按鈕
startAnimate.style.display = this.style.display = 'none';
// 小鳥顯示
bird.style.display = 'block';
// 小鳥下落速度,正數(shù)向下速度,負(fù)數(shù)為向上速度
bird.speed = 0;
// 允許下降最大距離:57為馬路的高度
bird.distanceMaxDecline = app.clientHeight - 57 - bird.offsetHeight;
// 是否死亡红淡,初始值為false
bird.isDie = false;
// +小鳥總分
bird.scoreSum = 0;
// 增加定時(shí)器
bird.fly = setInterval(flyInterval.bind(bird), 30);
// 管道定時(shí)器
pipeTimer = setInterval(createPipe,3000);
// 為舞臺(tái)增加點(diǎn)擊事件
app.onclick = birderRise;
}
- 增加管理均速移動(dòng)方法,并統(tǒng)計(jì)分?jǐn)?shù)
// 管道移動(dòng)
function pipeMove(){
// 每次移動(dòng)2像素
var distance = this.offsetLeft -2;
// 讓管道開始移動(dòng)
this.style.left = distance+"px";
// 判斷管道是否已經(jīng)移出舞臺(tái)
if(distance<-this.offsetWidth){
// 移除定時(shí)器
clearInterval(this.moveTimer);
// 移除管道
app.removeChild(this);
}else if(distance<-(this.offsetWidth-bird.offsetLeft)){
// 小鳥過了管道加分
if(this.score > 0){
bird.scoreSum+=this.score;
score[0].src="./img/"+parseInt(bird.scoreSum/100)+".jpg";
score[1].src="./img/"+parseInt((bird.scoreSum%100)/10)+".jpg";
score[2].src="./img/"+parseInt(bird.scoreSum%10)+".jpg";
this.score = 0;
}
}
}
- 在createPipe函數(shù)中調(diào)用pipeMove
// 創(chuàng)建管道
function createPipe(){
// 不狮。。锉屈。
// 荤傲。。颈渊。
// 遂黍。。俊嗽。
// +增加定時(shí)器雾家,讓管道均速移動(dòng)
pipe.moveTimer = setInterval(pipeMove.bind(pipe),30);
}
預(yù)覽效果:https://qianduanmao.com/demo/dom/xiaoniao/5.html
7- 讓草地進(jìn)行均速移動(dòng)
- 在游戲舞臺(tái)中增加草地元素
<!-- 草地 -->
<div id="banner">
<img src="img/banner.jpg"/>
<img src="img/banner.jpg"/>
</div>
- 為草地增加樣式
/*草地*/
#banner{
position: absolute;
left:0;
top:423px;
font-size: 0;
width: 200%;
}
- 全局獲得草地元素,并增加移動(dòng)初始值
// 獲得草地
var banner = document.querySelector("#banner");
// 向左移動(dòng)的數(shù)值
banner.distanceLeft = 0;
- 增加草地移動(dòng)函數(shù)
// 草地向左移動(dòng)
function bannerMove(){
// 向左移動(dòng)的數(shù)值 (距離)+2
banner.distanceLeft -= 2;
// 判斷最左側(cè)圖片是否消失在舞臺(tái)中
if(banner.distanceLeft < -app.clientWidth){
// 向左移動(dòng)的距離為0
banner.distanceLeft = 0;
// 將banner當(dāng)中的第一個(gè)DOM元素放置到banner的尾部
banner.appendChild(banner.firstElementChild);
}
banner.style.left = banner.distanceLeft+"px";
}
- 在start按鈕的事件處理函數(shù)中增加定時(shí)器绍豁,調(diào)用bannerMove
// 草地移動(dòng)
banner.timer = setInterval(bannerMove,30);
預(yù)覽效果:https://qianduanmao.com/demo/dom/xiaoniao/6.html
8- 檢測(cè)碰撞游戲結(jié)束
- 增加碰撞檢測(cè)函數(shù)
// 是否小鳥與柱子進(jìn)行了碰撞
function crashFn(pipe){
// 相撞:四個(gè)條件必須同時(shí)滿足
// bird與pipe
// 1- bird的右邊 大于等于 pipe的左邊
// 2- bird的下邊 大于等于 pipe的上邊
// 3- bird的左邊 小于等于 pipe的右邊
// 4- bird的上邊 小于等于 pipe的下邊
// bird:
var birdLeft = bird.offsetLeft;//左邊
var birdRight = birdLeft+bird.offsetWidth;// 右邊
var birdTop = bird.offsetTop;// 上邊
var birdBottom = birdTop+bird.offsetHeight;// 下邊
// pipe
var pipeLeft = pipe.parentNode.offsetLeft;
var pipeRight = pipeLeft+pipe.offsetWidth;
var pipeTop = pipe.offsetTop;
var pipeBottom = pipeTop+pipe.offsetHeight;
if(birdRight>=pipeLeft
&& birdBottom>=pipeTop
&& birdLeft<=pipeRight
&& birdTop<=pipeBottom){
return true;// 相撞了
}
return false;// 沒有相撞
}
- 在flyInterval函數(shù)中判斷是否碰撞
// 小鳥飛翔計(jì)時(shí)器
function flyInterval() {
// 加速度為0.5
this.speed += 0.5;
// 如果速度為正數(shù)芯咧,則下落,正數(shù)上升竹揍,設(shè)置圖片
this.src = this.speed > 0 ? "./img/down_bird0.png":"./img/bird0.png";
// 小鳥下落的距離
var distanceDecline = this.offsetTop + this.speed;
// 如果觸地則死亡
if (distanceDecline > this.distanceMaxDecline) {
distanceDecline = this.distanceMaxDecline;
// 小鳥死亡
this.isDie = true;
}
// distanceDecline不允許小于0
if (distanceDecline < 0) distanceDecline = 0;
// 設(shè)置top值
this.style.top = distanceDecline + "px";
// + 小鳥未亡敬飒,檢測(cè)管道是否與小鳥相撞
if(!this.isDie){
var pipes = document.querySelectorAll(".pipe div");
for(var i=0;i<pipes.length;i++){
// 相撞
if(crashFn(pipes[i])){
bird.isDie = true;
bird.className = "die";
break;
}
}
}
// + 判斷小鳥是否死亡
if(bird.isDie){
// 關(guān)閉小鳥定時(shí)器
clearInterval(this.fly);
// 關(guān)閉管道定時(shí)器
clearInterval(pipeTimer);
// 關(guān)閉草地定時(shí)器
clearInterval(banner.timer)
// 顯示開場(chǎng)動(dòng)畫及開始按鈕
startAnimate.style.display = start.style.display = 'block';
}
}
- 增加小鳥撞擊后的樣式
/*死亡*/
.die{
transition:0.5s;
top:393px !important;
}
- pipeMove函數(shù)判斷小鳥是否死亡
// + 判斷小鳥是否死亡
if(bird.isDie){
// 關(guān)閉管道移動(dòng)定時(shí)器
clearInterval(this.moveTimer)
// 清除管道
app.removeChild(this);
return;
}
- 重置游戲
// 點(diǎn)擊按鈕
start.onclick = function () {
// + 重置分?jǐn)?shù)
score[0].src = score[1].src = score[2].src = "./img/0.jpg";
// + 重置小鳥高度
bird.style.top = "50px";
// + 清除小鳥樣式
bird.className = null;
// 隱藏開場(chǎng)動(dòng)畫及開始按鈕
startAnimate.style.display = this.style.display = 'none';
// 小鳥顯示
bird.style.display = 'block';
// 小鳥下落速度,正數(shù)向下速度,負(fù)數(shù)為向上速度
bird.speed = 0;
// 允許下降最大距離:57為馬路的高度
bird.distanceMaxDecline = app.clientHeight - 57 - bird.offsetHeight;
// 是否死亡芬位,初始值為false
bird.isDie = false;
// 小鳥總分
bird.scoreSum = 0;
// 增加定時(shí)器
bird.fly = setInterval(flyInterval.bind(bird), 30);
// 管道定時(shí)器
pipeTimer = setInterval(createPipe, 3000);
// 草地移動(dòng)
banner.timer = setInterval(bannerMove, 30);
// 為舞臺(tái)增加點(diǎn)擊事件
app.onclick = birderRise;
}
預(yù)覽效果:https://qianduanmao.com/demo/dom/xiaoniao/7.html
9- 增加音樂-完整代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
* {
pading: 0;
margin: 0;
}
body {
user-select: none;
}
/* 游戲舞臺(tái) */
#app {
position: relative;
width: 343px;
height: 480px;
background: url("./img/bg.jpg");
margin: 20px auto;
overflow: hidden;
}
/* 分?jǐn)?shù) */
#score {
position: absolute;
width: 100%;
left: 0;
top: 20px;
text-align: center;
font-size: 0;
z-index: 1;
}
/* 開場(chǎng)動(dòng)畫 */
.startAnimate {
width: 236px;
height: 77px;
background-image: url("./img/head.jpg");
position: absolute;
top: 150px;
left: calc(50% - 118px);
animation: startAnimate 1s alternate infinite;
z-index: 9;
}
@keyframes startAnimate {
from {
top: 120px;
}
to {
top: 150px;
}
}
.animate-bird {
position: absolute;
width: 40px;
height: 26px;
background-image: url("./img/bird0.png");
right: 0;
top: calc(50% - 13px);
animation: bird 1s alternate infinite;
z-index: 9;
}
@keyframes bird {
from {
background-image: url("./img/bird0.png");
}
to {
background-image: url("./img/bird1.png");
}
}
/*開始按鈕*/
#start {
position: 85px;
height: 29px;
position: absolute;
left: calc(50% - 42.5px);
top: 260px;
cursor: pointer;
z-index: 9;
}
/* 管道 */
.pipe {
width: 62px;
height: 423px;
position: absolute;
left: 343px; /*修改為343*/
bottom: 57px;
}
.pipe_up {
position: relative;
left: 0;
top: 0;
height: 100px;
background: url("./img/up_mod.png") repeat-y;
}
.pipe_up img {
position: absolute;
bottom: 0;
}
.pipe_down {
position: absolute;
left: 0;
bottom: 0;
height: 223px;
background: url("./img/down_mod.png") repeat-y;
}
/* 小鳥 */
#bird {
position: absolute;
left: 30px;
top: 50px;
display: none;
z-index: 10;
}
/*草地*/
#banner {
position: absolute;
left: 0;
top: 423px;
font-size: 0;
width: 200%;
}
/*死亡*/
.die {
transition: 0.5s;
top: 393px !important;
}
</style>
</head>
<body>
<!-- 游戲舞臺(tái) -->
<div id="app">
<!-- 分?jǐn)?shù) -->
<div id="score">
<img src="./img/0.jpg" alt="">
<img src="./img/0.jpg" alt="">
<img src="./img/0.jpg" alt="">
</div>
<img id="bird" src="./img/bird0.png" alt="">
<!-- 開場(chǎng)動(dòng)畫 -->
<div class="startAnimate">
<div class="animate-bird"></div>
</div>
<!-- 開始按鈕 -->
<img id="start" src="./img/start.jpg" alt="">
<!-- 草地 -->
<div id="banner">
<img src="img/banner.jpg"/>
<img src="img/banner.jpg"/>
</div>
<audio preload="auto"
loop
src="./music/game_music.mp3">
</audio>
<audio preload="auto"
src="./music/game_over.mp3">
</audio>
<audio preload="auto"
src="./music/bullet.mp3">
</audio>
</div>
</body>
<script>
var audios = document.querySelectorAll("audio");
// 獲得開場(chǎng)動(dòng)畫元素
var startAnimate = document.querySelector('.startAnimate');
// 獲得開始按鈕
var start = document.querySelector('#start');
// 獲得小鳥元素
var bird = document.querySelector("#bird");
// 獲得后臺(tái)元素
var app = document.querySelector("#app");
// 獲得分?jǐn)?shù)元素
var score = document.querySelectorAll("#score>img");
// 獲得草地
var banner = document.querySelector("#banner");
// 向左移動(dòng)的數(shù)值
banner.distanceLeft = 0;
// 記錄生成管道定時(shí)器
var pipeTimer;
// 點(diǎn)擊按鈕
start.onclick = function () {
audios[0].play();
// 重置分?jǐn)?shù)
score[0].src = score[1].src = score[2].src = "./img/0.jpg";
// 重置小鳥高度
bird.style.top = "50px";
// 清除小鳥樣式
bird.className = null;
// 隱藏開場(chǎng)動(dòng)畫及開始按鈕
startAnimate.style.display = this.style.display = 'none';
// 小鳥顯示
bird.style.display = 'block';
// 小鳥下落速度,正數(shù)向下速度无拗,負(fù)數(shù)為向上速度
bird.speed = 0;
// 允許下降最大距離:57為馬路的高度
bird.distanceMaxDecline = app.clientHeight - 57 - bird.offsetHeight;
// 是否死亡,初始值為false
bird.isDie = false;
// 小鳥總分
bird.scoreSum = 0;
// 增加定時(shí)器
bird.fly = setInterval(flyInterval.bind(bird), 30);
// 管道定時(shí)器
pipeTimer = setInterval(createPipe, 3000);
// 草地移動(dòng)
banner.timer = setInterval(bannerMove, 30);
// 為舞臺(tái)增加點(diǎn)擊事件
app.onclick = birderRise;
}
// 單擊舞臺(tái)的處理函數(shù)
function birderRise() {
audios[2].play();
// 小鳥加速度設(shè)置為-5昧碉,向上飛翔
bird.speed = -5;
}
// 小鳥飛翔計(jì)時(shí)器
function flyInterval() {
// 加速度為0.5
this.speed += 0.5;
// 如果速度為正數(shù)英染,則下落,正數(shù)上升被饿,設(shè)置圖片
this.src = this.speed > 0 ? "./img/down_bird0.png" : "./img/bird0.png";
// 小鳥下落的距離
var distanceDecline = this.offsetTop + this.speed;
// 如果觸地則死亡
if (distanceDecline > this.distanceMaxDecline) {
distanceDecline = this.distanceMaxDecline;
// 小鳥死亡
this.isDie = true;
}
// distanceDecline不允許小于0
if (distanceDecline < 0) distanceDecline = 0;
// 設(shè)置top值
this.style.top = distanceDecline + "px";
// 小鳥未亡四康,檢測(cè)管道是否與小鳥相撞
if (!this.isDie) {
var pipes = document.querySelectorAll(".pipe div");
for (var i = 0; i < pipes.length; i++) {
// 相撞
if (crashFn(pipes[i])) {
bird.isDie = true;
bird.className = "die";
break;
}
}
}
// 判斷小鳥是否死亡
if (bird.isDie) {
audios[0].pause();
audios[1].play();
// 關(guān)閉小鳥定時(shí)器
clearInterval(this.fly);
// 關(guān)閉管道定時(shí)器
clearInterval(pipeTimer);
// 關(guān)閉草地定時(shí)器
clearInterval(banner.timer);
// 顯示開場(chǎng)動(dòng)畫及開始按鈕
startAnimate.style.display = start.style.display = 'block';
}
}
// 創(chuàng)建管道
function createPipe() {
var pipe = document.createElement("div");
pipe.className = "pipe";
pipe.score = 1;// 指定增加分值
// 上管道寬度
var upHeight = getRandom(60, 263);
// 下管道的高度
var downHeight = app.clientHeight - 57 - 100 - upHeight;
pipe.innerHTML = `
<div style="height:${upHeight}px" class="pipe_up">
<img src="./img/up_pipe.png" alt="">
</div>
<div style="height:${downHeight}px" class="pipe_down">
<img src="./img/down_pipe.png" alt="">
</div>
`;
// 將創(chuàng)建的管道放置在舞臺(tái)尾部
app.appendChild(pipe);
// 增加定時(shí)器,讓管道均速移動(dòng)
pipe.moveTimer = setInterval(pipeMove.bind(pipe), 30);
}
// 管道移動(dòng)
function pipeMove() {
// 判斷小鳥是否死亡
if (bird.isDie) {
// 關(guān)閉管道移動(dòng)定時(shí)器
clearInterval(this.moveTimer)
// 清除管道
app.removeChild(this);
return;
}
// 每次移動(dòng)2像素
var distance = this.offsetLeft - 2;
// 讓管道開始移動(dòng)
this.style.left = distance + "px";
// 判斷管道是否已經(jīng)移出舞臺(tái)
if (distance < -this.offsetWidth) {
// 移除定時(shí)器
clearInterval(this.moveTimer);
// 移除管道
app.removeChild(this);
} else if (distance < -(this.offsetWidth - bird.offsetLeft)) {
// 小鳥過了管道加分
if (this.score > 0) {
bird.scoreSum += this.score;
score[0].src = "./img/" + parseInt(bird.scoreSum / 100) + ".jpg";
score[1].src = "./img/" + parseInt((bird.scoreSum % 100) / 10) + ".jpg";
score[2].src = "./img/" + parseInt(bird.scoreSum % 10) + ".jpg";
this.score = 0;
}
}
}
// 草地向左移動(dòng)
function bannerMove() {
// 向左移動(dòng)的數(shù)值 (距離)+2
banner.distanceLeft -= 2;
// 判斷最左側(cè)圖片是否消失在舞臺(tái)中
if (banner.distanceLeft < -app.clientWidth) {
// 向左移動(dòng)的距離為0
banner.distanceLeft = 0;
// 將banner當(dāng)中的第一個(gè)DOM元素放置到banner的尾部
banner.appendChild(banner.firstElementChild);
}
banner.style.left = banner.distanceLeft + "px";
}
// 是否小鳥與柱子進(jìn)行了碰撞
function crashFn(pipe) {
// 相撞:四個(gè)條件必須同時(shí)滿足
// bird與pipe
// 1- bird的右邊 大于等于 pipe的左邊
// 2- bird的下邊 大于等于 pipe的上邊
// 3- bird的左邊 小于等于 pipe的右邊
// 4- bird的上邊 小于等于 pipe的下邊
// bird:
var birdLeft = bird.offsetLeft;//左邊
var birdRight = birdLeft + bird.offsetWidth;// 右邊
var birdTop = bird.offsetTop;// 上邊
var birdBottom = birdTop + bird.offsetHeight;// 下邊
// pipe
var pipeLeft = pipe.parentNode.offsetLeft;
var pipeRight = pipeLeft + pipe.offsetWidth;
var pipeTop = pipe.offsetTop;
var pipeBottom = pipeTop + pipe.offsetHeight;
if (birdRight >= pipeLeft
&& birdBottom >= pipeTop
&& birdLeft <= pipeRight
&& birdTop <= pipeBottom) {
return true;// 相撞了
}
return false;// 沒有相撞
}
// 工具函數(shù):生成指定范圍的隨機(jī)整數(shù)
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
</script>
</html>