Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon

27. February 2015

 

In this tutorial, we look at animating sprites using the Animation class.  We look at loading sprites two different ways.  First creates them by splitting up a Texture loaded into memory.  The second example uses a texture atlas.  As always the code is provide below.

 

You can watch the video in HD here.

 

 

The Source

 

Example 1:

package com.gamefromscratch;

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.Animation;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;

public class AnimationDemo extends ApplicationAdapter {
   SpriteBatch batch;
   Texture img;
   TextureRegion[] animationFrames;
   Animation animation;
   float elapsedTime;
   
   @Override
   public void create () {
      batch = new SpriteBatch();
      img = new Texture("walkcycle.png");

      TextureRegion[][] tmpFrames = TextureRegion.split(img,256,256);

      animationFrames = new TextureRegion[4];
      int index = 0;

      for (int i = 0; i < 2; i++){
         for(int j = 0; j < 2; j++) {
            animationFrames[index++] = tmpFrames[j][i];
         }
      }

      animation = new Animation(1f/4f,animationFrames);
   }

   @Override
   public void render () {
      elapsedTime += Gdx.graphics.getDeltaTime();
      Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
      batch.begin();
      batch.draw(animation.getKeyFrame(elapsedTime,true),0,0);
      batch.end();
   }
}

 

Example 2:

package com.gamefromscratch.com;

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.Animation;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;

public class TextureAtlasAnimationDemo extends ApplicationAdapter {
   SpriteBatch batch;
   private TextureAtlas textureAtlas;
   private Animation animation;
   private float elapsedTime = 0f;
   
   @Override
   public void create () {
      batch = new SpriteBatch();
      textureAtlas = new TextureAtlas(Gdx.files.internal("spritesheets/myspritesheet.atlas"));
      animation = new Animation(1f/15f, textureAtlas.getRegions());
   }

   @Override
   public void dispose() {
      batch.dispose();
      textureAtlas.dispose();
   }

   @Override
   public void render () {
      elapsedTime += Gdx.graphics.getDeltaTime();
      Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
      batch.begin();
      batch.draw(animation.getKeyFrame(elapsedTime,true),0,0);
      batch.end();
   }
}

Programming , , ,

3. February 2015

 

In this next part in the ongoing LibGDX Video tutorial series, we take our final look at the Scene2D library.  Specifically we look at using Scene2D to provide a UI, including buttons, windows, layout containers and more.  We also look at how to mix “normal” and Scene2D games together. 

 

The video is available in full HD here.  The source code from the examples is below the video:

 

Example 1

package com.gamefromscratch;

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;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Dialog;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.utils.Timer;
import com.badlogic.gdx.utils.viewport.ScreenViewport;

public class Scene2DUiDemo1 extends ApplicationAdapter {
   private Skin skin;
   private Stage stage;
   
   @Override
   public void create () {
      skin = new Skin(Gdx.files.internal("uiskin.json"));
      stage = new Stage(new ScreenViewport());

      final TextButton button = new TextButton("Click Me",skin,"default");
      button.setWidth(200);
      button.setHeight(50);

      final Dialog dialog = new Dialog("Click Message",skin);

      button.addListener(new ClickListener(){
         @Override
         public void clicked(InputEvent event, float x, float y) {
            dialog.show(stage);
            Timer.schedule(new Timer.Task() {
               @Override
               public void run() {
                  dialog.hide();
               }
            }, 10);
         }
      });
      stage.addActor(button);

      Gdx.input.setInputProcessor(stage);
   }

   @Override
   public void render () {
      Gdx.gl.glClearColor(0, 0, 0, 1);
      Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
      stage.act(Gdx.graphics.getDeltaTime());
      stage.draw();
   }


}

Example 2

package com.gamefromscratch;

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;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.*;
import com.badlogic.gdx.scenes.scene2d.utils.Align;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.utils.Timer;
import com.badlogic.gdx.utils.viewport.ScreenViewport;

public class Scene2DUiDemo1 extends ApplicationAdapter {
   private Skin skin;
   private Stage stage;

   private Table table;
   private TextButton startButton;
   private TextButton quitButton;
   
   @Override
   public void create () {
      skin = new Skin(Gdx.files.internal("uiskin.json"));
      stage = new Stage(new ScreenViewport());
      table = new Table();
      table.setWidth(stage.getWidth());
      table.align(Align.center | Align.top);

      table.setPosition(0,Gdx.graphics.getHeight());
      startButton = new TextButton("New Game",skin);
      quitButton = new TextButton("Quit Game",skin);

      table.padTop(30);

      table.add(startButton).padBottom(30);

      table.row();
      table.add(quitButton);

      stage.addActor(table);
      Gdx.input.setInputProcessor(stage);
   }

