天天看点

Phaser框架下的flappyBird

前端的小练习: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")
           

继续阅读