前端的小練習:flappyBird
體驗位址: https://xiaoxinnolabi.gitee.io/flappybird
碼雲位址: https://gitee.com/Xiaoxinnolabi/flappyBird.git
(很粗糙,bug略多)
index.html
<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>FlappyBird</title>
<script src="js/phaser.min.js"></script>
</head>
<body>
<center>
<!--放置遊戲畫面-->
<div id="game"></div>
<p style="text-align: center;font-family:Arial, Helvetica, sans-serif;">隻要你飛得夠高,你就能夠穿越山河大海</p>
</center>
</body>
<script src="js/game.js"></script>
</html>
game.js
// 放置遊戲邏輯代碼
const game = new Phaser.Game(320,505,Phaser.AUTO,"game")//(遊戲寬度、高度、渲染方式、盒子ID)
//在game對象裡面添加一個gameStates屬性 ,放置遊戲場景
game.gameStates = {}
//放入menu場景
game.gameStates.menu=function(){
//一個合法場景必須有以下三個功能中一個
//1 加載資源
this.preload=function(){
game.load.image('background','assets/background.png')
game.load.image('ground','assets/ground.png')
game.load.image('game_over','assets/gameover.png')
game.load.spritesheet('bird','assets/bird.png',34,24,3)//(命名、圖檔位置、寬度、高度、幀數)
game.load.image('title','assets/title.png')//加載題目圖檔
game.load.image('btnImg','assets/start-button.png')
//加載管道圖檔
game.load.spritesheet('pipe','assets/pipes.png',54,320,2)
game.load.audio('fly_sound','assets/flap.wav')
game.load.audio('score_sound','assets/score.wav')
//字型
game.load.bitmapFont('fly_font','assets/fonts/flappyfont/flappyfont.png','assets/fonts/flappyfont/flappyfont.fnt')
}
//2 加載資源後,進入create()方法
this.create=function(){
//const 定義常量 局部常量
const mybg=game.add.tileSprite(0,0,game.width,game.height,"background")//瓷磚精靈:(x軸,y軸,寬度,高度,對象)
const ground=game.add.tileSprite(0,game.height-112,game.width,112,"ground")//地闆
const titleGroup = game.add.group()//在遊戲對象添加一個組 titleGroup
titleGroup.create(0,0,'title')//(x軸位置,y軸位置,加入什麼元素)
const bird = titleGroup.create(190,0,'bird')//小鳥加入組
bird.animations.add('fly')//('動畫名字')
bird.animations.play('fly',16,true)//(動畫名字,每秒多少張圖檔,是否重複播放)
titleGroup.x=50
titleGroup.y=140
//tween(控制對象).to(位置,時間,緩動類型,是否自動開始,延遲幾秒開始,重複幾次,來回循環)緩動
game.add.tween(titleGroup).to({y:120},1000,null,true,0,Number.MAX_VALUE,true)
const btn = game.add.button(game.width/2,game.height/2,'btnImg',function(){
//點選後效果:跳轉到第二個
game.state.start("mysence2")
})//(x,y,填加進去的是什麼,執行的效果)
btn.anchor.setTo(0.5,0.5)//anchor修改按鈕中心點
mybg.autoScroll(-15,0)//重複自動滾動 (x,y)
ground.autoScroll(-100,0)
}
//3 時時刻刻監測的内容
this.update=function(){}
}
game.gameStates.play=function(){
//加載資源
this.preload=function(){
}
//資源加載後的場景
this.create=function(){
this.mybg=game.add.tileSprite(0,0,game.width,game.height,"background")//瓷磚精靈:(x軸,y軸,寬度,高度,對象)
//添加管道組
this.pipeGroup= game.add.group()
//添加聲音
this.flySound=game.add.audio('fly_sound')
this.scoreSound=game.add.audio('score_sound')
//開啟實體引擎
this.pipeGroup.enableBody=true
this.startGameFlag=false
this.ground=game.add.tileSprite(0,game.height-112,game.width,112,"ground")//地闆
//加載字型
this.scoreGroup=game.add.group()
this.scoreText=game.add.bitmapText(game.width/2,100,'fly_font','0',40,this.scoreGroup)
// this.scoreText.anchor.setTo(0.5,0.5)
this.bird = game.add.sprite(50,100,'bird')//小鳥加入組
this.bird.animations.add('fly')//('動畫名字')
this.bird.animations.play('fly',16,true)//(動畫名字,每秒多少張圖檔,是否重複播放)
this.bird.anchor.setTo(0.5,0.5)
//開啟實體引擎(physics.enable(引擎作用的對象,使用的實體引擎))
game.physics.enable(this.bird,Phaser.Physics.ARCADE)
game.physics.enable(this.ground,Phaser.Physics.ARCADE)
this.ground.body.immovable=true
//1.點選螢幕(事件,綁定到對象)
game.input.onDown.addOnce(this.startGame,this)//this.startGame隻要監聽一次用addOnce
}
//實時更新需要的場景
this.update=function(){
if(this.startGameFlag==false){
return
}
//collide碰撞(對象A,對象B,碰撞後執行的方法,回調,對象)
game.physics.arcade.collide(this.bird,this.ground,this.hit,null,this)
//碰撞檢測 一旦碰撞,停止
game.physics.arcade.overlap(this.bird,this.pipeGroup,this.hitPipe,null,this)
if(this.bird.angle<90 ){
this.bird.angle+=3
}
//得分檢測:檢測存在于螢幕中的物體,第二個隻能用于組
this.pipeGroup.forEachExists(this.checkScore,this)
}
//2.開始遊戲
//使用者定義startGame
this.startGame=function(){
this.score=0
this.mybg.autoScroll(-15,0)//重複自動滾動 (x,y)
this.ground.autoScroll(-100,0)
//一旦開啟實體引擎,就有body屬性
this.bird.body.gravity.y=1000
this.startGameFlag=true
game.input.onDown.add(this.fly,this)
//定時器 制作管道
this.Timer =game.time.events.loop(1000,this.makePipe,this)
}
//撞擊管道後
this.hitPipe=function(){
this.gameOver()
}
//分數檢測
this.checkScore=function(pipe){
//pipe是形參,是this.pipeGroup
if(!pipe.hasScore && pipe.y<=0 && pipe.x < this.bird.x-54){
this.scoreSound.play()
pipe.hasScore=true
this.score++
this.scoreText.text = this.score
console.log(this.score)
}
return
}
//結束遊戲
this.gameOver=function(){
//停止地闆和背景動畫
this.ground.stopScroll()
this.mybg.stopScroll()
//停止飛翔動作
this.bird.animations.stop('fly',0)
//移除滑鼠單擊事件的監聽
game.input.onDown.remove(this.fly,this)
//停止管道生成
this.pipeGroup.setAll('body.velocity.x',0)
game.time.events.remove(this.Timer)
//加載重新開始界面
this.restartGame()
}
//重新開始
this.restartGame=function(){
this.gameOverGroup = game.add.group()
const gameOverText = this.gameOverGroup.create(game.width/2,60,'game_over')
gameOverText.anchor.setTo(0.5,0.5)
const replayBtn=game.add.button(game.width/2,180,'btnImg',function(){
game.state.start('mysence1')
})
replayBtn.anchor.setTo(0.5,0.5)
}
//制作管道
this.makePipe=function(){
gam=100//空隙 空隙在85-320之間都是合理的
//math.random() 0-1 :Math.random(235)+85 管道的随機位置
const position = Math.floor(Math.random()*235)+85
const topPipeY = position -320//上管道
const bottomPipeY = position + 100//下管道
const topPipe = game.add.sprite(game.width,topPipeY,'pipe',0,this.pipeGroup)
const bottomPipe = game.add.sprite(game.width,bottomPipeY,'pipe',1,this.pipeGroup)
this.pipeGroup.setAll('body.velocity.x',-200)
}
//小鳥向上飛
this.fly=function(){
this.flySound.play()
//1 頭部向上揚起
game.add.tween(this.bird).to({angle:-30},100,null,true,0,0,false)
//2 小鳥向上運動
this.bird.body.velocity.y=-300//一次性
// 重力恒定this.bird.body.gravity.y=-300
}
//使用者定義this.hit
this.hit=function(){
//停止地闆和背景動畫
this.ground.stopScroll()
this.mybg.stopScroll()
//停止飛翔動作
this.bird.animations.stop('fly',0)
//移除滑鼠單擊事件的監聽
game.input.onDown.remove(this.fly,this)
//停止管道生成
this.pipeGroup.setAll('body.velocity.x',0)
game.time.events.remove(this.Timer)
//加載重新開始界面
this.restartGame()
}
}
game.state.add("mysence1",game.gameStates.menu)
game.state.add("mysence2",game.gameStates.play)
game.state.start("mysence1")