   @Override
   public void render () {
      Gdx.gl.glClearColor(0, 0, 0, 1);
      Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
      stage.act(Gdx.graphics.getDeltaTime());
      stage.draw();
   }


}

 

Example 3

package com.gamefromscratch;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputMultiplexer;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.actions.RepeatAction;
import com.badlogic.gdx.scenes.scene2d.ui.*;
import com.badlogic.gdx.scenes.scene2d.utils.Align;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.utils.Timer;
import com.badlogic.gdx.utils.viewport.ScreenViewport;

public class Scene2DUiDemo1 extends ApplicationAdapter implements InputProcessor {
   private Skin skin;
   private Stage stage;

   private Table table;
   private TextButton startButton;
   private TextButton quitButton;

   private SpriteBatch batch;
   private Sprite sprite;
   
   @Override
   public void create () {
      skin = new Skin(Gdx.files.internal("uiskin.json"));
      stage = new Stage(new ScreenViewport());
      table = new Table();
      table.setWidth(stage.getWidth());
      table.align(Align.center | Align.top);

      table.setPosition(0,Gdx.graphics.getHeight());
      startButton = new TextButton("New Game",skin);
      quitButton = new TextButton("Quit Game",skin);

      startButton.addListener(new ClickListener() {
         @Override
         public void clicked(InputEvent event, float x, float y) {
            Gdx.app.log("Clicked button","Yep, you did");
            event.stop();
         }
      });

      table.padTop(30);

      table.add(startButton).padBottom(30);

      table.row();
      table.add(quitButton);

      stage.addActor(table);



      batch = new SpriteBatch();
      sprite = new Sprite(new Texture(Gdx.files.internal("badlogic.jpg")));
      sprite.setSize(Gdx.graphics.getWidth(),Gdx.graphics.getHeight());

      Timer.schedule(new Timer.Task() {
         @Override
         public void run() {
            sprite.setFlip(false,!sprite.isFlipY());
         }
      },10,10,10000);


      // ORDER IS IMPORTANT!
      InputMultiplexer im = new InputMultiplexer(stage,this);
      Gdx.input.setInputProcessor(im);
   }

   @Override
   public void render () {
      Gdx.gl.glClearColor(0, 0, 0, 1);
      Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

      batch.begin();
      sprite.draw(batch);
      batch.end();

      stage.act(Gdx.graphics.getDeltaTime());
      stage.draw();
   }


   @Override
   public boolean keyDown(int keycode) {
      return false;
   }

   @Override
   public boolean keyUp(int keycode) {
      return false;
   }

   @Override
   public boolean keyTyped(char character) {
      return false;
   }

   @Override
   public boolean touchDown(int screenX, int screenY, int pointer, int button) {
      sprite.setFlip(!sprite.isFlipX(),sprite.isFlipY());
      return true;
   }

   @Override
   public boolean touchUp(int screenX, int screenY, int pointer, int button) {
      return false;
   }

   @Override
   public boolean touchDragged(int screenX, int screenY, int pointer) {
      return false;
   }

   @Override
   public boolean mouseMoved(int screenX, int screenY) {
      return false;
   }

   @Override
   public boolean scrolled(int amount) {
      return false;
   }
}

 

uiskin.json

// @formatter:off
{
  com.badlogic.gdx.graphics.g2d.BitmapFont: { default-font: { file: Razer.fnt } },
  com.badlogic.gdx.scenes.scene2d.ui.TextButton$TextButtonStyle: {
   default: { down: default-round-down, up: default-round, font: default-font },
  },
  com.badlogic.gdx.scenes.scene2d.ui.Window$WindowStyle: {
    default:  {
      titleFont: default-font
     }
   }
}

Programming , , ,

6. January 2015

 

In this second part of multiple part video tutorial looking at using Scene2D we look at creating Actors and Actions.  Actors are the entities that compose your game, while Actions are the things that make those Actors do… stuff.  The code for this example is included below the video.  The video on YouTube is available in high definition.

 

 

Actor Demo

package com.gamefromscratch;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.utils.viewport.ScreenViewport;

public class ActorDemo extends ApplicationAdapter {

   Stage stage;

   @Override
   public void create () {
      ScreenViewport viewport = new ScreenViewport();
      stage = new Stage(viewport);
      Gdx.input.setInputProcessor(stage);

      MyActor actor = new MyActor();
      stage.addActor(actor);
      stage.setKeyboardFocus(actor);
   }

   @Override
   public void render () {
      Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
      stage.act(Gdx.graphics.getDeltaTime());
      stage.draw();
   }
}
 
