2D games

LibGDX Game Tutorial

LibGDX  is a powerful video game framework . I’ve been using it for some time now with my projects. Mostly cause its free and offers good portability and libraries.

I made this game as a learning exercise using libGDX and some of its libraries .
The code is by no means perfect, but I hope it helps you get on the right track if you are looking to develop a game Using libGDX. Also, even though libGDX is a cross-platform framework, I only targeted Android and desktop for testing . 

Note: I assume you have prior experience in using java and you know how to setup the ADT with eclipse .I also won’t be explaining much on libGDX or anyother libraries used (tween for animation and transitions) I’m only taking you through my own implementation . So if you get lost I recommend you read the libGDX wiki. You should also know that I’m doing this tutorial in a top to bottom manner . So I am going to implement this project starting from the beginning of the app i.e when app is launched ,its a strange way to do things since most people   work on gameplay first. 

By the end of this tutorial you should be able to make a game that looks like this.


Game Concept.

The game concept is simple . You have to help red (a bird) to collect as many of her eggs as possible before it gets killed by moving square blocks . I know its cheesy but it will do . The player controls red by swiping across the screen.

With our awesome design done, let’s build the game!

Creating the project.


Let’s  setup our project  with the gdx-setup . There are  two setup’s that we can use . The newer gradle setup or an older setup .You can double click on the jar to make it run but it doesn’t work on my computer so I will be using the cmd.

If you dont know how to use the cmd to run a jar file .

  • Open cmd by typing “cmd” in your search box
  • Type” cd/ “to go to the begining  of your hard drive and navigate to where your jar files are . use “dir” in order to see what is in the current directory.
  • Once you find your jars type”java  -jar name of your jar”

Then wait until your jar starts .It should look something like this.

We are not going to be using any extensions and I’m only targeting android  and desktop  but don’t worry if you want to add more platforms  you can but you will need an emulator  in order to test and run your program in Html and Ios.

Importing Project into Eclipse .



Once you import your project into eclipse  it will have several errors ,so lets fix them.

  • You can delete the code  in your core project but leave the class declaration.
  • In the android package  you need to delete the line 

 Cfg.20 =false;

  • Then right click on your android project and go to properties .On the list select Android and check the Project Build Target and click apply .

  • Finally in the desktop project do the first step you did on the android  project . 

Time to Code.

After cleaning your code the game class should look like this after extending the Game class.This class allows us to create multiple screens.

Package com.me.mygdxgame;

Import com.badlogic.gdx.Game

