Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon
8. September 2014

 

The following is a guest tutorial by Avetis showing how to use LibGDX and Overlap2D to create an Angry Birds like game.  Overlap2D is a level and UI editor handy for separating game coding from content creation.  Keep in mind, Overlap2D is fairly young, currently at 0.0.4 version. Now, on with the tutorial!

 



Making Flappy Bird with Overlap2D – Overlappy Tutorial

 

 

Agenda


In this tutorial we are going to create a FlappyBird clone game (for learning purposes only) using Java, LibGDX framework and accelerate it all by moving our UI, Level, and Asset management into Overlap2D Editor. One thing I figured while coding is that you can’t make a quick tutorial about a flappy bird clone, ever. It’s going to be long if we want details. It is easier though to use the explain approach instead of step by step guide.  So I am going to share all the sources and resources, and then go with you through setting this all up, show how things work, and hopefully this all will make sense.

 

Prerequisites


Java knowledge, basic LibGDX experience, computer, time. Make sure you use latest Overlap2D editor and runtimes (v 0.0.4 or higher)

Get latest LibGDX project setup here: http://bitly.com/1i3C7i3 ( Details here )
Get latest Overlap2D editor here: http://overlap2d.com

 

First - Get Game Assets (Resources)


First let’s download the assets. I made a small pack of images I found on the internet with Flappy Bird images, animations and font. You can get it here: http://overlap2d.com/?p=236

 

 

Setting up Your Overlap2D Project

 

Unzip your Overlap2D zip file, and run the Overlap2D.jar.


First things first, you are currently viewing demo project, so go to File and Create New Project. Call it OverlappyBird and then create the scene size, let it be 480 width, 800 in height. It’s a standard small mobile device resolution, and since Flappy Bird is a portrait game, it should be just right. Click Create Project.
You have now created an empty project and it’s ready for setup, now you need to import the assets. Here we have 3 types of assets, first is just image textures, and second is a sprite animation for bird itself, and lastly the TTF font for score label. I have separated them in folders so you can import easily. Click on File, import to library.


First click on “…” button near the import images text field to select your images; locate them, select all. When done click on import and they all will get imported to your assets area on the right middle panel. Then open same the dialog again, and this time find Import Sprite Animations (note: not spine, but sprite) Click on “…” button there and locate bird.atlas file. Click Import, and it will get added to your assets list as well.


Lastly open import dialog again, and import font, by locating ttf file.


Your project setup is ready.

 

Making The Main Scene

 

First let’s see how main scene looks in Overlap2D when it is finished:

 

image


 
I decided to make several layers to have things organized, bg layer for background image that is not moving, default layer for pipes and bird itself, ground layer for moving the ground that is covering pipes, ui layer for “get ready” popups and score labels, and finally dlg layer for end game dialog. The reason I am not putting dialog inside ui layer is that I can position it in its layer correctly, and later hide that layer so it will not intervene with my work.  So, go ahead and create this layers in the order I described from bottom to top. (bg layer goes below them all, and you can rearrange them by drag-and-dropping)


I also recommend you to open my example project (provided with resources). Open it with Overlap2D and see how things are positioned and grouped. (To open a project, click file, open, and then locate .pit file inside project.)


Compose your own project like I did,. Put background on bg layer, and add bird on default layer. Make sure it looks like the picture above.


The ground is going to be a moving part, so we need to have 2 of this near each other for seamless movement. Put two grounds near each other and then group them into composites, like on this picture, do not forget to give identifier to it for later use.


image

 

For the pipes we are going to do the following trick. First of all we are going to put pipes on top of each other with a gap, and convert them into composite, and then add to library to have kind of a prefab for a pipe column. Later in code we are going to pre-load 3 of this because there is never more than 3 columns of pipes visible on screen, so we can re-use the ones that are left of the screen for next pipe iteration.


image


Now some of the pipes are going to vary in position on Y axis. So there are a minimum and maximum values that it should not be below or above. To avoid having this values in code, I just put 2 of pipe columns on screen: one at the lowest point and the other at the highest, and give them identifiers in order to read those values from code later.

 

image

 

Next click on bird in properties box and add 2 custom variables, by clicking on custom variables button. First is jump_speed=400, and second is gravity=1000 (so you can later tweak game from editor not from code)


image

 

Next up, put a “hint” and “get ready” assets convert them into composite as they always go together and give them id to hide show from game. They should go to ui layer.

 

Making Menu Scene

 

This one is easier: click on File, Scenes, Create New Scene, and choose MenuScene as name.


Make sure to put up all things just like on this picture. And note that you should make a composite for ground agai n (as we do not yet share prefabs between the scenes).


Put a Play button as image and give it an id to add listeners later in your code.


Here is how it should look:

 

image

 

Overlap2D Part DONE!


Looks pretty good! Both scenes are set up and ready for some coding. Most importantly your scene and UI are very flexible and code-independent.

 

 

 

Setting up LibGDX Project and Getting Ready to Code:

 

Download the LibGDX setup application and setup an empty project (make sure to have checked box2d and freetype fonts), import it to your eclipse or other IDE, run the desktop app to make sure it works, then strip it from LibGDX picture  and make it just a black screen.


Make sure your desktop launcher has code to specify screen size of 480x800 (config variables in launcher).


We are going to render everything using a simple LibGDX Stage, so the code structure will be the following: GameStage extending Stage that will load all the Overlap2D data and display it; Main class that will be rendering GameStage in its render method.


For all the rest we are going to use iScript functionality of Overlap2D. Let me go a bit in depth for that. Overlap2D runtime provides an interface that you can implement to create a “brain” of any composite item. Basically it is your way of attaching logic to an object. In this example we are going to create 3 iScripts, one is going to get attached to entire mainScreen and be a GameScreenScript with all game logic, other will be MenuScreenScript for menu, and the last one will be BirdScript that we will attach to the bird. It is important to mention that you cannot attach script to an image, or sprite animation, so I have converted bird animation to composite item in order to do it (right click, convert into composite).

 

You can find the full project on my github:  https://github.com/azakhary/OverlappyBird

Here are the well commented sources:

 

OverlappyBird.java

package com.underwater.demo.overflappy;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;

/*
 * This is our ApplicationListener the main thing that things start in libGDX
 */