package com.gamefromscratch;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.Touchable;
import com.badlogic.gdx.scenes.scene2d.actions.MoveByAction;

public class MyActor extends Actor {
    Sprite sprite = new Sprite(new Texture(Gdx.files.internal("badlogic.jpg")));

    public MyActor(){
        setBounds(sprite.getX(),sprite.getY(),sprite.getWidth(),sprite.getHeight());
        setTouchable(Touchable.enabled);

        addListener(new InputListener(){
            @Override
            public boolean keyDown(InputEvent event, int keycode) {
                if(keycode == Input.Keys.RIGHT){
                    MoveByAction mba = new MoveByAction();
                    mba.setAmount(100f,0f);
                    mba.setDuration(5f);

                    MyActor.this.addAction(mba);
                }
                return true;
            }
        });
    }

    @Override
    protected void positionChanged() {
        sprite.setPosition(getX(),getY());
        super.positionChanged();
    }

    @Override
    public void draw(Batch batch, float parentAlpha) {
        sprite.draw(batch);
    }

    @Override
    public void act(float delta) {
        super.act(delta);
    }
}

 

Action Demo

package com.gamefromscratch;

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.scenes.scene2d.Stage;
import com.badlogic.gdx.utils.viewport.ScreenViewport;

public class ActionDemo extends ApplicationAdapter {

   Stage stage;

   @Override
   public void create () {
      stage = new Stage(new ScreenViewport());
      stage.addActor(new MyActor(new Texture(Gdx.files.internal("badlogic.jpg"))));
      Gdx.input.setInputProcessor(stage);
      stage.setKeyboardFocus(stage.getActors().first());
   }

   @Override
   public void render () {
      Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
      stage.act(Gdx.graphics.getDeltaTime());
      stage.draw();
   }
}
 
package com.gamefromscratch;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.actions.*;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;

import static com.badlogic.gdx.scenes.scene2d.actions.Actions.*;
import static com.badlogic.gdx.scenes.scene2d.actions.Actions.addAction;


public class MyActor extends Image {

    @Override
    public void draw(Batch batch, float parentAlpha) {
        batch.setColor(this.getColor());

        ((TextureRegionDrawable)getDrawable()).draw(batch, getX(),getY(),
                getOriginX(),getOriginY(),
                getWidth(),getHeight(),
                getScaleX(),getScaleY(),
                getRotation());
    }

    public MyActor(Texture texture){
        super(texture);

        setBounds(getX(),getY(),getWidth(),getHeight());

        addListener(new InputListener(){
            @Override
            public boolean keyDown(InputEvent event, int keycode) {
                switch(keycode) {
                    case Input.Keys.NUM_1:
                        MoveToAction moveToAction = new MoveToAction();
                        moveToAction.setPosition(200f,200f);
                        moveToAction.setDuration(5f);
                        MyActor.this.addAction(moveToAction);
                        break;

                    case Input.Keys.NUM_2:
                        MoveByAction moveByAction = new MoveByAction();
                        moveByAction.setAmount(-200f,0f);
                        moveByAction.setDuration(3f);
                        MyActor.this.addAction(moveByAction);
                        break;

                    case Input.Keys.NUM_3:
                        ColorAction colorAction = new ColorAction();
                        colorAction.setEndColor(Color.PURPLE);
                        colorAction.setDuration(5f);
                        MyActor.this.addAction(colorAction);
                        break;

                    case Input.Keys.NUM_4:
                        MoveToAction mta = new MoveToAction();
                        mta.setPosition(Gdx.graphics.getWidth() - 200f,Gdx.graphics.getHeight()-200f);
                        mta.setDuration(3f);

                        ScaleByAction sba = new ScaleByAction();
                        sba.setAmount(2f);
                        sba.setDuration(3f);

                        RotateToAction rta = new RotateToAction();
                        rta.setRotation(90f);
                        rta.setDuration(3f);

                        ParallelAction pa = new ParallelAction(mta,sba,rta);
                        MyActor.this.addAction(pa);
                        break;

                    case Input.Keys.NUM_5:
                        MoveToAction mta2 = new MoveToAction();
                        mta2.setPosition(Gdx.graphics.getWidth() - 200f,Gdx.graphics.getHeight()-200f);
                        mta2.setDuration(3f);

                        ScaleByAction sba2 = new ScaleByAction();
                        sba2.setAmount(2f);
                        sba2.setDuration(3f);

                        RotateToAction rta2 = new RotateToAction();
                        rta2.setRotation(90f);
                        rta2.setDuration(3f);

                        SequenceAction sa = new SequenceAction(mta2,sba2,rta2);
                        MyActor.this.addAction(sa);
                        break;

                    case Input.Keys.NUM_6:
                        RunnableAction ra = new RunnableAction();
                        ra.setRunnable(new Runnable(){
                            @Override
                            public void run() {
                                MyActor.this.setPosition(0f,0f);
                                MyActor.this.setRotation(0f);
                                MyActor.this.setScale(1f);
                            }
                        });
                        MyActor.this.addAction(ra);
                        break;

                    case Input.Keys.SPACE:
                        addAction(parallel(
                            moveTo(200f, 200f, 3f),
                            scaleTo(2f, 3f),
                            rotateTo(90f, 3f)
                        ));
                        break;
                }
                return true;
            }
        });
    }
}

