前端的小练习:flappyBird
体验地址: https://xiaoxinnolabi.gitee.io/flappybird
码云地址: https://gitee.com/Xiaoxinnolabi/flappyBird.git
(很粗糙,bug略多)
index.html
<!DOCTYPE html>
<html lang="en">
<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")