public class OverflappyBird extends ApplicationAdapter {
   
   /*
    * GameStage will be holding both menu and main game
    */
   private GameStage stage;
   
   @Override
   public void create () {
      stage = new GameStage();
   }

   @Override
   public void render () {
      // Clearing the screen before each render
      Gdx.gl.glClearColor(0, 0, 0, 1);
      Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
      
      // calling stage act method and passing delta time passed since last call
      stage.act(Gdx.graphics.getDeltaTime());
      // drawing all actors
      stage.draw();
      
   }
}

GameStage.java

package com.underwater.demo.overflappy;

import java.io.File;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.uwsoft.editor.renderer.DefaultAssetManager;
import com.uwsoft.editor.renderer.SceneLoader;

/*
 * GameStage 
 */
public class GameStage extends Stage {
   
   // Speed of pixels per second of how fast things move left (required both for 
                                                               menu and the game,
                                                               thus put here)
   public float gameSpeed = 200;

   // Overlap2D  provides this easy asset manager that loads things as they are 
   provided by default when exporting from overlap
   private DefaultAssetManager assetManager;
   
   public GameStage() {
      super();
      
      // Set this is input processor so all actors would be able to listen to 
      touch events
      Gdx.input.setInputProcessor(this);
      
      // Initializing asset manager
      assetManager = new DefaultAssetManager();
      
      // providing the list of sprite animations which is one in this case, to 
      avoid directory listing coding
      assetManager.spriteAnimationNames = new String[1]; assetManager.
                                          spriteAnimationNames[0] = "bird";
      
      // loading assets into memory
      assetManager.loadData();
      
      // Menu goes first
      initMenu();
   }
   
   public void initMenu() {
      clear();
      
      // Creating Scene loader which can load an Overlap2D scene
      SceneLoader menuLoader = new SceneLoader(assetManager);
      
      // loading MenuScene.dt from assets folder
      menuLoader.loadScene(Gdx.files.internal("scenes" + File.separator + 
                           "MenuScene.dt"));
      
      // Initializing iScript MenuSceneScript that will be holding all menu 
      logic, and passing this stage for later use
      MenuScreenScript menuScript = new MenuScreenScript(this);
      
      // adding this script to the root scene of menu which is hold in 
      menuLoader.sceneActor
      menuLoader.sceneActor.addScript(menuScript);
      
      // Adding root actor to stage
      addActor(menuLoader.sceneActor);
      
      
   }
   
   public void initGame() {
      clear();
      
      // Creating Scene loader which can load an Overlap2D scene
      SceneLoader mainLoader = new SceneLoader(assetManager);
      
      // loading MainScene.dt from assets folder
      mainLoader.loadScene(Gdx.files.internal("scenes" + File.separator + 
                           "MainScene.dt"));
      
      // Initializing iScript GameSceneScript that will be holding all game, and 
      passing this stage for later use
      GameScreenScript gameScript = new GameScreenScript(this, mainLoader);
      
      // adding this script to the root scene of game which is hold in 
      mainLoader.sceneActor
      mainLoader.sceneActor.addScript(gameScript);
      
      // Adding root actor to stage
      addActor(mainLoader.sceneActor);
   }

}

GameScreenScript.java

package com.underwater.demo.overflappy;

import java.util.ArrayList;

import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.Touchable;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
import com.badlogic.gdx.scenes.scene2d.actions.AddAction;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.uwsoft.editor.renderer.SceneLoader;
import com.uwsoft.editor.renderer.actor.CompositeItem;
import com.uwsoft.editor.renderer.actor.LabelItem;
import com.uwsoft.editor.renderer.script.IScript;

/*
 * iScript for entire game logic
 */
public class GameScreenScript implements IScript {
   
   /*
    * reference to GameStage
    */
   private GameStage stage;
   
   /*
    * Main actor that holds root of game screen
    */
   private CompositeItem game;
   
   // Screen loader reference to be later used to retrieve prefabs from library
   private SceneLoader loader;
   
   // Game over Dialog actor
   private CompositeItem gameOverDlg;
   
   /*
    * this will be holding 2-ground system composite item 
    */
   private CompositeItem groundRotator;
   
   /*
    * Instead of holding bird actor we are going to hold birdscript that will 
    provide all bird logic and methods.
    * Also it will have bird actor inside
    */
   private BirdScript bird;
   
   // Hint Box actor the one that shown in begining of game
   private CompositeItem hintBox;
   
   // some helping booleans
   private boolean gameStarted = false;
   private boolean groundStop = false;
   
   // going to hold what is the possible low and high position for a pipe column
   private float minPipe;
   private float maxPipe;
   
   private int gameScore = 0;
   private LabelItem scoreLbl;
   
   // Going to hold 3 pipes here to reuse as pipe pool
   private ArrayList<CompositeItem> pipes = new ArrayList<CompositeItem>();
   
   public GameScreenScript(GameStage stage, SceneLoader loader) {
      this.stage = stage;
      this.loader = loader;
   }
   
   @Override
   public void init(CompositeItem gameItem) {
      game = gameItem;
      
      gameScore = 0;
      
      // Creating and holding BirdScript that will hold entire bird logic.
      bird = new BirdScript(stage);
      game.getCompositeById("bird").addScript(bird);
      
      groundRotator = game.getCompositeById("groundRotator");
      hintBox = game.getCompositeById("hintBox");
      scoreLbl = game.getLabelById("scoreLbl");
      
      // Adding listeners to listen for taps to make bird jump
      game.addListener(new ClickListener() {
         public boolean touchDown (InputEvent event, float x, float y, int 
                                   pointer, int button) {
            return true;
         }
         public void touchUp (InputEvent event, float x, float y, int pointer, 
                              int button) {
            // screen tap was done
            screenTap();
         }
      });
      
      // Loading min/max positions from level editor
      minPipe = game.getCompositeById("minPipe").getY();
      maxPipe = game.getCompositeById("maxPipe").getY();

      // Retrieving 3 pipe columns from library putting them into array,
      // and adding on screen in minus coordinates so the will becom "availible"
      for(int i = 0;  i < 3; i++) {
         CompositeItem pipe = loader.getLibraryAsActor("pipeGroup");             
         pipe.setX(-pipe.getWidth());        
         game.addItem(pipe);
         
         pipes.add(pipe);
      }
      
      
      // Making sure first pipe will be added not sooner then 3 seconds from now
      game.addAction(Actions.sequence(Actions.delay(3.0f), Actions.run(new 
                     Runnable() {
         
         @Override
         public void run() {
            putPipe();
         }
      })));
      
      // hiding game over dialog
      gameOverDlg = game.getCompositeById("gameOverDlg");
      // it should not listen for taps
      gameOverDlg.setTouchable(Touchable.disabled);
      gameOverDlg.setVisible(false);
   }