Public class MygdxGame extends Game{   

     @override

Public void create(){}

@override

Public void dispose(){}

 
Now create a new package called screens and add three new classes Gamescreen ,Splashscreen,Menuscreen.They should all look like this

package com.screens;

import com.badlogic.gdx.Screen;

public class GameScreen implements Screen {

    @Override

    public void render(float delta) {

    }

    @Override

    public void resize(int width, int height) {

    }

    @Override

    public void show() {

    }

    @Override

    public void hide() {

    }

    @Override

    public void pause() {

    }
    @Override

    public void resume() {

    }

    @Override

    public void dispose() {

    }

 Now we need to tell our game class to set the Splashscreen when our game starts.

Package com.me.mygdxgame;

Import com.badlogic.gdx.Game

Public class MygdxGame extends Game{   

     @override

Public void create(){

setScreen (new Splashscreen (this));

}

@override 

Now we setup the splashscreen so that we can display our splash as our game is loading assets .  We will need the tween engine so that we can add a smooth fade in and fade out effect.  In order to add tween to your project you need to again open your project setup and click update then add the tween package just like you did with libgdx.

The splashscreen class done.

Package com.screens 

Public class splashscreen{

Private TweenManager manager;

Private Spritebatch batcher;

Private Sprite  sprite; 

Private  MyGdxGame game;

Public splashscreen(MyGdxGame game){this.game=game;}

@override 

Public void show(){

sprite = new Sprite(Assetloader.logo);

sprite.setColor(1,1,1,0);

float width = Gdx.graphics. getWidth();

float height = Gdx.graphics. getHeight();

float desiredWidth = width *.7f

float  scale = desiredWidth / spirte.getWidth(); 

sprite.setSize(sprite.getWidth() * scale ,sprite.getHeight*scale);

sprite.setPosition((width/2)-(sprite.getWidth()/2),(height /2)-(sprite.getHeight()/2));

setupTween();

}

private void setupTween(){

Tween.register Accessor(Sprite.class,new SpriteAccessor());

manager = new  TweenManager();

TweenCallback back = new TweenCallback(){

@override

Public void onEvent(int type,BaseTween<?>source){

game.setScreen(new MenuScreen(game));

}

};

Tween.to(spriteAccessor.ALPHA, .8f).target (1).ease(TweenEquations.easeInQuad).repeatYoyo(1,.4f).setCallback(back).setCallbackTriggers(TweenCallback.COMPLETE).start(manager);

@override

Public void render(float delta){

manager.update(delta);

Gdx.gl.glClearColor(1,1,1,1);

Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

batch.begin();

sprite.draw(batch);

batch.end() ;

}


Our splash screen.

Adding this code to your splashscreen will cause a ton of errors .To fix them we need to create another package tween and a dd  three new classes spriteAccessor,Value,ValueAccessor.

The spriteAccessor class .

Package tween;

Public class spriteAccessor implements TweenAccessor<Sprite>{

public static final int ALPHA = 1;

@override

Public int getValues(Sprite target, int tweenType, float[] returnValues){

switch(tweenType){

case ALPHA:

returnValues[0] = target.getColor().a;

return 1;

default:

return 0;}

@override

Public void setValues(Sprite target, int tweenType,float[]returnValues){

switch(tweenType){

Case ALPHA:

target.setColor(1,1,1,newValues);

break;

}}

The value class.

package com.tween;

public class Value{

private float val = 1;

public float getValue(){

return val;

}

public void setValue(float newVal){

val = newVal;}}

The valueAccessor class.

package com.tween;

public class  ValueAccessor implements TweenAccessor<Value>{

@override

Public int getValues(Values target,int tweenType,float[] returnValues){

returnValues[0] =target.getValue();

return 1;

}

@override

public void setValues(Value target , int tweenType,float[] newValues){

target.setValue(newValues[0])

And that does it for the tween package.but we still have some errors . So lets create a new package called utils  we are  going to create our asset loader class in here it will load all our assets at start up .

Package utils;

public class AssetLoader{

Public static Texture logo;

public static void load(){

logo =new Texture(Gdx.files.internal (“logo.png”));

}

public static void destroy(){

logo.dispose

As you can see we have imported our logo to be used by the splashscreen . You need to remember to dispose of the assets you import.Now we need to update our game class so that our assets can be loaded at start up.

Note : You need to put all your assets in the android assets folder for them to get added to your project.

Package com.me.mygdxgame;

Import com.badlogic.gdx.Game

Public class MygdxGame extends Game{   

 @override

Public void create(){

Assetloader.load();

setScreen (new Splashscreen (this));

}

Setting Up the World.

Now we need a world for our red bird . Create a new package called world  and create  a world class.This class is responsible for our game object getting updated . We also need a render class in order to draw all our objects to the screen.

Now lets put these two new classes to use . Open the Gamescreen class and update the code with the one below .The finished gamescreen class. 

public class GameScreen implements Screen{

   

 private World world;

 private Renderer renderer;

 private float runTime;

 

    public GameScreen(){

 

  float screenWidth=Gdx.graphics.getWidth();

  float screenHeight=Gdx.graphics.getHeight();

  float gameHeight=408;

  float gameWidth=screenWidth/(screenHeight/gameHeight);

 

  int screenY=(int)(gameHeight/2);

 

  world=new World(screenY);

  renderer=new Renderer(world,(int)gameWidth,screenY);

  world.setRenderer(renderer);

 }

 

 @Override

 public void show() {

 

 

 }

 @Override

 public void render(float delta) {

  runTime+=delta;

  world.update(delta);

  renderer.render(delta,runTime);

 

 }

Thats it for now  next time we will add code to our world class and renderer as well as adding our bird to the world.

If you have any questions or comments, feel free to let me know in the comments section.

Cheers!

Uncategorized

Lwjgl 3D Game Engine

Welcome to the second part .Today we are going make our window and an interface class that will make our engine reusable to make different type of games . Any class that will implement the interface will inherit all its methods . 

package gameLoop;

public interface Game{

void audio();

void dispose();

void render();

void update(float time);

void input();

void init()throws Exception;

}

OK now  we can create our window . So create a new class called Display.

Public class Display{

public static final into width = 800;

public static final int  height = 600;

private static long lastFrameTime ;

private static float delta;

private static int last frame;

private static int fps;

private static long lastFps;

public static boolean vsync;

We define some properties for our window ,the width and height . The other variables will help us calculate our fps at run time . Vsync  prevents screen tearing  but  we define it as a boolean because  we want to be able to change it at runtime .

public static void createDisplay(){

ContextAttribs attribs = new ContextAttribs(3,2).withForwardCompatible(true).withProfileCore(true);

try{

Display. setDisplayMode(new Display Mode(WIDTH,HEIGHT));

Display. create(new PixelFormat().withDepthBits(24),attribs);

Display. setTitle(“Game Engine”);

Display. setInitialBackground(1,1,1);

GL11.glEnable (GL13.GL_MULTISAMPLE);

}catch(LWJGLException e){

e.printStackTrace();

System.err.printing(“Couldn’t create display”);

System. exit(-1);

}

GL11.glViewport(0,0,WIDTH, HEIGHT);

lastFrameTime = getCurrentTime();

getDelta();

lastFps  = get time();

}

We create our display in this method and set its parameters . When you create the context you need to input the opengl version  supported by your GPU .In my case its 3,2 . 

public static float getCurrentTime(){

return Sys.get time()*1000/Sys.getTimerResolution();

}

public static void update display(){

Display. sync(GameEngine.TARGET_FPS);

Display.update ();

long current FrameTime = getCurrentTime();

delta = (current FrameTime – lastFrameTime)/1000f;

lastFrameTime = current FrameTime;

updateFps();

update(delta);

}

public static float getFrameTimeSeconds(){

return delta;}

public static void destroyDisplay(){

Display. destroy;}

public static void update (float delta){

while(Keyboard.next()){

if(keyboard.getEventKeyState()){ if(keyboard. getEventKey()==keyboard. KEY_F){

setDisplayMode(WIDTH, HEIGHT,! Display. isFullscreen());}

if(keyboard.get eventKey()==keyboard. KEY_V){

vsync =!vsync;

Display. setVSyncEnable(vsync);

}}}}

we sync the display to update at our target frame rate  . We also make it possible for us to change both the screen settings (between full screen and window mode) and vsync. The rest of the code is self explanatory . The finished Display class.



public static final int WIDTH = 800;

 public static final int HEIGHT = 600;

 

 private static long lastFrameTime;

 private static float delta;

 

    private static int lastFrame;

 

 private static int fps;

 

 private static long lastFps;

 

 public static boolean vsync;

 


 public static void createDisplay(){

  ContextAttribs attribs = new ContextAttribs(1,3)

  .withForwardCompatible(true);

 

  try {

   

   Display.setDisplayMode(new DisplayMode(WIDTH,HEIGHT));

   Display.create(new PixelFormat().withDepthBits(24), attribs);

   Display.setTitle(“Game enginet”);

   Display.setInitialBackground(1, 1, 1);

   GL11.glEnable(GL13.GL_MULTISAMPLE);

   

  } catch (LWJGLException e) {

   e.printStackTrace();

   System.err.println(“Couldn’t create display!”);

   System.exit(-1);

  }

 

 

  GL11.glViewport(0,0,WIDTH,HEIGHT);

  lastFrameTime = getCurrentTime();

  getDelta();

  lastFps = getTime();

 }

 private static long getCurrentTime() {

  return Sys.getTime()*1000/Sys.getTimerResolution();

 }

 public static void updateDisplay(){

  Display.sync(GameEngine.TARGET_FPS);

  Display.update();

 

  long currentFrameTime = getCurrentTime();

  delta = (currentFrameTime – lastFrameTime)/1000f;

  lastFrameTime = currentFrameTime;

  updateFps();

  update(delta);

 }

 public static float getFrameTimeSeconds(){

  return delta;

 }

 public static void destroyDisplay(){

   Display.destroy();

 

 }

   public static void update(float delta){

 

  while(Keyboard.next()){

   if(Keyboard.getEventKeyState()){

    if(Keyboard.getEventKey()==Keyboard.KEY_F){

     setDisplayMode(WIDTH,HEIGHT,!Display.isFullscreen());

    }

    if(Keyboard.getEventKey() == Keyboard.KEY_V){

     

      vsync =!vsync;

      Display.setVSyncEnabled(vsync);

     

    }

   }

  }

 

 }

   

   public static void setDisplayMode(int width,int height,boolean fullscreen){

 

  if((Display.getDisplayMode().getWidth() == width)&&

    (Display.getDisplayMode().getHeight() == height)&&

    (Display.isFullscreen() == fullscreen)){

   return;

  }

 

  try{

   DisplayMode targetDisplayMode = null;

   

   if(fullscreen){

    DisplayMode[] modes = Display.getAvailableDisplayModes();

    int freq = 0;

   

    for(int i = 0;i<modes.length;i++){

     DisplayMode current = modes[i];

     

     if((current.getWidth() == width)&&(current.getHeight()==height)){

     

      if((targetDisplayMode ==null)||(current.getFrequency()>=freq)){

       

       if((targetDisplayMode ==null)||(current.getBitsPerPixel()>targetDisplayMode.getBitsPerPixel()))

       {

        targetDisplayMode = current;

        freq = targetDisplayMode.getFrequency();

       }

      }

      if((current.getBitsPerPixel() == Display.getDesktopDisplayMode().getBitsPerPixel())&&

       

        (current.getFrequency() == Display.getDesktopDisplayMode().getFrequency())){

       targetDisplayMode = current;

       

       break;

      }

     }

    }

   }else{

    targetDisplayMode = new DisplayMode(width,height);

   }

   if(targetDisplayMode == null){

    System.out.println(“Failed to find value mode”+width+”x”+height+”fs=”+fullscreen);

    return;

   }

   Display.setDisplayMode(targetDisplayMode);

   Display.setFullscreen(fullscreen);

  }catch(LWJGLException e){

   System.out.println(“Unable to setup mode”+width+”x”+height+”fullscreen=”+fullscreen + e);

  }

 }

 public static int getDelta(){

  long time = getTime();

  int delta =(int)(time – lastFrame);

  lastFrame = (int) time;

 

  return delta;

 }

 public static long getTime(){

  return Sys.getTime() * 1000/ Sys.getTimerResolution();

 }

 

 public static void updateFps(){

  if(getTime() – lastFps > 1000){

   Display.setTitle(“FPS:”+ fps);

   fps = 0;

   lastFps += 1000;

  }

  fps++;

 }

Well that’s it for now .Feel free to leave a comment cheers!.



Uncategorized

Lwjgl 3D Game Engine.

For some months now I have been learning opengl so that I can make my own 3D video games . So I decided to make my own game engine that I will use in making my games.
Note: The code used in this tutorial is far  from perfect also note that I assume you know basic java and eclipse (the IDE I’m using) . With that out of the way let’s  get started. 

 Create a new  project in eclipse call it whatever you like .  You can download the lwjgl library here Download the lwjgl 2  version  don’t go for lwjgl 3 since they are very different and I’m using lwjgl 2.xx so if you choose to get lwjgl 3 you are on your own.
Setting up lwjgl in eclipse .

  • Right click on your project folder and go to properties.
  • Right click on java Build Path and select the libraries tab.
  • To add lwjgl to your project click on either Add JARs…. or Add External JARs…. depending on where your lwjgl folder is on your computer .
  • Once in your lwjgl folder select lwjgl_utils ,lwjgl . 
  • Then click on lwjgl.jar and select native  library and navigate to the lwjgl files and select natives and choose your operating system .

        Now that the lwjgl is added to our project we can start making our game engine . 
        The Game Loop .

        I am going to be using a fixed step game loop for the game engine over the  variable step game loop .Each type of loop has its own pros and cons ,if you have time I recommend that you do your own research and decide which game loop is good for you . 

        Create a new package called gameLoop and create a GameEngine class. 

        package gameLoop;

        public class GameEngine implements Runnable {

        public static final int TARGET_FPS = 120;

        public static final int TARGET_EPS=30;

        private final Timekeeper keeper;

        private final Thread gameThread;

        public GameEngine(){

        gameThread = new Thread(this,””);

        keeper = new TimeKeeper();

        public void thread(){

        String osName = System.getProperty(“os.name”);

        If(osName.contains(“Mac”)){

        gameThread.run();

        }else{

        gameThread.start();}

        }

        @Override

        public void run(){

        try{

        create();

        gameLoop();

        }catch(Exception e ){

        e.printStackTrace();

        }}

        protected void gameloop(){

        float elapsedTime;

        float accumulator = 0f;

        float intervals = 1f/ TARGET_EPS ;

        boolean isRunning = true;

        while(isRunning && !Display.isCloseRequested()){

        elapsedTime = keeper.getElapsedTime();

        while(accumulator >= intervals){

        update(intervals);

        accumulator -= intervals;

        }

        float loop = 1f / TARGET_FPS;

        double time = keeper.getLastLoopTime() + loop ;

        while(keeper.getTime() < time){

        try{

        Thread.sleep(1);}catch(InterruptedException e){

        }

        }}

        Our gameEngine class implements Runnable so that we can have access to use the Thread (create a new Thread when run() is called) . Once you implement Runnable you will notice that you have to implement its method  run the next lines are self explanatory . In the thread method we check which operating system the engine is running .If we tried to run the engine while calling gameThread.start() on a mac an exception will occur , thats why we have to check which operating system our engine is being run on  . The rest of the code is the fixed time step we implement in our game engine.  

        Now we need to create our TimeKeeper class that  calculates the time difference since we last updated  .  

        package gameLoop;

        public class Timer {

        private double lastTick;

        public void init(){

        lastTick = getTime():

        }

        public double getTime(){

        return System.nanoTime()/1000000000.0;

        }

        public float  getElapsedTime(){

        double tick = getTime();

        float elapsedTime =(float)(tick-lastTick);

        lastTick = tick;

        return elapsedTime;

        }

        public double getLastTickTime(){return last Tick}}

          So thats our game loop done for now . next time we are going to make our display(just a black screen) using opengl . Feel free to comment cheers! 

        Opengl.

        LibGDX Game Tutorial Part 2

        Welcome to part 2 of the libgdx game tutorial . Today we are going to add code to our world class as well as the game renderer class and create our protagonist. 
        Let’s get started with the game world class .This class is responsible for updating all our entities in the game world.the finished game class.

        public class GameWorld {

         

         private GameState currentState;

         public int midPointY;

         

         private Cube cube;

         private FinalBar bar;

         private ScrollHandler scroller;

         private ScrollHandlerUpDown scroller2;

         private GameRenderer renderer;

         

            private int score=0;

            private int StarScore=0;

            private float runTime=0;

           

         public enum GameState{

          MENU,READY,RUNNING,GAMEOVER,HIGHSCORE,LEVEL2,LEVEL3

         }

         

         public GameWorld(int midPointY){

         

          currentState=GameState.MENU;

          this.midPointY=midPointY;

         

          setCube(new Cube(10,midPointY+88,60,60));

          scroller=new ScrollHandler(midPointY+66);

          scroller2=new ScrollHandlerUpDown(midPointY);

          setBar(new FinalBar(100,100,65,65,this));

         

                   Gdx.input.setInputProcessor(new InputHandler(new InputHandler.DirectionListener(){

           

            @Override

            public void onUp(){

             

             if(cube.isAlive){

             

              cube.moveUp();

           

                      }

         

              if(isGameOver()||isHighScore()){

               restart();

              }

                 if(isMenu()){

                        ready();

                       

              }else if(isReady()){

               start();

                       

              }

            }

           

            @Override

            public void onDown(){

             

             if(cube.isAlive){

             

              cube.moveDown();

           

                    }

             

              if(isGameOver()||isHighScore()){

               restart();

              }

             

              if(isMenu()){

               ready();

              }

              else if(isReady()){

               start();

              }

            }

            @Override

            public void onRight(){

             

             if(cube.isAlive){

             

              cube.moveRight();

             

              }

             

                       if(isGameOver()||isHighScore()){

                        restart();

                       }

                       

                       if(isMenu()){

               ready();

               

              }

                       else if(isReady()){

               start();

              }

            }

            @Override

            public void onLeft(){

             

             if(cube.isAlive){

             

              cube.moveLeft();

             

              }

                       if(isGameOver()||isHighScore()){

                        restart();

                       }

                       if(isMenu()){

               ready();

              }

                       else if(isReady()){

               start();

              }

            }

           }));

           

         }

         public void setRenderer(GameRenderer renderer) {

          this.renderer = renderer;

         }

         public void update(float delta){

         

           setRunTime(getRunTime() + delta);

           

          switch(currentState){

          case READY:

          case MENU:

           updateReady(delta);

           break;

           

          case RUNNING:

           updateRunning(delta);

           break;

           default:

            break;

           

         

          }

         

         }

         private void updateReady(float delta) {

          cube.updateReady(delta);

          scroller2.update(delta);

          scroller.update(delta);

         

         }

         private void updateRunning(float delta) {

         

          if(delta > .15f){

           delta = .15f;

          }

          cube.update(delta);

          bar.update();

          scroller.update(delta);

          scroller2.update(delta);

         

          if(scroller.collides(cube)||scroller.collides(cube) && cube.isAlive){

           scroller.stop();

           scroller2.stop();

           currentState=GameState.GAMEOVER;

           AssetLoader.dead.play();

           

           renderer.prepareTransition(255, 255, 255, .3f);

           

           if(score>AssetLoader.getHighScore()){

            AssetLoader.setHighScore(score);

            currentState=GameState.GAMEOVER;

           }

          }

          if(scroller2.collides(cube)||scroller.collides(cube) && cube.isAlive){

           scroller2.stop();

           scroller.stop();

           currentState=GameState.GAMEOVER;

           AssetLoader.dead.play();

           

           renderer.prepareTransition(255, 255, 255, .3f);

           

           if(score>AssetLoader.getHighScore()){

            AssetLoader.setHighScore(score);

            currentState=GameState.GAMEOVER;

           

           }

           

          }

          if(bar.collides(cube)){

           

            AssetLoader.coin.play();

           

            renderer.prepareTransition(255, 255, 255, .3f);

          }

         

          if(AssetLoader.getHighScore()>10){

         

          }

          else if(AssetLoader.getHighScore()>20){

         

          }

          else if(AssetLoader.getHighScore()>30){

           

          }

          if(AssetLoader.getStarScore()>5){

           

           

          }

         

         }

         public boolean isLevel2(){

          return currentState==GameState.LEVEL2;

         }

         public boolean isLevel3(){

          return currentState==GameState.LEVEL3;

         }

         public boolean isReady(){

          return currentState == GameState.READY;

         }

         public void level2() {

           currentState = GameState.LEVEL2;

           renderer.prepareTransition(355, 355, 355, .3f);

            }

         public void level3() {

           currentState = GameState.LEVEL3;

           renderer.prepareTransition(355, 355, 355, .3f);

         }

         

            public void start(){

             

             if(AssetLoader.getStarScore()>3){

             

           currentState=GameState.LEVEL2;

           level2();

           

          }else if(AssetLoader.getStarScore()>10){

           

           currentState=GameState.LEVEL3;

           level3();

          }

         if(AssetLoader.getHighScore()>20){

         

         

         }else if(AssetLoader.getHighScore()>40){

         

         

         }else{

          currentState = GameState.RUNNING;

         }

         }

            public void ready() {

          currentState = GameState.READY;

          renderer.prepareTransition(255, 255, 255, .3f);

         }

         public void restart(){

          score=0;

          setStarScore(0);

          scroller.onRestart();

          scroller2.onRestart();

          cube.onRestart(midPointY-5,10);

          bar.recur();

          ready();

         }

         public boolean isGameOver(){

         

          return currentState == GameState.GAMEOVER;

         

         }

         public boolean isHighScore(){

         

          return currentState==GameState.HIGHSCORE;

         }

         

         public int getScore(){

          return score;

         }

         public void addStarScore(int increment){

          setStarScore(getStarScore() + increment);

         }

         public void addScore(int increment){

          score += increment;

         }

         public Cube getCube() {

          return cube;

         }

         public void setCube(Cube cube) {

          this.cube = cube;

         }

         public ScrollHandler getScroller() {

          return scroller;

         }

         public void setScroller(ScrollHandler scroller) {

          this.scroller = scroller;

         }

         public ScrollHandlerUpDown getScroller2() {

          return scroller2;

         }

         public void setScroller2(ScrollHandlerUpDown scroller2) {

          this.scroller2 = scroller2;

         }

         public FinalBar getBar() {

          return bar;

         }

         public void setBar(FinalBar bar) {

          this.bar = bar;

         }

         public float getRunTime() {

          return runTime;

         }

         public void setRunTime(float runTime) {

          this.runTime = runTime;

         }

         public boolean isMenu(){

          return currentState==GameState.MENU;

         }

         public boolean isRunning() {

          return currentState == GameState.RUNNING;

         }

         

         

         public int getStarScore() {

          return StarScore;

         }

         public void setStarScore(int starScore) {

          StarScore = starScore;

         }

         

        Now let’s take care of our rendering.This class draws and redraws our images to the screen .the finished game renderer.

        public class GameRenderer {

               

         private GameWorld myWorld;

         private OrthographicCamera cam;

         private SpriteBatch batch;

         private ShapeRenderer shapeRender;

         private int midPointY;

         private int gameWidth;

         private Cube cube;

         private FinalBar bar;

         private Pipe pipe1,pipe2,pipe3;

         private PipeDown pipe6,pipe7;

         private ScrollHandler scroller;

         private ScrollHandlerUpDown scroller2;

         private Background bg;

         private TweenManager manager;

         private Value alpha = new Value();

         private Color transitionColor;

         public GameRenderer(GameWorld world,int gameWidth,int midPointY){

          setMyWorld(world);

          

          this.setGameWidth(gameWidth);

          this.setMidPointY(midPointY);

          

          cam=new OrthographicCamera();

          cam.setToOrtho(true,gameWidth,408);

          

          batch=new SpriteBatch();

          batch.setProjectionMatrix(cam.combined);

          

          shapeRender=new ShapeRenderer();

          shapeRender.setProjectionMatrix(cam.combined);

          

          initGameObjects();

          initAssets();

          

          transitionColor = new Color();

          prepareTransition(255, 255, 255, .5f);

         }
         private void initAssets() {
          

         }
         private void initGameObjects() {

          

                 cube= myWorld.getCube();

                 scroller=myWorld.getScroller();

              scroller2=myWorld.getScroller2();

              pipe1=scroller.getPipe1();

              pipe2=scroller.getPipe2();

              pipe3=scroller.getPipe3();

              pipe6=scroller2.getPipe6();

              pipe7=scroller2.getPipe7();

              bar=myWorld.getBar();

              

         }

            public void render(float delta,float runTime){

          

          Gdx.gl.glClearColor(1,1,1,0);

          Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

          

          if(myWorld.isRunning()){

          batch.begin();

          batch.draw(AssetLoader.bg,bg.getX(),bg.getY()-50,gameWidth,600);

          batch.draw(AssetLoader.egg,bar.getFinalBar().getX(),bar.getFinalBar().getY(),bar.getFinalBar().getWidth()+4,bar.getFinalBar().getHeight());

          

          batch.draw(AssetLoader.wood,pipe1.getBarUp().getX(),pipe1.getBarUp().getY(),pipe1.getBarUp().getWidth(),pipe1.getBarUp().getHeight());

          batch.draw(AssetLoader.wood,pipe2.getBarDown().getX(),pipe2.getBarDown().getY(),pipe2.getBarDown().getWidth(),pipe2.getBarDown().getHeight());

          batch.draw(AssetLoader.wood,pipe3.getBarSide().getX(),pipe3.getBarSide().getY(),pipe3.getBarSide().getWidth(),pipe1.getBarSide().getHeight());

          batch.draw(AssetLoader.wood,pipe6.getBarUp2().getX(),pipe6.getBarUp2().getY(),pipe6.getBarUp2().getWidth(),pipe6.getBarUp2().getHeight());

          batch.draw(AssetLoader.wood,pipe7.getBarDown2().getX(),pipe7.getBarDown2().getY(),pipe7.getBarDown2().getWidth(),pipe7.getBarDown2().getHeight());

          batch.end();
          

          if(bar.collides(cube)){

           batch.begin();

           batch.draw(AssetLoader.win,cube.getX(),cube.getY(),cube.getWidth(),cube.getHeight());

           batch.end();

          }else{

           batch.begin();

           batch.draw(AssetLoader.playerAnim.getKeyFrame(runTime),cube.getX(),cube.getY(),cube.getWidth(),cube.getHeight());

           batch.end();

          

          }

          

           //Score

          batch.begin();

          String score=myWorld.getScore()+””;

          AssetLoader.shadow.draw(batch,””+myWorld.getScore(),20-(3*score.length()),midPointY-180);

          AssetLoader.font.draw(batch,””+myWorld.getScore(),20-(3*score.length()-1),midPointY-179);

          batch.end();

          

          }else if(myWorld.isReady()){

           

               batch.begin();

               batch.draw(AssetLoader.bg,bg.getX(),bg.getY()-50,gameWidth,600);

               batch.draw(AssetLoader.egg,bar.getFinalBar().getX(),bar.getFinalBar().getY(),bar.getFinalBar().getWidth()+4,bar.getFinalBar().getHeight());

            

            batch.draw(AssetLoader.wood,pipe1.getBarUp().getX(),pipe1.getBarUp().getY(),pipe1.getBarUp().getWidth(),pipe1.getBarUp().getHeight());

            batch.draw(AssetLoader.wood,pipe2.getBarDown().getX(),pipe2.getBarDown().getY(),pipe2.getBarDown().getWidth(),pipe2.getBarDown().getHeight());

            batch.draw(AssetLoader.wood,pipe3.getBarSide().getX(),pipe3.getBarSide().getY(),pipe3.getBarSide().getWidth(),pipe1.getBarSide().getHeight());

            batch.draw(AssetLoader.wood,pipe6.getBarUp2().getX(),pipe6.getBarUp2().getY(),pipe6.getBarUp2().getWidth(),pipe6.getBarUp2().getHeight());


        batch.draw(AssetLoader.wood,pipe7.getBarDown2().getX(),pipe7.getBarDown2().getY(),pipe7.getBarDown2().getWidth(),pipe7.getBarDown2().getHeight());

           

               batch.draw(AssetLoader.ready,gameWidth/6,midPointY-150,200,100);

               

             

            batch.end();

           

          }else if(myWorld.isMenu()){

             

           

                   batch.begin();

                   batch.draw(AssetLoader.bg,bg.getX(),bg.getY()-50,gameWidth,600);

                batch.draw(AssetLoader.wood,pipe1.getBarUp().getX(),pipe1.getBarUp().getY(),pipe1.getBarUp().getWidth(),pipe1.getBarUp().getHeight());

             batch.draw(AssetLoader.wood,pipe2.getBarDown().getX(),pipe2.getBarDown().getY(),pipe2.getBarDown().getWidth(),pipe2.getBarDown().getHeight());

             batch.draw(AssetLoader.wood,pipe3.getBarSide().getX(),pipe3.getBarSide().getY(),pipe3.getBarSide().getWidth(),pipe1.getBarSide().getHeight());

             batch.draw(AssetLoader.wood,pipe6.getBarUp2().getX(),pipe6.getBarUp2().getY(),pipe6.getBarUp2().getWidth(),pipe6.getBarUp2().getHeight());

             batch.draw(AssetLoader.wood,pipe7.getBarDown2().getX(),pipe7.getBarDown2().getY(),pipe7.getBarDown2().getWidth(),pipe7.getBarDown2().getHeight());

                batch.draw(AssetLoader.playerAnim.getKeyFrame(runTime),gameWidth/2-25,midPointY,cube.getWidth(),cube.getHeight());

             batch.draw(AssetLoader.title2,gameWidth/6,midPointY-150,200,100);

             batch.draw(AssetLoader.swipe, gameWidth/3,midPointY+66,100,50);

             batch.end();

                 

            }

            else if(myWorld.isGameOver()){

           

         

              batch.begin();

              batch.draw(AssetLoader.bg,bg.getX(),bg.getY()-50,gameWidth,600);

           batch.draw(AssetLoader.wood,pipe1.getBarUp().getX(),pipe1.getBarUp().getY(),pipe1.getBarUp().getWidth(),pipe1.getBarUp().getHeight());

           batch.draw(AssetLoader.wood,pipe2.getBarDown().getX(),pipe2.getBarDown().getY(),pipe2.getBarDown().getWidth(),pipe2.getBarDown().getHeight());

           batch.draw(AssetLoader.wood,pipe3.getBarSide().getX(),pipe3.getBarSide().getY(),pipe3.getBarSide().getWidth(),pipe3.getBarSide().getHeight());

           batch.draw(AssetLoader.wood,pipe6.getBarUp2().getX(),pipe6.getBarUp2().getY(),pipe6.getBarUp2().getWidth(),pipe6.getBarUp2().getHeight());

           batch.draw(AssetLoader.wood,pipe7.getBarDown2().getX(),pipe7.getBarDown2().getY(),pipe7.getBarDown2().getWidth(),pipe7.getBarDown2().getHeight());

           

           batch.draw(AssetLoader.gameover,gameWidth/4,midPointY-180,150,75);

           

           @SuppressWarnings(“unused”)

           String score=myWorld.getScore()+””;

           AssetLoader.shadow.draw(batch,””+myWorld.getScore(),gameWidth/2-30,midPointY+1);

           AssetLoader.font.draw(batch,””+myWorld.getScore(),gameWidth/2-29,midPointY);

           batch.draw(AssetLoader.currentscore,gameWidth/3,midPointY-55,100,50);

           

           @SuppressWarnings(“unused”)

           int length2 = (“” + AssetLoader.getHighScore()).length();

           AssetLoader.shadow.draw(batch, “” + AssetLoader.getHighScore(),

             gameWidth/2-30, midPointY+120);

           

           AssetLoader.font.draw(batch, “” + AssetLoader.getHighScore(),

             gameWidth/2-29, midPointY+119);

                    batch.draw(AssetLoader.highscore,gameWidth/3,midPointY+55,100,50);


           batch.draw(AssetLoader.retry,gameWidth/3,midPointY-100,100,50);

           

           batch.end();

          }else

          if(myWorld.isLevel2()){

           

           batch.begin();

           

           batch.draw(AssetLoader.bg2,bg.getX(),bg.getY(),gameWidth,600);

           batch.draw(AssetLoader.egg,bar.getFinalBar().getX(),bar.getFinalBar().getY(),bar.getFinalBar().getWidth()+4,bar.getFinalBar().getHeight());

           

           batch.draw(AssetLoader.stone,pipe6.getBarUp2().getX(),pipe6.getBarUp2().getY(),pipe6.getBarUp2().getWidth(),pipe6.getBarUp2().getHeight());

           batch.draw(AssetLoader.stone,pipe7.getBarDown2().getX(),pipe7.getBarDown2().getY(),pipe7.getBarDown2().getWidth(),pipe7.getBarDown2().getHeight());

           

           batch.end();


           

           if(bar.collides(cube)){

            batch.begin();

            batch.draw(AssetLoader.win,cube.getX(),cube.getY(),cube.getWidth(),cube.getHeight());

            batch.end();

           }else{

            batch.begin();

            batch.draw(AssetLoader.playerAnim.getKeyFrame(runTime),cube.getX(),cube.getY(),cube.getWidth(),cube.getHeight());

            batch.end();

           

           }

           

            //Score

           batch.begin();

           String score=myWorld.getScore()+””;

           AssetLoader.shadow.draw(batch,””+myWorld.getScore(),20-(3*score.length()),midPointY-180);

           AssetLoader.font.draw(batch,””+myWorld.getScore(),20-(3*score.length()-1),midPointY-179);

           batch.end();

           

          }

           

          drawTransition(delta);

         

            }

            public void prepareTransition(int r, int g, int b, float duration) {

             

          transitionColor.set(r / 255.0f, g / 255.0f, b / 255.0f, 1);

          alpha.setValue(1);

          Tween.registerAccessor(Value.class, new ValueAccessor());

          manager = new TweenManager();

          Tween.to(alpha, -1, duration).target(0)

            .ease(TweenEquations.easeOutQuad).start(manager);

         }


         private void drawTransition(float delta) {

         

          if (alpha.getValue() > 0) {

           manager.update(delta);

           Gdx.gl.glEnable(GL20.GL_BLEND);

           Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);

           shapeRender.begin(ShapeType.Filled);

           shapeRender.setColor(transitionColor.r, transitionColor.g,

             transitionColor.b, alpha.getValue());

           shapeRender.rect(0, 0, 136, 300);

           shapeRender.end();

           Gdx.gl.glDisable(GL20.GL_BLEND);


          }

         }


         public int getGameWidth() {

          return gameWidth;

         }


         public void setGameWidth(int gameWidth) {

          this.gameWidth = gameWidth;

         }


         public int getMidPointY() {

          return midPointY;

         }


         public void setMidPointY(int midPointY) {

          this.midPointY = midPointY;

         }


         public GameWorld getMyWorld() {

          return myWorld;

         }


         public void setMyWorld(GameWorld myWorld) {

          this.myWorld = myWorld;

         }


         public OrthographicCamera getCam() {

          return cam;

         }

         public void setCam(OrthographicCamera cam) {this.can=can;

         

        The game renderer  needs  to get all the assets(Images and sound ) from the Assetloader class . The order in which  the images are drawn and updated is determined by the game states in the gameWorld class . So now we need to update our Assetloader . The finished class.

        public static Texture bg5,ice,stone,star,bg3,bg2,collect,gold,can,many,win,pack,egg,logo,title,swipe,title2,gameover,retry,ready,highscore,currentscore,b
        g; public static Sound dead,coin; public static BitmapFont font,shadow; public static Preferences prefs; public static TextureRegion pl1,pl2,pl3,pl4,wood; public static Animation playerAnim; public static void load(){ pack=new Texture(Gdx.files.internal(“pack.png”)); pack.setFilter(TextureFilter.Linear, TextureFilter.Linear); win=new Texture(Gdx.files.internal(“CUBED#.png”)); stone=new Texture(Gdx.files.internal(“stone.png”)); ice=new Texture(Gdx.files.internal(“ice.png”)); bg5=new Texture(Gdx.files.internal(“bg5.png”)); pl1=new TextureRegion(pack,1,1,195,125); pl1.flip(false, true); pl2=new TextureRegion(pack,198,1,195,125); pl2.flip(false, true); pl3=new TextureRegion(pack,393,1,195,125); pl3.flip(false, true); pl4=new TextureRegion(pack,588,1,195,125); pl4.flip(false, true); wood=new TextureRegion(pack,783,68,121,58); collect=new Texture(Gdx.files.internal(“collect.png”)); gold=new Texture(Gdx.files.internal(“gold.png”)); many=new Texture(Gdx.files.internal(“many.png”)); can=new Texture(Gdx.files.internal(“can.png”)); star=new Texture(Gdx.files.internal(“star.png”)); TextureRegion[]playerAni={pl1,pl2,pl3,pl3,pl2,pl1,pl1,pl2,pl3,pl3,pl2,pl1,pl1,pl2,pl3,pl3,pl2,pl1,pl1,pl2,pl3,pl4}; playerAnim=new Animation(0.01f,playerAni); playerAnim.setPlayMode(Animation.PlayMode.LOOP_PINGPONG); logo=new Texture(Gdx.files.internal(“logo.png”)); logo.setFilter(TextureFilter.Linear,TextureFilter.Linear); title=new Texture(Gdx.files.internal(“title.png”)); title.setFilter(TextureFilter.Linear,TextureFilter.Linear); swipe=new Texture(Gdx.files.internal(“swipe.png”)); swipe.setFilter(TextureFilter.Linear,TextureFilter.Linear); title2=new Texture(Gdx.files.internal(“title2.png”)); title2.setFilter(TextureFilter.Linear,TextureFilter.Linear); gameover=new Texture(Gdx.files.internal(“gameover.png”)); gameover.setFilter(TextureFilter.Linear,TextureFilter.Linear); retry=new Texture(Gdx.files.internal(“retry.png”)); retry.setFilter(TextureFilter.Linear,TextureFilter.Linear); ready=new Texture(Gdx.files.internal(“ready.png”)); ready.setFilter(TextureFilter.Linear,TextureFilter.Linear); highscore=new Texture(Gdx.files.internal(“highscore.png”)); highscore.setFilter(TextureFilter.Linear,TextureFilter.Linear); currentscore=new Texture(Gdx.files.internal(“currentScore.png”)); currentscore.setFilter(TextureFilter.Linear,TextureFilter.Linear); bg=new Texture(Gdx.files.internal(“bg.png”)); bg.setFilter(TextureFilter.Linear, TextureFilter.Linear); bg2=new Texture(Gdx.files.internal(“bg2.png”)); bg2.setFilter(TextureFilter.Linear,TextureFilter.Linear); bg3=new Texture(Gdx.files.internal(“bg4.png”)); egg=new Texture(Gdx.files.internal(“egg.png”)); egg.setFilter(TextureFilter.Linear, TextureFilter.Linear); dead=Gdx.audio.newSound(Gdx.files.internal(“dead.wav”)); coin=Gdx.audio.newSound(Gdx.files.internal(“coin.wav”)); font = new BitmapFont(Gdx.files.internal(“whitetext.fnt”)); font.getData().setScale(1.0f, -1.0f); shadow=new BitmapFont(Gdx.files.internal(“shadow.fnt”)); shadow.getData().setScale(1.0f,-1.0f); prefs=Gdx.app.getPreferences(“AnDi”); if(!prefs.contains(“highScore”)){ prefs.putInteger(“highScore”,0); } if(!prefs.contains(“highStar”)){ prefs.putInteger(“highScore”,0); } } public static void setHighScore(int val){ prefs.putInteger(“highScore”, val); prefs.flush(); } public static int getHighScore(){ return prefs.getInteger(“highScore”); } public static void setStarScore(int val){ prefs.putInteger(“highStar”, val); prefs.flush(); } public static int getStarScore(){ return prefs.getInteger(“highStar”); } public static void dispose(){ logo.dispose(); title.dispose(); swipe.dispose(); title2.dispose(); gameover.dispose(); retry.dispose(); ready.dispose(); currentscore.dispose(); highscore.dispose(); dead.dispose(); coin.dispose(); } }

        Now let’s add our red bird to its world . Create a new class Cubed. The finished class.

        public class Cube { private Vector2 position; private Vector2 velocity; private Vector2 acceleration; private int width; private int height; private Rectangle boundingRect,screenRect; public boolean isAlive; public Cube(float x,float y,int width,int height){ this.width=width; this.height=height; position=new Vector2(x,y); velocity=new Vector2(5,5); acceleration=new Vector2(0,0); boundingRect=new Rectangle(); screenRect=new Rectangle(0,0,Gdx.graphics.getWidth(),Gdx.graphics.getHeight()); isAlive=true; } public void update(float delta){ boundingRect.set(position.x,position.y,width,height); if(position.y < 0){ position.y+=1.5f; }else if(position.y+height>screenRect.height){ position.y-=1.5f; }else if(position.x<0){ position.x+=1.5f; }else if(position.x + width>screenRect.width){ position.x-=1.5f; } } public void updateReady(float delta){ if(position.y<0){ position.y+=velocity.y; } else if(position.y+height>screenRect.height){ position.y-=velocity.y; } } public void moveUp(){ position.y-=60; } public void moveDown(){ position.y +=70; } public void moveRight(){ position.x +=65; } public void moveLeft(){ position.x -=65; } public void die(){ isAlive=false; velocity.y=0; velocity.x=0; } public void onRestart(float y,float x){ position.y=y; position.x=x; velocity.x=0; velocity.y=0; acceleration.x=0; acceleration.y=0; isAlive=true; } public Vector2 getVelocity() { return velocity; } public void setVelocity(Vector2 velocity) { this.velocity = velocity; } public Vector2 getAcceleration() { return acceleration; } public void setAcceleration(Vector2 acceleration) { this.acceleration = acceleration; } public int getWidth() { return width; } public void setWidth(int width) { this.width = width; } public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } public Rectangle getBoundingRect() { return boundingRect; } public void setBoundingRect(Rectangle boundingRect) { this.boundingRect = boundingRect; } public float getX() { return position.x; } public float getY() { return position.y; }


        Thats it for our bird class . Now we need a way to control the bird . We want the bird to move in the direction the player swipes . Create a new class InputHandler . The finished class.

        import com.badlogic.gdx.input.GestureDetector; public class InputHandler extends GestureDetector{ public interface DirectionListener{ void onLeft(); void onRight(); void onDown(); void onUp(); } public InputHandler(DirectionListener directionListener){ super(new DirectionGestureListener(directionListener)); } static class DirectionGestureListener extends GestureAdapter{ DirectionListener directionListener; public DirectionGestureListener(DirectionListener directionListener){ this.directionListener=directionListener; } @Override public boolean fling(float velocityX,float velocityY,int button){ if(Math.abs(velocityX)>Math.abs(velocityY)){ if(velocityX>0){ directionListener.onRight(); }else{ directionListener.onLeft(); } }else{ if(velocityY>0){ directionListener.onDown(); }else{ directionListener.onUp(); } } return super.fling(velocityX,velocityY,button); } } public InputHandler(GestureListener listener) { super(listener); } }


        The bird needs to save its eggs . But our world does not have any eggs . so let’s make some . The eggs will be generated at randomly selected positions . If we tell java to randomly generate  a position for our eggs   it could easily  generate the position outside our world . So to avoid this we will create an emun which will store the possible positions where our eggs  can appear . We will then create a class that will randomly select from the enum we created . OK so let’s  implement this .  The finished random class. 

        p

        ublic enum FinalBarType { BAR_ROW(10,7.5f), BAR_LARGE2(88f,7.5f), BAR_ROW2(200,7.5f), BAR_COLUMN(88f,330), BAR_COLUMN2(10,330); protected Vector2 position; public Vector2 getPosition() { return position; } public void setPosition(Vector2 position) { this.position = position; } FinalBarType(float x, float y) { position = new Vector2(x, y); } }

        The finished random selector class . This class selects a position from our enum.

        import java.util.Random; import com.AnDi.GameActor.FinalBarType; public class RandomFinalBar { public static FinalBarType getRandomBarType(){ RandomEnumrandomEnum=new RandomEnum(FinalBarType.class); return randomEnum.random(); } @SuppressWarnings(“rawtypes”) private static class RandomEnum{ private static final Random RND=new Random(); private final E[]values; public RandomEnum(Classtoken){ values=token.getEnumConstants(); } public E random(){ return values[RND.nextInt(values.length)]; } } }

        Now we create a class that ties all this together . This class is similar to the cubed class as they do the same function (we create bounding box etc). The finished class 

        public class FinalBar { private Rectangle finalBar; private Vector2 position; public GameWorld gameWorld; private int width; private int height; private boolean isScored=false; public FinalBar(float x,float y,int width,int height,GameWorld gameWorld){ this.gameWorld=gameWorld; this.width=width; this.height=height; finalBar=new Rectangle(); position=new Vector2(x,y); } public void update(){ finalBar.set(position.x,position.y,width,height); } public void resetX(){ position.x=RandomFinalBar.getRandomBarType().getPosition().x; isScored=false; } public void resetY(){ position.y=RandomFinalBar.getRandomBarType().getPosition().y; isScored=false; } public void recur(){ if(RandomFinalBar.getRandomBarType().getPosition().x==position.x||RandomFinalBar.getRandomBarType().getPosition().x==position.x){ resetX(); } if(RandomFinalBar.getRandomBarType().getPosition().y==position.y||RandomFinalBar.getRandomBarType().getPosition().y==position.y){ resetY(); } } public boolean collides(Cube cube){ if(Intersector.overlaps(cube.getBoundingRect(),finalBar)){ resetX(); resetY(); if(!isScored()){ addScore(1); } } return false; } public void addScore(int increment){ gameWorld.addScore(increment); } public boolean isScored(){ return isScored; } public void setScored(boolean b){ isScored=b; } public Rectangle getFinalBar() { return finalBar; } public void setFinalBar(Rectangle finalBar) { this.finalBar = finalBar; } public Vector2 getPosition() { return position; } public void setPosition(Vector2 position) { this.position = position; } public int getWidth() { return width; } public void setWidth(int width) { this.width = width; } public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } }

        Now let’s  make our  moving blocks. The starting position for our moving blocks will  be generated  randomly like our eggs  but will move with a constant speed  from left to right and from bottom to top .Once out of the screen the blocks will be reset . the finished barType class. It will select our block starting position.

        import java.util.Random; import com.AnDi.GameActor.Bar2Type; public class RandomUtils2 { public static Bar2Type getRandomBarType(){ RandomEnumrandomEnum=new RandomEnum(Bar2Type.class); return randomEnum.random(); } @SuppressWarnings(“rawtypes”) private static class RandomEnum{ private static final Random RND=new Random(); private final E[]values; public RandomEnum(Classtoken){ values=token.getEnumConstants(); } public E random(){ return values[RND.nextInt(values.length)]; } } }

        The blocks enum class is identical to  the eggs enum class so you can use the same code but you will need to adjust the position(x coordinates and y coordinates )  .  You can create  more block enum classes in order to have more columns and rows of moving blocks . Now we need a class that will  update our blocks position . This class was borrowed from Kiloblot’s tutorial so if you dont understand how the code  works you can visit their tutorial.the finished scrollable and scrollableHandler classes.


        protected Vector2 position,position2,position3,position4,position5; protected Vector2 velocity; protected int width; protected int height; protected boolean isScrolledLeft; public Scrollable(float x, float y, int width, int height, float scrollSpeed) { position = new Vector2(RandomUtils.getRandomBarType().getPosition().x,RandomUtils.getRandomBarType().getPosition().y); position2=new Vector2(RandomUtils2.getRandomBarType().getPosition().x,RandomUtils2.getRandomBarType().getPosition().y); position3 = new Vector2(RandomUtils3.getRandomBarType().getPosition().x,RandomUtils3.getRandomBarType().getPosition().y); velocity = new Vector2(scrollSpeed, 0); this.width = width; this.height = height; isScrolledLeft = false; } public void update(float delta) { position.add(velocity.cpy().scl(delta)); position2.add(velocity.cpy().scl(delta)); position3.add(velocity.cpy().scl(delta)); if (position.x + width < 0) { position.x=RandomUtils.getRandomBarType().getPosition().x; position.y=RandomUtils.getRandomBarType().getPosition().y; }else if(position2.x + width < 0){ position2.x=RandomUtils2.getRandomBarType().getPosition().x; position2.y=RandomUtils2.getRandomBarType().getPosition().y; }else if(position3.x + width <0){ position3.x=RandomUtils3.getRandomBarType().getPosition().x; position3.y=RandomUtils3.getRandomBarType().getPosition().y; } } public void reset(float newX) { position.x = RandomUtils.getRandomBarType().getPosition().x; position2.x = RandomUtils2.getRandomBarType().getPosition().x; position3.x=RandomUtils3.getRandomBarType().getPosition().x; } public void stop(){ velocity.x=0; } public boolean isScrolledLeft() { return isScrolledLeft; } public float getTailX() { return position.x + width; } public float getX() { return position.x; } public float getY() { return position.y; } public int getWidth() { return width; } public int getHeight() { return height; } public Vector2 getPosition2() { return position2; } public void setPosition2(Vector2 position2) { this.position2 = position2; } public Vector2 getPosition() { return position; } public void setPosition(Vector2 position) { this.position = position; } public Vector2 getPosition3() { return position3; } public void setPosition3(Vector2 position3) { this.position3 = position3; } public Vector2 getPosition4() { return position4; } public void setPosition4(Vector2 position4) { this.position4 = position4; } public Vector2 getPosition5() { return position5; } public void setPosition5(Vector2 position5) { this.position5 = position5; }

        The scroll handler class.

        public class ScrollHandler { private Pipe pipe1,pipe2,pipe3; public static final int SCROLL_SPEED=-130; public static final float PIPE_GAP=2.5f; public ScrollHandler(int midPointY){ pipe1 = new Pipe(RandomUtils.getRandomBarType().getPosition().x,RandomUtils.getRandomBarType().getPosition().y,65,65, SCROLL_SPEED); pipe2 = new Pipe(RandomUtils2.getRandomBarType().getPosition().x,RandomUtils2.getRandomBarType().getPosition().y,65,65, SCROLL_SPEED ); pipe3 = new Pipe(RandomUtils3.getRandomBarType().getPosition().x,RandomUtils3.getRandomBarType().getPosition().y,65,65, SCROLL_SPEED ); } public void update(float delta){ pipe1.update(delta); pipe2.update(delta); pipe3.update(delta); if(pipe1.isScrolledLeft()){ pipe1.reset(RandomUtils.getRandomBarType().getPosition().x); }else if(pipe2.isScrolledLeft()){ pipe2.reset(RandomUtils2.getRandomBarType().getPosition().x); }else if(pipe3.isScrolledLeft()){ pipe3.reset(RandomUtils3.getRandomBarType().getPosition().x); } } public void stop(){ pipe1.stop(); pipe2.stop(); pipe3.stop(); } public boolean collides(Cube cube){ return(Intersector.overlaps(cube.getBoundingRect(),pipe1.getBarUp()) || Intersector.overlaps(cube.getBoundingRect(),pipe2.getBarDown()) || Intersector.overlaps(cube.getBoundingRect(),pipe3.getBarSide()) ); } public void onRestart(){ pipe1.onRestart(210,SCROLL_SPEED); pipe2.onRestart(pipe1.getTailX()+5f,SCROLL_SPEED); pipe3.onRestart(pipe2.getTailX()+5f,SCROLL_SPEED); } public static float getPipeGap() { return PIPE_GAP; } public Pipe getPipe1() { return pipe1; } public void setPipe1(Pipe pipe1) { this.pipe1 = pipe1; } public Pipe getPipe2() { return pipe2; } public void setPipe2(Pipe pipe2) { this.pipe2 = pipe2; } public Pipe getPipe3() { return pipe3; } public void setPipe3(Pipe pipe3) { this.pipe3 = pipe3; }

        Finally we make the place holder class for our blocks just like the cubed and finalbar class .

        import com.AnDi.Common.RandomUtils; import com.AnDi.Common.RandomUtils2; import com.AnDi.Common.RandomUtils3; import com.badlogic.gdx.math.Intersector; import com.badlogic.gdx.math.Rectangle; public class Pipe extends Scrollable{ private Rectangle barUp,barDown,barSide; public Rectangle getBarUp() { return barUp; } public void setBarUp(Rectangle barUp) { this.barUp = barUp; } public Pipe(float x, float y, int width, int height, float scrollSpeed) { super(x, y, width, height, scrollSpeed); barUp=new Rectangle(); barDown=new Rectangle(); barSide=new Rectangle(); } @Override public void reset(float newX) { super.reset(newX); position.x=RandomUtils.getRandomBarType().getPosition().x; position2.x=RandomUtils2.getRandomBarType().getPosition().x; position.y=RandomUtils.getRandomBarType().getPosition().y; position2.y=RandomUtils2.getRandomBarType().getPosition().y; position3.x=RandomUtils3.getRandomBarType().getPosition().x; position3.y=RandomUtils3.getRandomBarType().getPosition().y; } public Rectangle getBarDown() { return barDown; } public void setBarDown(Rectangle barDown) { this.barDown = barDown; } public Rectangle getBarSide(){ return barSide; } public void setBarSide(Rectangle barSide){ this.barSide=barSide; } @Override public void update(float delta){ super.update(delta); barUp.set(position.x,position.y,width,height); barDown.set(position2.x,position2.y,width,height); barSide.set(position3.x,position3.y,width,height); } public boolean collides(Cube cube){ if(Intersector.overlaps(cube.getBoundingRect(),barUp) ||Intersector.overlaps(cube.getBoundingRect(),barDown) ||Intersector.overlaps(cube.getBoundingRect(),barSide)){ } return false; } public void onRestart(float x,float scrollSpeed){ velocity.x=scrollSpeed; reset(x); } }

        The final class  we need to create in our project is the menu class .

        public class MenuScreen implements Screen{ private TweenManager manager; private SpriteBatch batcher; private Sprite sprite; private CDGame game; public MenuScreen(CDGame game) { this.game = game; } @Override public void show() { sprite = new Sprite(AssetLoader.title); sprite.setColor(1, 1, 1, 0); float width = Gdx.graphics.getWidth(); float height = Gdx.graphics.getHeight(); float desiredWidth = width * .7f; float scale = desiredWidth / sprite.getWidth(); sprite.setSize(sprite.getWidth() * scale, sprite.getHeight() * scale); sprite.setPosition((width / 2) – (sprite.getWidth() / 2), (height / 2) – (sprite.getHeight() / 2)); setupTween(); batcher = new SpriteBatch(); } private void setupTween() { Tween.registerAccessor(Sprite.class, new SpriteAccessor()); manager = new TweenManager(); TweenCallback cb = new TweenCallback() { @Override public void onEvent(int type, BaseTween source) { game.setScreen(new GameScreen()); } }; Tween.to(sprite, SpriteAccessor.ALPHA, .8f).target(1) .ease(TweenEquations.easeInOutQuad).repeatYoyo(1, .4f) .setCallback(cb).setCallbackTriggers(TweenCallback.COMPLETE) .start(manager); } @Override public void render(float delta) { manager.update(delta); Gdx.gl.glClearColor(1, 1, 1, 1); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); batcher.begin(); sprite.draw(batcher); batcher.end(); } @Override public void resize(int width, int height) { } @Override public void hide() { // TODO Auto-generated method stub } @Override public void pause() { // TODO Auto-generated method stub } @Override public void resume() { // TODO Auto-generated method stub } @Override public void dispose() { // TODO Auto-generated method stub } }

        Well that does it for the libgdx game   tutorial . you can now run the game with no errors . 

        ​​​

        If you have any questions or comments, feel free to let me know in the comments section.You can get the finished code on github .