• libgdx自制简易Flappy Bird


    Flappy Bird,好吧,无需多说。今天年初不知咋的,一下子就火了,而且直接跃居榜首,在ios和android平台都是如此,实在难以理解。传说其作者每天收入能达到5w刀,着实碉堡了。。。

    好吧,咱没创意,不过山寨一个还是可以的,话说!!!

    好了,不罗嗦了,直接代码了。

    我使用libgdx框架(你要说是引擎也行)实现的,版本为0.9.9。就设计了一个开始画面和一个游戏画面。

    游戏入口和主类:

    package com.fxb.flappy;
    
    import com.badlogic.gdx.Game;
    
    public class FlappyBird extends Game{
    
        //static Skin skin;
        StartScreen startScreen;
        GameScreen gameScreen;
        LevelScreen levelScreen;
        
        @Override
        public void create() {
            // TODO Auto-generated method stub
            
            Assets.init();
            
            startScreen = new StartScreen(this);
            gameScreen = new GameScreen(this);
            levelScreen = new LevelScreen(this);
            
            setScreen( startScreen );
        }
    
        @Override
        public void render() {
            // TODO Auto-generated method stub
            super.render();
        }
        
        @Override
        public void dispose() {
            // TODO Auto-generated method stub
            //skin.dispose();
            Assets.clean();
            super.dispose();
        }
    
    }

    开始画面:

    package com.fxb.flappy;
    
    import com.badlogic.gdx.Gdx;
    import com.badlogic.gdx.ScreenAdapter;
    import com.badlogic.gdx.graphics.GL10;
    import com.badlogic.gdx.scenes.scene2d.InputEvent;
    import com.badlogic.gdx.scenes.scene2d.InputListener;
    import com.badlogic.gdx.scenes.scene2d.Stage;
    import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
    
    public class StartScreen extends ScreenAdapter{
        
        FlappyBird game;
        Stage stage;
        TextButton btnStart, btnMode;
        
        public StartScreen(FlappyBird game0){
            game = game0;
            stage = new Stage();
            
            btnStart = new TextButton( "Start Game", Assets.skin, "default" );
            btnStart.setSize( 150, 70 );
            Constant.CenterInStage( btnStart, stage );
            stage.addActor( btnStart );
            
            btnStart.addListener(new InputListener(){
                @Override
                public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
                    // TODO Auto-generated method stub
                    return true;
                }
                @Override
                public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
                    // TODO Auto-generated method stub
                    game.setScreen( game.gameScreen );
                    Constant.state = Constant.GameState.game_on;
                }            
            });
            
        }
    
        @Override
        public void show() {
            // TODO Auto-generated method stub
            Gdx.input.setInputProcessor( stage );
        }
        
        @Override
        public void render(float delta) {
            // TODO Auto-generated method stub
            Gdx.gl.glClearColor( 0, 1, 1, 1 );
            Gdx.gl.glClear( GL10.GL_COLOR_BUFFER_BIT );
            
            stage.act();
            stage.draw();        
        }
    
        @Override
        public void dispose() {
            // TODO Auto-generated method stub
            stage.dispose();
            super.dispose();
        }
        
    }

    游戏场景:

    package com.fxb.flappy;
    
    import com.badlogic.gdx.Gdx;
    import com.badlogic.gdx.ScreenAdapter;
    import com.badlogic.gdx.graphics.GL10;
    
    public class GameScreen extends ScreenAdapter{
        
        FlappyBird game;
        GameStage gameStage;
        OverStage overStage;
        
        
        public GameScreen(FlappyBird game0){
            game = game0;
            gameStage = new GameStage(this);
            overStage = new OverStage(this);
        }
    
        @Override
        public void show() {
            // TODO Auto-generated method stub
            Gdx.input.setInputProcessor( gameStage );
        }
        
        @Override
        public void render(float delta) {
            // TODO Auto-generated method stub
            Gdx.gl.glClearColor( 0, 1, 1, 1 );
            Gdx.gl.glClear( GL10.GL_COLOR_BUFFER_BIT );
            
            if( Constant.state == Constant.GameState.game_on ){
                gameStage.act();
                gameStage.draw();    
                Gdx.input.setInputProcessor( gameStage );
            }
            else if( Constant.state == Constant.GameState.game_preover ){
                gameStage.draw();
                overStage.act();
                overStage.draw();
                Gdx.input.setInputProcessor( overStage );
            }
    
        }
    
        @Override
        public void dispose() {
            // TODO Auto-generated method stub
            super.dispose();
        }
        
    }

    游戏舞台:

    package com.fxb.flappy;
    
    import com.badlogic.gdx.Gdx;
    import com.badlogic.gdx.graphics.OrthographicCamera;
    import com.badlogic.gdx.graphics.g2d.SpriteBatch;
    import com.badlogic.gdx.graphics.g2d.TextureRegion;
    import com.badlogic.gdx.math.MathUtils;
    import com.badlogic.gdx.scenes.scene2d.Group;
    import com.badlogic.gdx.scenes.scene2d.InputEvent;
    import com.badlogic.gdx.scenes.scene2d.InputListener;
    import com.badlogic.gdx.scenes.scene2d.Stage;
    import com.badlogic.gdx.scenes.scene2d.ui.Image;
    import com.badlogic.gdx.utils.Pool;
    import com.badlogic.gdx.utils.Pools;
    
    public class GameStage extends Stage{
    
        GameScreen gameScreen;
        Group groupUp, groupDown;
        Pool<PipeUp> poolUp;
        Pool<PipeDown> poolDown;
        Bird bird;
        Image imgBack;
        OrthographicCamera camera;
        
        int xIndex;
        float leftX = 0;
        float speed;
        float currentTime;
        float lastTouchTime;
        
        public GameStage( GameScreen gameScreen0 ){
            gameScreen = gameScreen0;
            
            groupUp = new Group();
            groupDown = new Group();
            
            poolUp = Pools.get( PipeUp.class );
            poolDown = Pools.get( PipeDown.class );
            
            bird = new Bird();
            imgBack = Constant.CreateImage( Assets.regionBack );
            camera = new OrthographicCamera( Assets.regionBack.getRegionWidth(), Assets.regionBack.getRegionHeight() );
            camera.position.set( Assets.regionBack.getRegionWidth()/2, Assets.regionBack.getRegionHeight()/2, 0 );
            
            //addActor( imgBack );
            addActor( bird );
            addActor( groupUp );
            addActor( groupDown );
                            
            this.addListener(new InputListener(){
                @Override
                public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
                    // TODO Auto-generated method stub
                    if( currentTime - lastTouchTime > 0.15f ){
                        if( bird.speedY < 0 ){
                            bird.speedY += 15;                        
                        }
                        else if( bird.speedY < 5 ){
                            bird.speedY += 15;
                        }
                        else if( bird.speedY < 8 ){
                            bird.speedY += 8;
                        }
                        else{
                            bird.speedY += 4;
                        }
    
                        if( bird.speedY > 25 ){
                            bird.speedY = 25;
                        }
                        lastTouchTime = currentTime;
                    }
                    return true;
                }        
            });
            
            
            Clear();        
        }
        
        public void Clear(){
            xIndex = 3;
            //this.camera.translate( -leftX, 0 );
            //this.camera.position.set( getWidth()/2, getHeight()/2, 0 );
            this.getCamera().translate( -leftX, 0, 0 );
            leftX = 0;
            
            speed = 2f;
            currentTime = 0;
            lastTouchTime = -1f;
            
            bird.Clear();
            
            groupUp.clear();
            groupDown.clear();
            poolUp.clear();
            poolDown.clear();
            
            for( int i=0; i<xIndex; ++i ){
                AddPipe(i);            
            }
                
            Gdx.input.setInputProcessor(this);
        }
        
        public void AddPipe( int xIndex0 ){
            PipeUp pipeup = poolUp.obtain();        
            PipeDown pipedown = poolDown.obtain();        
                    
            groupUp.addActor( pipeup );
            groupDown.addActor( pipedown );
            
            float rate1 = MathUtils.random( 0.2f, 1.3f );
            float rate2 = 1.5f - rate1;
            
            //rate1 = 0.8f;
            //rate2 = 0.2f;
            
            int height1 = (int)( Assets.regionPipeUp.getRegionHeight()*rate1 );
            int height2 = (int)( Assets.regionPipeDown.getRegionHeight()*rate2 );
            
            if( rate1 < 1 ){
                pipeup.region = new TextureRegion( Assets.regionPipeUp, 0, Assets.regionPipeUp.getRegionHeight()-height1, Assets.regionPipeUp.getRegionWidth(), height1 );
                pipeup.setHeight( height1 );
            }
            else{
                pipeup.region = Assets.regionPipeUp;
                pipeup.setHeight( height1 );
            }
            
            if( rate2 < 1 ){
                pipedown.region = new TextureRegion( Assets.regionPipeDown, 0, 0, Assets.regionPipeDown.getRegionWidth(), height2 );
                pipedown.setHeight( height2 );
            }
            else{
                pipedown.region = Assets.regionPipeDown;
                pipedown.setHeight( height2 );
            }
            
            //pipedown        
            pipeup.setPosition( getWidth()+xIndex0*300, getHeight()-pipeup.getHeight() );
            pipedown.setPosition( getWidth()+xIndex0*300, 0 );
        }
            
        @Override
        public void act() {
            // TODO Auto-generated method stub
            
            leftX += speed;
            this.getCamera().translate( speed, 0, 0 );
            bird.translate( speed, bird.speedY );
            
            currentTime += Gdx.graphics.getDeltaTime();
            
            boolean isDis = false;
            for( int i=0; i<groupUp.getChildren().size; ++i ){
                PipeUp pipeup = (PipeUp)groupUp.getChildren().items[i];
                if( pipeup.getRight() < leftX ){
                    groupUp.removeActor( pipeup );
                    poolUp.free( pipeup );
                    if( !isDis ){
                        isDis = true;                    
                    }
                }
                
                if( Constant.IsCollsion( pipeup, bird )  ){
                    //Gdx.app.exit();
                    Constant.state = Constant.GameState.game_preover;
                }
            }
    
            for( int i=0; i<groupDown.getChildren().size; ++i ){
                PipeDown pipedown = (PipeDown)groupDown.getChildren().items[i];
                if( pipedown.getRight() < leftX ){
                    groupDown.removeActor( pipedown );
                    poolDown.free( pipedown );
                    if( !isDis ){
                        isDis = true;                    
                    }
                }
                
                if( Constant.IsCollsion( pipedown, bird )  ){
                    //Gdx.app.exit();
                    Constant.state = Constant.GameState.game_preover;
                }
            }
            
            if( isDis ){
                AddPipe( xIndex );
                xIndex++;
            }
            
            if( bird.getY() < 0 ){
                Constant.state = Constant.GameState.game_preover;
            }
            
            
            super.act();
        }
        
        @Override
        public void draw() {
            // TODO Auto-generated method stub    
            camera.update();
            
            SpriteBatch batch = this.getSpriteBatch();
            batch.setProjectionMatrix(camera.combined);
            batch.begin();
            batch.draw( Assets.regionBack, 0, 0 );
            batch.end();
                
            super.draw();
        }
    
        @Override
        public void dispose() {
            // TODO Auto-generated method stub
            super.dispose();
        }
        
    }

    游戏结束舞台:

    package com.fxb.flappy;
    
    import com.badlogic.gdx.Gdx;
    import com.badlogic.gdx.scenes.scene2d.InputEvent;
    import com.badlogic.gdx.scenes.scene2d.InputListener;
    import com.badlogic.gdx.scenes.scene2d.Stage;
    import com.badlogic.gdx.scenes.scene2d.ui.Label;
    import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
    import com.badlogic.gdx.scenes.scene2d.ui.Window;
    
    public class OverStage extends Stage{
        
        Window window;
        TextButton button1;
        TextButton button2;
        Label label;
        GameScreen gameScreen;
        
        public OverStage(GameScreen gameScreen0){
            gameScreen = gameScreen0;
            
            window = new Window( "", Assets.skin );
            //window.add( "GAME OVER
    " );
            
            label = new Label( "GAME OVER", Assets.skin );
            //label.setFontScale( 1.0f );
            
            button1 = new TextButton( "Again", Assets.skin );
            button2 = new TextButton( "Exit", Assets.skin );
            
            
            button1.addListener( new InputListener(){
                @Override
                public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
                    // TODO Auto-generated method stub
                    return true;
                }
    
                @Override
                public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
                    // TODO Auto-generated method stub
                    Constant.state = Constant.GameState.game_on;
                    gameScreen.gameStage.Clear();
                }        
            });
            
            button2.addListener( new InputListener(){
                @Override
                public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
                    // TODO Auto-generated method stub
                    return true;
                }
    
                @Override
                public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
                    // TODO Auto-generated method stub
                    //Constant.state = Constant.GameState.game_on;
                    Gdx.app.exit();
                }        
            });
            
            window.setSize( getWidth()/2, getHeight()/6 );
            window.addActor( button1 );
            window.addActor( button2 );
            window.addActor( label );
            
            button1.setSize( 60, 30 );
            button2.setSize( 60, 30 );
            label.setSize( 100, 50 );
            button1.setPosition( window.getWidth()/8, 10 );
            button2.setPosition( window.getWidth()*7/8-button2.getWidth(), 10 );
            label.setPosition( window.getWidth()/2-label.getWidth()/2, button2.getTop()+20 );
            
            this.addActor( window );
            Constant.CenterInStage( window, this );
        }
        
        
    
    }

    游戏主角类,即那只鸟

    package com.fxb.flappy;
    
    import com.badlogic.gdx.Gdx;
    import com.badlogic.gdx.graphics.g2d.Animation;
    import com.badlogic.gdx.graphics.g2d.SpriteBatch;
    import com.badlogic.gdx.graphics.g2d.TextureRegion;
    import com.badlogic.gdx.scenes.scene2d.Actor;
    
    public class Bird extends Actor{
    
        Animation animation;
        float currentTime;
        float speedY;
        
        public Bird(){
            animation = new Animation( 0.15f, Assets.sRegionBird );
            setSize( Assets.sRegionBird[0].getRegionWidth(), Assets.sRegionBird[0].getRegionHeight() );
            setOrigin( getWidth()/2, getHeight()/2 );
            //setPosition(  );
            Clear();
        }
        
        public void Clear(){
            currentTime = 0;
            setPosition( 100, Gdx.graphics.getHeight()/2-getHeight()/2 );
            speedY = Constant.speedY;
        }
        
        @Override
        public void act(float delta) {
            // TODO Auto-generated method stub        
            currentTime += delta;
            
            //this.translate( 0, speedY  );
            //speedY -= 0.5f;
            
            if( speedY > -10f ){
                speedY += Constant.speedInc;
            }
            
            super.act(delta);
        }
        
        @Override
        public void draw(SpriteBatch batch, float parentAlpha) {
            // TODO Auto-generated method stub
            
            TextureRegion keyFrame = animation.getKeyFrame( currentTime, true );
            
            batch.draw( keyFrame, getX(), getY(), getOriginX(), getOriginY(), getWidth(), getHeight(), getScaleX(), getScaleY(), getRotation() );
            
            super.draw(batch, parentAlpha);
        }
    
    }

    上面管道类

    package com.fxb.flappy;
    
    import com.badlogic.gdx.graphics.g2d.SpriteBatch;
    import com.badlogic.gdx.graphics.g2d.TextureRegion;
    import com.badlogic.gdx.scenes.scene2d.Actor;
    
    public class PipeUp extends Actor{
        
        TextureRegion region;
        
        public PipeUp(){
            region = new TextureRegion( Assets.regionPipeUp );
            setSize( region.getRegionWidth(), region.getRegionHeight() );
        }
        
        /*
        public UpdateRegion(){
            region = new TextureRegion( Assets.regionPipeUp );
        }
        */
        @Override
        public void act(float delta) {
            // TODO Auto-generated method stub
            super.act(delta);
        }
        
        
        @Override
        public void draw(SpriteBatch batch, float parentAlpha) {
            // TODO Auto-generated method stub
            
            //batch.draw( region, region.getRegionX(), region.getRegionY(), region.getRegionWidth(), region.getRegionHeight() );
            batch.draw( region, getX(), getY(), getWidth(), getHeight() );
            
            super.draw(batch, parentAlpha);
        }
    }

    下面管道类:

     1 package com.fxb.flappy;
     2 
     3 import com.badlogic.gdx.graphics.g2d.SpriteBatch;
     4 import com.badlogic.gdx.graphics.g2d.TextureRegion;
     5 import com.badlogic.gdx.scenes.scene2d.Actor;
     6 
     7 public class PipeDown extends Actor{
     8 
     9     TextureRegion region;
    10     
    11     public PipeDown(){
    12         region = new TextureRegion( Assets.regionPipeDown );
    13         setSize( region.getRegionWidth(), region.getRegionHeight() );
    14     }
    15     
    16     @Override
    17     public void act(float delta) {
    18         // TODO Auto-generated method stub
    19         super.act(delta);
    20     }
    21     
    22     
    23     @Override
    24     public void draw(SpriteBatch batch, float parentAlpha) {
    25         // TODO Auto-generated method stub
    26         //batch.draw( region, region.getRegionX(), region.getRegionY(), region.getRegionWidth(), region.getRegionHeight() );
    27         batch.draw( region, getX(), getY(), getWidth(), getHeight() );
    28         super.draw(batch, parentAlpha);
    29     }
    30 }
    View Code

     资源类:

     1 package com.fxb.flappy;
     2 
     3 import com.badlogic.gdx.Gdx;
     4 import com.badlogic.gdx.assets.AssetManager;
     5 import com.badlogic.gdx.graphics.g2d.TextureAtlas;
     6 import com.badlogic.gdx.graphics.g2d.TextureRegion;
     7 import com.badlogic.gdx.scenes.scene2d.ui.Skin;
     8 
     9 public class Assets {
    10     public static Skin skin;
    11     public static AssetManager manager;
    12     public static TextureAtlas atlas; 
    13     public static TextureRegion[] sRegionBird;
    14     
    15     public static TextureRegion regionPipeUp;
    16     public static TextureRegion regionPipeDown;
    17     public static TextureRegion regionBack;
    18     
    19     public static void init(){
    20         skin = new Skin( Gdx.files.internal( "skin/uiskin.json" ) );
    21         atlas = new TextureAtlas( Gdx.files.internal( "data/bird.pack" ) );
    22         
    23         sRegionBird = new TextureRegion[3]; 
    24         for( int i=0; i<sRegionBird.length; ++i ){
    25             sRegionBird[i] = atlas.findRegion( "bird_blue", i );            
    26         }
    27         
    28         regionPipeUp = atlas.findRegion( "bound_up" );
    29         regionPipeDown = atlas.findRegion( "bound_down" );
    30         regionBack = atlas.findRegion( "background" );
    31 
    32     }
    33     
    34     public static void clean(){
    35         if( skin != null ) skin.dispose();
    36         if( atlas != null ) atlas.dispose();
    37         
    38     }
    39 }
    View Code

    常量及功能函数类:

     1 package com.fxb.flappy;
     2 
     3 import com.badlogic.gdx.graphics.g2d.TextureRegion;
     4 import com.badlogic.gdx.scenes.scene2d.Actor;
     5 import com.badlogic.gdx.scenes.scene2d.Stage;
     6 import com.badlogic.gdx.scenes.scene2d.ui.Image;
     7 
     8 public class Constant {
     9     
    10     enum GameState{ game_ready, game_on, game_preover, game_over };
    11     public static GameState state = GameState.game_ready;
    12     
    13     public static float speedY = -1f;
    14     public static float speedInc = -0.5f;
    15     
    16     public static void CenterInStage( Actor actor, Stage stage ){
    17         actor.setPosition( stage.getWidth()/2-actor.getWidth()/2, stage.getHeight()/2-actor.getHeight()/2 );
    18     }
    19     
    20     public static Image CreateImage( TextureRegion region0 ){
    21         Image img = new Image( region0 );
    22         img.setSize( region0.getRegionWidth(), region0.getRegionHeight() );
    23         return img;
    24     }
    25     
    26     public static boolean IsCollsion( Actor actor1, Actor actor2 ){
    27         float x1 = actor1.getX(), y1 = actor1.getY(), w1 = actor1.getWidth(), h1 = actor1.getHeight();
    28         float x2 = actor2.getX(), y2 = actor2.getY(), w2 = actor2.getWidth(), h2 = actor2.getHeight();
    29         if( x1<x2 && x1+w1<x2 ){
    30             return false;
    31         }
    32         else if( x2<x1 && x2+w2<x1 ){
    33             return false;
    34         }
    35         else if( y1<y2 && y1+h1<y2 ){
    36             return false;
    37         }
    38         else if( y2<y1 && y2+h2<y1 ){
    39             return false;
    40         }
    41         
    42         return true;
    43     }
    44 
    45 }
    View Code

    大概就这样了,也是比较粗糙。自己试验了下,在android平台下感觉操作不太顺手,可能里面一些参数还是没有调整好,提升的空间挺大的!!

  • 相关阅读:
    存储过程为参数NULL时的处理方法
    查询数据占比
    ROW_NUMBER() OVER()函数用法;(分组,排序),partition by
    存储过程 set 和 select 对变量赋值的区别 (转自Theo)
    对布尔值取反,使用 ~
    创建存储过程
    JavaScript验证密码强度
    一些简单的JavaScript的方法
    递归方式实现树的展示形式
    ASP.NET验证控件详解
  • 原文地址:https://www.cnblogs.com/MiniHouse/p/3739394.html
Copyright © 2020-2023  润新知