   @Override
   public void act(float delta) {
      
      // if game is not yet started or started (but most importantly not ended, 
                                                ground is moving) 
      if(!groundStop) {
         groundRotator.setX(groundRotator.getX() - delta * stage.gameSpeed);     
         if(groundRotator.getX() < -groundRotator.getWidth()/2) groundRotator.
            setX(0);
      }
      
      // if game is started, so first tap fone, then we dhould check for 
      collisions and move pipes
      if(gameStarted) {
         for(int i = 0; i < pipes.size(); i++) {
            // get pipe
            CompositeItem pipe = pipes.get(i);
            
            // move it if it has positive coordinate
            if(pipe.getX() > -pipe.getWidth()) {
               // if pipe was right of thebird, and will now become left of the 
               bird, add to score
               if(pipe.getX() >= bird.getBirdCenter().x && pipe.getX() - delta * 
                  stage.gameSpeed < bird.getBirdCenter().x) {
                  gameScore++;
               }
               pipe.setX(pipe.getX() - delta * stage.gameSpeed);
            }
            
            //check for collision with bird
            collisionCheck();
         }
      }
      
      // update scorel label
      scoreLbl.setText(gameScore+"");
   }
   
   /*
    * Check for bird versus pipe row collision
    */
   private void collisionCheck() {
      // iterate through all 3 pipes
      for(int i = 0; i < pipes.size(); i++) {
         CompositeItem pipe = pipes.get(i);
         
         // to make it easy going to think about bird as circle with 5 radius 
         Vector2 birdPoint = bird.getBirdCenter();
         
         // Is there collision? if yes stop the game and allow bird to fall
         if(birdPoint.x+5 > pipe.getX() && birdPoint.x - 5 < pipe.getX() + pipe.
            getWidth() && (pipe.getY() + 532 > birdPoint.y - 5 || pipe.getY()+
            701 < birdPoint.y + 5)) {
            stopGame(); 
         }
         
         // Did bird hit the ground? not only stop the game but also 
         // disable gravity to keep from further falling, and consider bird dead 
         ( animations stop )
         if(birdPoint.y-5 < groundRotator.getY()+groundRotator.getHeight()) {
            if(!groundStop) {
               stopGame();
            }
            bird.disableGravity();
            bird.getBird().setY(groundRotator.getY()+groundRotator.getHeight()+5)
                         ;
            // killitwithfire
            bird.die();
         }
      }
   }
   
   /*
    * Stops the game
    */
   private void stopGame() {
      gameStarted = false;
      groundStop = true;
      game.clearActions();
      
      // show end game dialog
      showEndDialog();
   }
   
   /*
    * showing end game dialog
    */
   public void showEndDialog() {
      // enabling touch back, showing
      gameOverDlg.setTouchable(Touchable.enabled);
      gameOverDlg.setVisible(true);
      // setting transparency to full
      gameOverDlg.getColor().a = 0;
      // and fading it in
      gameOverDlg.addAction(Actions.fadeIn(0.4f));
      
      // setting play button listener to replay the game
      gameOverDlg.getImageById("playBtn").addListener(new ClickListener() {
         public boolean touchDown (InputEvent event, float x, float y, int 
                                   pointer, int button) {
            return true;
         }
         public void touchUp (InputEvent event, float x, float y, int pointer, 
                              int button) {
            stage.initGame();
         }
      });
   }
   
   /*
    * Called when screen is tapped
    */
   private void screenTap() {
      // if ground is not moving then bird is dead no actin required on tapp
      if(groundStop) return;
      
      // if game started just jump the bird
      if(gameStarted) {
         bird.jump();
      } else {
         // if game is not yet started, start the game and jump the bird
         gameStarted = true;
         hintBox.addAction(Actions.fadeOut(0.3f));
         // and also enable gravity from now on
         bird.enableGravity();
         bird.jump();
      }
   }
   
   /*
    * get's availible pipe
    * availible pipe is any pipe that is left of screen and not visible
    */
   public CompositeItem getAvailablePipe() {
      for(int i = 0; i < pipes.size(); i++) {
         if(pipes.get(i).getX() <= -pipes.get(i).getWidth()) {
            return pipes.get(i);
         }
      }
      
      return null;
   }
   
   /*
    * this is called every X time to put a new pipe on the right
    */
   public void putPipe() { 
      // getting availible pipe
      CompositeItem pipe = getAvailablePipe();
      
      // when you die at bad moment, it can be null sometimes
      if(pipe == null) return;
      
      // put pipe column on the random hight from min to max range
      pipe.setX(stage.getWidth());
      pipe.setY(MathUtils.random(minPipe, maxPipe));
      
      // schedule next pipe to be put in 1.3 seconds
      game.addAction(Actions.sequence(Actions.delay(1.3f), Actions.run(new 
                     Runnable() {
         
         @Override
         public void run() {
            // call itself
            putPipe();
         }
      })));
   }

}

 

MenuScreenScript.java

 

package com.underwater.demo.overflappy;

import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.uwsoft.editor.renderer.actor.CompositeItem;
import com.uwsoft.editor.renderer.actor.ImageItem;
import com.uwsoft.editor.renderer.actor.SpriteAnimation;
import com.uwsoft.editor.renderer.script.IScript;

/*
 * iScript for menu logic
 */
public class MenuScreenScript implements IScript {
   
   /*
    * reference to GameStage
    */
   private GameStage stage;
   
   /*
    * this is the main root menu actor to work with
    */
   private CompositeItem menu;
   
   /*
    * this will be holding 2-ground system composite item 
    */
   private CompositeItem groundRotator;
   