Programming , , ,

30. December 2014

 

In this first of multiple part video tutorial we start looking at using Scene2D in LibGDX.  Scene2D is a library built over top of LibGDX providing a scene graph and UI/widget layer.  None of that make any sense?  Then watch the video! :)  Speaking of which, it is available in 1080p on YouTube.

 

 

The code from the example:

package com.gamefromscratch;

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.Batch;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.utils.viewport.ScreenViewport;

public class Scene2DDemo1 extends ApplicationAdapter {

   class MyActor extends Actor {
      Texture texture = new Texture(Gdx.files.internal("badlogic.jpg"));

      @Override
      public void draw(Batch batch, float parentAlpha) {
         batch.draw(texture,0,0);
      }
   }
   Stage stage;
   @Override
   public void create () {
      stage = new Stage(new ScreenViewport());
      MyActor actor = new MyActor();
      stage.addActor(actor);
      Gdx.input.setInputProcessor(stage);
   }

   @Override
   public void render () {
      Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
      stage.draw();
   }
}

Programming , , ,

19. December 2014

 

In this tutorial we look at the process of creating and using a Spritesheet in LibGDX.  This involves creating a series of sprites, putting them together with TexturePacker, then using a TextureAtlas and TextureRegion to display them with our Sprite.  We also quickly look at TexturePacker ( different product ) for those that prefer a UI.  Sample code and links to included assets below the video.

 

Once again, you can view the video in HD on YouTube by click here.

 

 

Example’s Source

package com.gamefromscratch;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureRegion;

public class SpritesheetDemo extends ApplicationAdapter implements InputProcessor {
   SpriteBatch batch;
   TextureAtlas textureAtlas;
   Sprite sprite;
   TextureRegion textureRegion;
   int currentFrame = 1;
   int MAX_FRAMES = 19;
   
   @Override
   public void create () {
      batch = new SpriteBatch();
      textureAtlas = new TextureAtlas(Gdx.files.internal("ss.txt"));
      textureRegion = textureAtlas.findRegion("0001");
      sprite = new Sprite(textureRegion);
      sprite.setPosition(Gdx.graphics.getWidth()/2 - sprite.getWidth()/2,
            Gdx.graphics.getHeight()/2 - sprite.getHeight()/2);

      Gdx.input.setInputProcessor(this);
   }

   @Override
   public void render () {
      Gdx.gl.glClearColor(0, 0, 0, 1);
      Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
      batch.begin();
      sprite.draw(batch);
      batch.end();
   }

   @Override
   public boolean keyDown(int keycode) {
      if(keycode == Input.Keys.UP){
         currentFrame++;
         if(currentFrame > MAX_FRAMES)
            currentFrame = 1;
         sprite.setRegion(textureAtlas.findRegion(String.format("%04d",currentFrame)));
      }
      if(keycode == Input.Keys.DOWN){
         currentFrame--;
         if(currentFrame < 1)
            currentFrame = MAX_FRAMES;

         sprite.setRegion(textureAtlas.findRegion(String.format("%04d",currentFrame)));
      }
      return true;
   }

   @Override
   public boolean keyUp(int keycode) {
      return false;
   }

   @Override
   public boolean keyTyped(char character) {
      return false;
   }

   @Override
   public boolean touchDown(int screenX, int screenY, int pointer, int button) {
      return false;
   }

   @Override
   public boolean touchUp(int screenX, int screenY, int pointer, int button) {
      return false;
   }

   @Override
   public boolean touchDragged(int screenX, int screenY, int pointer) {
      return false;
   }

   @Override
   public boolean mouseMoved(int screenX, int screenY) {
      return false;
   }

   @Override
   public boolean scrolled(int amount) {
      return false;
   }
}

 

The sprite art used for this example was rendered using this Blender file.

The texture packing application (near the end) was CodeAndWeb’s TexturePacker.

Programming , , , ,

Month List

Popular Comments