   /*
    * this will be the bird sprite animation displayed in center of screen
    */
   private SpriteAnimation bird;
   
   // this variables are used to wiggle bird up and down with sin function
   private float iterator = 0;
   private float birdInitialPos;
   
   public MenuScreenScript(GameStage stage) {
      this.stage = stage;
   }

   public void init(CompositeItem menuItem) {
      menu = menuItem;
      
      // Finding playButton by id and storing in variable
      ImageItem playBtn = menuItem.getImageById("playBtn");
      
      // Finding ground composite and storing in variable 
      groundRotator = menuItem.getCompositeById("groundRotator");
      
      // Finding bird and storing in variable
      bird = menuItem.getSpriteAnimationById("bird");
      
      // let's remember where bird was initially
      birdInitialPos = bird.getY();
      
      // Adding a Click listener to playButton so we can start game when clicked
      playBtn.addListener(new ClickListener() {
         // Need to keep touch down in order for touch up to work normal (libGDX 
                                                                          awkward
                                                                          ness)
         public boolean touchDown (InputEvent event, float x, float y, int 
                                   pointer, int button) {
            return true;
         }
         public void touchUp (InputEvent event, float x, float y, int pointer, 
                              int button) {
            // when finger is up, ask stage to load the game
            stage.initGame();
         }
      });
   }
   
   /*
    * This is called every frame
    */
   public void act(float delta) {
      // moving ground left with game speed multiplied by delta as delta shows 
      what part of second was passed since last call
      groundRotator.setX(groundRotator.getX() - delta * stage.gameSpeed);     
      
      // if ground rotator got half way left, we can just put it back to 0, and 
      to eye it will look like it endlessly moves
      if(groundRotator.getX() < -groundRotator.getWidth()/2) groundRotator.setX(
         0);
      
      // Now this part is to wiggle bird up and down, we are going change 
      iterator based on time passed
      iterator += delta*400;
      
      // Then figure out the bird offset from it's original position based on 
      iterator which is based on time passed, and do it with sinus function
      float birdOffset = MathUtils.sinDeg(iterator)*5;
      
      // put bird on it's original pos + offset
      bird.setY(birdInitialPos + birdOffset); 
   }
   
}

 

BirdScript.java

 

package com.underwater.demo.overflappy;

import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;
import com.uwsoft.editor.renderer.actor.CompositeItem;
import com.uwsoft.editor.renderer.actor.SpriteAnimation;
import com.uwsoft.editor.renderer.script.IScript;

/**
 * Bird Script
 * @author azakhary
 * This is brain of the bird, it's physics and everything
 */
public class BirdScript implements IScript {

   /*
    * reference to GameStage
    */
   private GameStage stage;
   
   // Bird composite item actor
   private CompositeItem bird;
   
   // Inside bird composite actor there is the bird sprite animation actor
   private SpriteAnimation birdAnimation;
   
   // used to wiggle the bird in the air using Sine function
   private float iterator = 0;
   
   // current vertical velocity of the bird
   private float currVerticalVelocity = 0;
   
   // boolean to know if gravity is enabled or not
   private boolean isGravityEnabled = false;
   
   // to avoid jumping to rotation bird will try to always rotate a bit towards 
   desired rotation
   private float desiredRotation;
   
   // is it alive?
   private boolean isAlive = true;
   
   
   public BirdScript(GameStage stage) {
      this.stage = stage;
   }
   
   @Override
   public void init(CompositeItem item) {
      bird = item;
      
      // find animation from the composite
      birdAnimation = bird.getSpriteAnimationById("birdAnimation");
      
      // set origin of the bird in it's center, so it will rotate normally
      bird.setOrigin(bird.getWidth()/2, bird.getHeight()/2);
      
      // set desired rotation to current rotation which is 0
      desiredRotation = bird.getRotation();
   }

   @Override
   public void act(float delta) {
      
      if(!isGravityEnabled && isAlive) {
         // Wiggling when no gravity only
         iterator += delta*400;
         float birdOffset = MathUtils.sinDeg(iterator)*5;
         birdAnimation.setY(birdOffset);
      }
      
      // aplying gravity every frame
      gravity(delta);
      
      // moving to new position based on current vertical velocity
      bird.setY(bird.getY() + delta*currVerticalVelocity);
      
      // manage bird rotation based on it's vertical speed
      manageRotation(delta);
      
   }
   
   /*
    * manage bird rotation based on it's vertical speed
    * this is a part of code that is not interesting boring and whatever..
    */
   private void manageRotation(float delta) {
      if(isGravityEnabled) {
         if(currVerticalVelocity > -200) {
            float rotation = currVerticalVelocity+200;
            desiredRotation = rotation/15f;
         }
         if(currVerticalVelocity <= -200) {
            float rotation = currVerticalVelocity+200;
            if(rotation < -400) rotation = -400;
            desiredRotation = rotation/4.4f;
         }
         
         if(desiredRotation != bird.getRotation()) {
            if(desiredRotation > bird.getRotation()) {
               bird.setRotation(bird.getRotation() + 900*delta);
               if(desiredRotation < bird.getRotation()) bird.setRotation(
                  desiredRotation);
            }
            if(desiredRotation < bird.getRotation()) {
               bird.setRotation(bird.getRotation() - 900*delta);
               if(desiredRotation > bird.getRotation()) bird.setRotation(
                  desiredRotation);
            }
         }
      }
   }
   
   public void enableGravity() {
      isGravityEnabled = true;
   }
   
   public void disableGravity() {
      isGravityEnabled = false;
   }
   
   public void jump() {
      // if bird is dead do not jump (I think I checked it somewhere already)
      if(!isAlive) return;
      
      // if bird is higher then screen then do not jump
      if(bird.getY() > stage.getHeight()) return;
      
      // if jumped get the custom variable jump_speed from bird actor and set it 
      as current vertical velocity
      currVerticalVelocity = bird.getCustomVariables().getFloatVariable(
                             "jump_speed");
   }
   
   /*
    * Apply gravity each frame (get's delta time since last frame)
    */
   private void gravity(float delta) {
      if(isGravityEnabled) {
         // change curernt velocity based on gravity (gravity changes velocity 
                                                      every second by gravity 
                                                      amount)
         currVerticalVelocity -= delta*bird.getCustomVariables().
                                 getFloatVariable("gravity");
      }
   }
   
   public CompositeItem getBird() {
      return bird;
   }
   
   // get's the bird center coordinates as vector 2 needed for collision 
   detection in GameScreenScript
   public Vector2 getBirdCenter() {
      Vector2 vec = new Vector2(bird.getX() + bird.getWidth()/2, bird.getY() + 
                    bird.getHeight()/2);
      return vec;
   }
   
   // Kills the bird, for reals
   public void die() {
      currVerticalVelocity = 0;  
      isAlive = false;
      desiredRotation = 0; 
      bird.setRotation(0);
      birdAnimation.pause();
   }

}

Programming Design


4. February 2014

 

In my head this part of the process of creating a dynamically equipped character in 3D and rendering it to 2D was going to be a breeze.  Conceptually it went something like this...

 

  • Create a named bone in parent object where the weapon could attach.
  • Create a named bone in the child object where the weapon starts.
  • Find bone one, attach bone two.
  • Go enjoy a beer in smug satisfaction.

 

Sadly it doesn’t quite work like that.

 

There are a couple problems here.

1- LibGDX doesn’t have a SceneGraph.  A Scene Graph is basically a data structure that holds relationships in the world.  Essentially this is what scene2D actually is.  Well, LibGDX sorta has a SceneGraph in the form of Model, which is a graph of nodes that compose the model.  There however isn’t a layer above this for creating relationships between models.  This sadly means I can’t (out of the box) do something like myTank.attachObjectAt(turrent,(3,3,3));

 

2- Modifying bones in LibGDX doesn’t actually seem to do anything.  My first though was… well this is easy enough then, Ill just set the GlobalTransform of the child bone to the location of the parent bone.  This however doesn’t do anything.  I might be missing something here, in fact I probably am.  But I couldn’t get changes to a bone to propagate to the attached model.  This one is likely user error, but after playing around with it for a few days, I am still no further ahead.

 

3- Bones don’t have direction.  Well, that’s not accurate, bones don’t point in a direction.  Here for example is a sample hierarchy of bones exported in text readable format:

{"id": "Armature",
   "rotation": [-0.497507, 0.502480, -0.502480, 0.497507],
   "scale": [ 1.000000, 1.000000, 1.000000],
   "translation": [ 0.066099, 0.006002, -0.045762],
   

   "children": [
      {"id": "Bone_Torso",
      "rotation": [-0.498947, 0.501051, -0.501042, -0.498955],
      "scale": [ 1.000000, 1.000000, 1.000000],
   

      "children": [
         { "id": "Bone_UpArm",
        "rotation": [ 0.007421, -0.000071, -0.009516, 0.999927],
        "scale": [ 1.000000, 1.000000, 1.000000],
        "translation": [ 1.728194, 0.000000, -0.000000],

      "children": [
         {"id": "Bone_LowArm",
         "rotation": [ 0.999846, 0.012394, -0.000030, 0.012397],
         "scale": [ 1.000000, 1.000000, 1.000000],
         "translation": [ 1.663039, 0.000000, 0.000000],

      "children": [
         {"id": "Bone_Hand",
         "rotation": [ 0.999737, -0.016222, -0.000425, 0.016225],
         "scale": [ 1.000000, 1.000000, 1.000000],
         "translation": [ 1.676268, 0.000000, -0.000000]}
      ]}
   ]}
]}

As you can see, you have the Armature, which is basically the root of the skeleton.  It’s translation is the start location of the bones in local space ( of the model ).  Each bone within is therefore offset from the bone above it in the hierarchy.  What is lacking ( for me ), is a direction.  As an aside, I can actually confer the direction using the distance between (in this example) Bone_Hand and Bone_LowArm.  This of course requires two bones on both the parent and child models.

 

Consider this bad drawing.

 

You have a tank and a turret like so, with the red dots representing bone positions:

 

Tankexample1

 

So long as your tank and turret are modelled with consistent coordinate systems ( aka, both same scale, same facings, etc ), you can simply locate the tank bone and offset the turret relative, like so:

Tankexample2

 

In this simple example, it works perfectly!

 

Let’s consider a slightly more advanced situation however. Lets say we are diehard Warhammer fans and want to add sponsons to the side of our tank.

Once again, by modelling consistently with the tank and sponson, we can get:

TankExample3

 

Yay future tank now looks a hell of a lot like the world’s first tank…  but this is pretty much what we want.  Now lets mount one to the other side of the tank.

 

TankExample4

 

Ah shi… that’s not right.  Our second gun is INSIDE the tank.

 

The problem here is, we can’t depend on the coordinates of the both models matching up anymore.  We need to figure out direction when mounting the new weapon to the tank.  This means we need a facing direction for the bone, and this is something we don’t have.

 

Again, this problem has proven trickier then expected.  I will share some of my failed approaches shortly as this post got pretty long.

Design


9. January 2014

 

Right off the hop for my new game I have to deal with a problem that many games have to deal with but one that could have a huge impact on how my game is structured, so I am going to address it with a proof of concept right up front.   That thing, as the title probably spoils, is character customization.

 

As I said earlier, this is a pretty common problem in games and something you see questions about quite often if you hang around game development forums for any period of time.  So what do I mean with character customization?  Ever played Diablo or a similar title?  When you change your gear in Diablo, your character is updated on screen.  This behaviour is pretty much expected in this day and age… personally I really hate when I am playing an RPG and the weapon I equip has no affect on my avatar.  That said, it is certainly a non-trivial problem and one that could have a pretty big impact on your game.

 

Let’s start by taking a look at the various options… at least the ones I can think of.

 

2D - Pre-render all possible configurations

Of course, brute forcing it is always a possibility and in a few cases may actually be ideal.  Basically for a 2D game, you simply create every combination of sprite for every combination of equipment.  So if you have an animation sequence for “walk_left” and “walk_right”, you would have to create a version for each possible equipable item.  So you might have “walk_left_with_axe” and “walk_left_with_sword” sprite sheets for the different weapon combinations.  If you are rendering your spritesheets automatically from a 3D application, this could actually be the easiest approach.  Of course there are some seriously massive downsides to this approach.  Memory usage quickly becomes outrageous.  For each piece of equipment you double the size of your original sprite sheet for example.  Once you start adding more and more options, this approach quickly becomes unfeasible.  If you only have a very small amount of customization ( two or three weapon options ), this approach may appeal due to it’s simplicity.  With anything more than a couple combinations though, this approach is pretty much useless.

 

2D – Pre-rendered spritesheet + pre-rendered weapon animation frames.

You can use a regular sprite sheet and simply keep the weapons separate.  So basically you have two separate sprite sheets, one of the character without weapons, one with just the weapons.  Then at run-time you combine them.   Consider these two sprite sheets ( taken from a StackOverflow question ).

Animated Character:

Player SpriteSheet

Weapon:

Weapon SpriteSheet

Then at run-time you combine the two sprites together depending on what is equipped.

In fact, if your weapon isn’t animated ( as in, it doesn’t move, like a sword, as opposed to a weapon like a whip or nunchucks ) you can get by using a hard point system, where you define the mount position of the weapon ( for example, the players right hand ) and orientation.  Basically for each frame of animation, you provide an x and y coordinate as well as rotation amount that represents where and how the weapon should be mounted.  Then at runtime you combine the two sprites, positioning and rotating the weapon sprite relative to the mount/hardpoint. This way, you only need a single image per equipable weapon.

This approach has a couple downsides.  First, you need a separate data file to hold mount point data and possibly a tool to generate it.  Second, it makes bounding/hit detection more difficult as the mounted weapon may exceed the dimensions of the originating sprite.  Third, you need to deal with z-depth issues, you cant simply paste the weapon on top of the sprite, as what happens when the character is walking right but carrying the weapon in the left hand?  To handle this your workflow needs to basically be: render obscured weapons, render character sprite, render foreground weapons.  Finally, weapons with their own animation, like a whip snapping, would require even more effort.

All told, this is probably the easiest while still flexible system for 2D animation.  It requires a bit more work than simply brute forcing your sprite sheets, but the payoffs in reduced size and complexity are well worth it, especially if you have more than a couple items.  One other big win about this approach is then weapons can be re-used across different sprites, a huge win!  Then you can model a single sword and it will be available to all sprite sheets with hard/mount point information available.

 

3D - Bone/hardpoint system

If your game is pure 3D this is often the way you want to go.  If you character is a knight for example, in your 3D modelling application you create named hard points in your model, either as bones or as an object of some form such as a null object, point or invisible box.  Then at runtime you bind other models to those locations.  So for example, if you equip a long sword and shield, your code searches for the “right_arm_shield” bone and uses it as the parent object for a shield 3D model.  Then you bind a sword to say… the “left_arm_hand” bone.  You can see an example of this behaviour in this UDK example.

This approach is basically identical to the last 2D method mentioned except in 3D and that you dont generally need to define your own hardpoint system, as most 3D packages and engines already support it out of the box, either by binding to a bone or by accessing and parenting 3D objects to named locations.  Like working in 2D, then your weapon and character are two separate entities, like so:

3P_Weapon_Attach.JPG

One of the major advantages of 3D over 2D is flexibility.  Most animations in 2D need to be pre-calculated, while in 3D you have a great deal more flexibility with the computer filling in the blanks for you.  Unlike in 2D, additional 3D animations add very little to the data file sizes.

 

2D Bone based animation

One of the major downsides to 2D animation is, as you add more animations, it takes up more space.  People have been working on solutions, one of the most common of which is 2D bone animation.  How exactly can you use bones on a 2D image file you ask?  That’s a good question!  In 3D, its pretty simple… the motion/influence of the bone transforms the attached geometry.  In 2D, there is no geometry, so how can you do this?

Well, the simple version is, you cut your bitmap or vector image up into body parts.  So instead of a single image of an animated character, you instead of an image for the foot, lower leg, upper leg, torso, waist, shoulder, left upper arm, etc…  Then you can draw 2D bones that control the animation of this hierarchy of images.  There are applications/libraries that support this, making it mostly transparent for you.  Here is one such example from Spine from Esoteric Software.

 

The character:

Creating Bones

 

It looks like a single image ( and you can see a couple bones being drawn in the foot/leg area ), but it is actually composed of a few dozen source images:

Set Parent

 

Basically the workflow goes, you create your traditional image in your regular art program, except instead of creating a single image, you create dozens of hopefully seamless ones representing each body part.  You stitch them together, setting the drawing order ( what’s covering what ), then define bones to create animations.  This has the double advantage of massively decreasing space requirements while simplifying the animation process.  The downsides are creating your initial image are a great deal more difficult and of course, you need to buy ( or roll your own ) bone system, such as Spine. 

 

Spine is not the only option, there is also Spriter from BrashSoftware and probably others I am unaware of.  Both of these are commercial packages, but then, both are dirt cheap ( IMHO ) with price tags between $25 and $250 dollars, with $60 and $25 dollars being the norm with each package respectively.

The nice thing about taking this segmented bone approach… you basically get the ability to swap components or bind weapons for free.

 

2.5D hybrid approach

2 1/2D is becoming more and more popular these days.  Essentially a 2.5D game is a 3D game with 2D assets ( such as 2D sprites over a 3D background ), but more commonly its 3D sprites over a 2D background.  How does this work?

Well there are two basic approaches.  You model, texture, animate your 3D model as per normal.  Any character customization you perform you would do as if you were working in full 3D.  Now is where the two different approaches vary, depending on performance, the hardware you are running on, etc…  You can either generate a sprite sheet dynamically.  Essentially when your character is loaded or you change equipment, in the background your game renders a sprite sheet of your updated character containing every animation frame, then you use this sheet as if it was a normal 2D sprite sheet.  The other option is, you render your character each time it moves.  Creating a spritesheet consumes more memory, but very little GPU or CPU demand.  Generating your characters current animation frame dynamically on the other hand, takes almost no memory, but at a much higher CPU/GPU burden.  Which is right for your game is obviously up to you.

Of course the 2.5D approach certainly has it’s share of problems too.  First off, it is the most complicated of the bunch.  Second, you cant do any “by hand” calculations on your generated sprite/spritesheets, as they are now being rendered dynamically.  This means no ability to create pre-calculated bounding volumes for example.  On the other hand, the 2.5D approach gives you most of the advantages of 3D ( compact animation data structure, easy programmable modification, ability to alter texture mapping, lighting effects, etc… ) that 3D does, but with the simplicity of dealing with a traditional 2D world.

One animation to rule them all!

You may be thinking WAHOO… I can cut my work way down now!  All I need to do is animate an attack sequence and then I can simply substitute the different weapon images.  Not so fast I am sorry to say.  Think about it this way…  are the images for swinging an AXE and a Sword the same?  What about a pole arm?  You are still going to have several different animations to support different classes of weapons, but these techniques will still vastly reduce the amount of data and work required while allowing a ton of customization.

 

 

So then, what am I going to do?

So, which approach am I taking?  Ultimately I am going to require a great deal of customization, going far beyond the examples described above.  One such example scenario is a Mech with a customizable left weapon… this weapon could be an arm holding a gun, a turret containing one or more guns, or possibly even a large pack of rockets.  Each “weapon” could have it’s own animation set.  Oh, and I am much more proficient in 3D than 2D.  On the other hand, the game itself is a 2D game and I would prefer to keep it that way for the simplicity that brings in a number of areas ( level creation tools, path-finding and other AI tasks, physics, cheating at art, etc… ).  As a result, I am going to try the 2.5D approach, where the mech is created and animated in 3D, dynamically equipped, then rendered to 2D.  I am going to try both pre-rendering sprite sheets and dynamically rendering a single frame and see what the overhead of each is.  I actually have the compounded issue of dealing with enemy characters that are also dynamically generated, so any impact will be magnified many time over!

If I can’t get adequate performance from each approach, I may be forced to go full 3D and emulating a 2D look.  As I said, it’s one of those things that can have a major impact on your game!  That said, I am pretty confident performance wont be too much of a factor.  My immediate take away task list is:

  • get a LibGDX project set up that can load and render an textured, animated 3D model exported from Blender. I am pretty new to 3D in LibGDX ( okay… completely new to it )
  • bind another model to a bone on this model ( aka, a sword to a hand bone )
  • try to dynamically generate a sprite sheet of the character’s complete animation.  Measure resulting memory usage and time required to generate sheet
  • re-architect the code to instead generate each frame of animation per frame on demand.
  • scale both scenarios up to include multiple instances and see results on performance
  • measure performance impact of each approach on both desktop and mobile.

 

The outcome of this experiment will ultimately decide what approach I take.  Stay tuned if that process sounds interesting!

 

Oh, and of course, these are only the scenarios I could come up with for dealing with dynamically equipped characters, if you have another idea, please share it!

Design Programming


7. August 2013

 

This isn’t an area I spend a ton of time on, as I haven’t got much talent for drawing.  That said, if I just fire up Blender and start modelling I tend to be a lot slower then if I nail down the basics of my concept, at least the proportions and overall shape, before even beginning to model.

 

In this case my concept was pretty simple… I want to make a jet that is a throwback to classic planes of old like the twin tailed Lockheed P38 Lightning or the DeHavilland Vampire, except with wing mounted engines like the Me-262.  However, I want it to appear near-future modern, like a contemporary of the F22 Raptor or F35 Lightning II.

 

For non plane buffs, I basically want:

 

This (P38):

p38

 

Or This (Vampire):

Vamp

 

With engines like these (Me-262):

me262

 

But more modern/futuristic, like this ( F22 ):

f22

 

 

Got it?  So basically I want a retro style twin tailed jet that looks futuristic.

 

So, time for some doodling!  I have a tendency to start with something really quick, break it down into individual pieces and go from there.  This way I get mostly the correct perspective, but I can work on smaller details instead of big picture… I can also quickly decide what works and what doesn’t.

 

For this, I worked entirely on my iPad Mini using a 5 dollar stylus and the application iDraw, which is a vector based graphic suite for iOS and MacOS.  Obviously any sketching app would work, as would paper if you have access to a scanner or digital camera.

 

Here is my first brain dump of the concept, side and top view:

1

 

I'm relatively happy with the top view, but hate the under-wing engine and am not a fan at all of the side profile.  I am thinking wingmounted engines don't work too well with the look I am shooting for here.

 

Instead I am going to switch to a single jet engine, like the Vampire pictured above.  Let’s clean up the tail section a bit and move to a single centrally mounted engine, again top and side view:

2

 

OK, I'm pretty happy with that look over all, now I’m going to look at the top and wing layout.  I start with:

3

 

Not really a fan.  Doesn’t make a ton of sense for the wing to extend out in front of the air intake.  Instead I decide to extend the air intake forward quite a bit, like so:

4

 

I like the overall shape better, it’s starting to look more modern, but I am still not a fan of the cockpit, nor have I nailed down the side profile yet.

 

On to the side profile.  I start with a quick sketch of the side, now using the forward wing, air intake and single engine. 

5

 

I did a quick sketch in black and it’s too fat and not very modern.  Drew over it in red more to my liking.

 

Now it’s a matter of figuring out the cockpit I am still not happy with, as well as the front view.

6

 

Started with a 3/4 view of the cockpit area, a rough front sketch, then a slightly cleaner one.  Over all, I’m pretty happy with the front profile.

 

So, I’ve got my basic design down, now the most important part, as a modelling aid and so I get the proportions generally right, I trace over the side and top view of my design using the line tool and end up with this:

7

 

The basic outline for the side and top profile of our jet.  I am certainly going to win no awards for artistic talent, but it should be sufficient for my needs and over all, I’m fairly pleased with the design concept.

 

You will see how we use it in the next part when we fire up Blender.

Art Design


1. August 2013

 

Way way wayyyyyy back when I created I want to be a game developer… now what? I wrote:

So, you’ve picked a language, the libraries you want to use and now you need to, you know… do something.  The following are a list of suggested projects for a new developer interested in games, with a ( fully my opinion ) difficulty rating attached

Then I completely neglected to actually provide the list.   Oops.

 

As this is one of those questions that comes up so often with new developers, I’ve decided to finally answer it.  Basically this is just a list of progressively more difficult game projects that you can work on when just starting out, as well as details of why to do each project.  Of course, you don’t need to do any or all of these projects, it is simply a logical ( to me! ) progression of projects for a new game developer to work on. 

 

For each example, I've linked some random tutorials that you can refer to if you have trouble.  I would suggest trying to do it without the help of a tutorial the first time, you will learn more that way.  That said, there is no reason to bang your head against the wall over and over if you run into difficulty.  Although occasionally satisfying, head banging is rarely an effective learning method.  If there was a new concept introduced with the game, I often also add other links that should prove of some use to you. 

 

The tutorials were discovered mostly using Google, then I took a brief look at the code to make sure it wasn't awful.  If you have better recommendations for linked tutorials, let me know in the comments and I will edit them in!  If you run into trouble, also let me know in the comments and I will see what I can do. I hope some of you find this guide useful!

 

Games you should make when just starting out, in chronological order

 

Adventure/Zork/Simple text adventure

Why?

It's about as simple as you can get and still call it a game.  You are going to learn string handling, something you will be doing A LOT.  You will also implement a rudimentary game loop ( get input, update world, display result ).  Also, you don't have the added complexity of graphics.

Examples:

C++ text adventure tutorial

Java text adventure tutorial

Javascript text adventure sourcecode

 
 

Hangman

HangmanExample

Why?

If creating a text adventure isn't your thing, Hangman is another simple game concept that doesn't require graphics.  In many ways, the process will be virtually identical to a text adventure, so if you do the one, you won't really learn much by doing the other and vice versa.

Examples:

C# Hangman tutorial

C++ Hangman tutorial

JavaScript Hangman tutorial

Java Hangman tutorial

 
 

Tic Tac Toe

Why?

One word… AI.  While not having made the jump to graphical programming yet, you are now going to have an opponent to program.  The nice thing about Tic Tac Toe is, you can start of brute forcing the logic, but after some time you can look at implementing a more elegant solution.

Examples:

Java Tic Tac Toe Tutorial

C# Tic Tac Toe

See Also:

Once you've got Tic Tic Toe going, consider looking at a more elegant way of solving the board.  A very commonly use algorithm in AI development for making decisions is the MinMax algorithm.  After you licked MinMax, there is an optimized version called AB ( alpha-beta pruning ).

MinMax description

MinMax and AB pruning explained ( pseudo code )

C# implementation of Tic Tac Toe using Minmax and AB pruning.

 
 

Pong

Why?

Welcome to the wonderful world of graphics!  You will have to learn about the render loop, how you draw the world each frame.  This will also be your first taste of collision detection, although with Pong this can be faked.  You will also have to learn how to make an AI that isn't perfect!  Of course, you will also be taking your first steps into 2D game math, although you can minimize the math required a great deal, depending on how you implement Pong.  You may also encounter a state machine for the first time, depending on how you implement it.  Pong represents a project you can start simply and make a great deal more complex as you get comfortable.

 

Examples:

Over-engineered pong in C++ using SFML ( on GameFromScratch.com )

Pong in XNA (C#)

JavaScript Pong

 

See Also:

At this point you are going to need to select a graphics library for your language of choice.  Pong is simple enough you can often get buy using the native drawing library of your programming language ( if it has one, C or C++ do not ).  Otherwise you need to select a library.  This post should help you in the selection process if you are using C++, C#, Java or Python.  If you are using Lua, this post should help.  If you are using JavaScript, select a library here.

Now might be a good time to brush up on the concept of a game loop.

 

Breakout

Why?

Well, it's basically Pong for one player with slightly more sophisticate math.  Purely optional, but if you completed Pong, Breakout/Arkanoid should be a pretty easy progression.  Granted, you won't really learn much new.

 

Examples:

Breakout in JavaScript using Canvas

Breakout in Java

Asteroids

Why?

Math baby math.  The process is going to be very similar to Breakout or Pong, but since the player can move and shoot in many directions, the math is going to be very different.  The collision detection is also going to be more complicated.  Don't let math scare you off, it's not really that complicated, and I've got examples/tutorials for basically everything you need to know!

Examples:

Asteroids in C#/XNA

Asteroids in Python with PyGame

 

See Also:

For the math, I've created a series of math tutorials that cover everything you need to know to implement Asteroids.

PacMan

Pac-man

Why?

PacMan introduces a couple interesting concepts.  First is the concept of a level file or map.  Next is the AI controlling the ghosts, commonly implemented using a State Machine, a very common algorithm in game programming.  PacMan also introduces the concept of levels.

Examples:

PacMan in JavaScript

Source for PacMan in LUA/LOVE

Source for PacMan in C++/SDL

 

See Also:

Finite State Machine in PacMan (PDF Link)

Platformer

SMB

Why?

Now would be a good time to try and implement a platforming game, be it a single screen game like Donkey Kong, to a side scroller like Super Mario brothers.  You will be faced with implementing some kind of physics ( jumping, falling, not-falling ) and more advanced collision detection than you have to date.  You will also have more difficult level requirements.  Optionally at this point, you can implement physics in your game, don't worry, it's not as scary as it sounds.

Examples:

JavaScript platformer tutorial (link to part two is in the comments)

Android platformed with Java/libGDX

 

See Also:

A big requirement to creating a platformer is a level creation tool.  Now might be a good time to check out Tiled one of the most popular, and free, map editing tools available.  If you decide to use Tiled, I have a very detailed tutorial series to get you started.

For 2D physics, Box2D is the most popular library and it has been ported to dozens on languages.  Here is a tutorial on creating a platformer using Box2D and Cocos2D with Objective-C.

What now?

 

That will have covered off most of the basics.  The only thing glaringly missing from the list of things covered that I can think of is advanced pathfinding, such as learning the A* (A-star) algorithm.  You can learn more about it by reading this Stanford article.  The next logical jump would probably be to work in 3D, if that's where you want to go next ( you could easily spend your entire life just working on 2D games if that was your preference ).  If you want to go 3D, I highly recommend using an engine to start.  If you are struggling with how to create art for your game you may want to check out A Programmer's Guide to creating art for your game.

 

Once again, this page was simple meant as a list of suggestions for games to create for developers that are just starting out.  Feel free to do them in whatever order you want, or to skip them entirely, but as listed above, the difficulty progression does make a certain amount of sense.

Programming Design


GFS On YouTube

See More Tutorials on DevGa.me!

Month List