Tag Archives: Multiplatform Dev

Developing Multiplatform Game With Libgdx – part 4 – Game Field & Hero Placement

Preparing Assets

So, we have the background, maybe now it’s the time to get to the elements in the front. We’ll try to display a walkable tiles (4×4), and a player.

Since there’s really no way to indicate the walkable tiles, let’s draw a simple „base” first.  Make a small picture 16×2 and draw something like a base where character can stand at. Here’s mine (I’m really not an artist):

base

This will indicate where player can move. Save it as base.png. One thing that I’ve learned as I started to develop games is that this type of bases should never be as big as the character. Since our characters are 16×16, it might seem like a good idea to make the base as the square (which will be drawn around our character). Nothing can be further from the truth! If we do this – the characters will look ‘caged’ in the tiles which makes the game look bad.

As for the player, we pick one from the same tileset by Lanea Zimmerman (http://opengameart.org/content/tiny-16-basic). Just open up characters.png and cut out 16×16 tile with any character you like. Here’s mine:

player

Cool. Save it as player.png.

Let’s add those resources in our Resources class.  Similar to our ground and wall declarations, let’s declare two more TextureRegions: player and base.

public TextureRegion player;
public TextureRegion base;

Load them the same way you loaded wall and ground.

player = gameSprites.findRegion("player");
base = gameSprites.findRegion("base");

Ok, we’re done here. But before we proceed to actual drawing, we need to determine WHERE to draw them, right?

Programming The Coordinates

Again, we need to position those things in a good way. The way I approach it is that I usually create some sort of SizeEvaluator class which calculates the stage width and gets me the relative positions of the elements on the stage. Let’s get to programming! In our graph package, add a new class. Name it SizeEvaluator. This will actually calculate where we should place our hero / enemy / tile bases.

Add the private variable Stage measuredStage; this one will be pointing towards the current game stage. Also, add the private variable Resources which will be pointing, you’ve guessed it correctly, to the game resources.

The SizeEvaluator will also contain the max X and max Y the base tile can have. We have 4×4 field, so x and y will limit to 3 [0..3]. Similar to the screen coordinates, X will go from left to right (0 being the leftmost, 3 being the rightmost) and Y go from bottom to top (0 at the bottom, 3 at the top).

The SizeEvaluator constructor is going to accept a stage as parameter and assign the value to measuredStage. The same with resources: we’ll need them to get the tile sizes in order to properly calculate the distances. We’ll also need to pass max base x and max base y to it.

This is how it should look at first:

public class SizeEvaluator {

    Stage measuredStage;
    Resources resources;

    private final int maxTileBaseX;
    private final int maxTileBaseY;

    public SizeEvaluator(Stage _stage,
                         Resources _resources,
                         int _maxTileBaseX,
                         int _maxTileBaseY)
    {
        measuredStage = _stage;
        resources = _resources;

        maxTileBaseX = _maxTileBaseX;
        maxTileBaseY = _maxTileBaseY;
    }

}

 

It still does nothing. Let’s fix it! We’ll write the function which will give back the tile coordinates. We’ve talked that our hero (and the walkable tiles) are going to be located on the left. That means that we can simply take the width of the stage, split it into two then add some margin and take the position of the base into account.

We’ll implement the public function getBaseScreenX(int baseX) and getBaseScreenY(int baseY). It will take the x and y coordinates of the base (x and y can range from 0 to 3 included) and return their position on the screen.

The first implementation of functions is going to look like this:

public float getBaseScreenX(int baseX)
{
    return measuredStage.getWidth() / 2 - resources.TILE_SIZE * (1 + 
maxTileBaseX - baseX);
}

Quite simple: as we discussed before, we split the stage width by two (getting the coordinates of the middle), then we substract as tile widths to get to our necessary base x. (i.e. if we pass 0 as base X, we’ll take middle of our scene (call it midX) and substract (4 – 0) * 16 from it, getting the leftmost base tile coordinate).

 

We’re adding 1 to maxTileBase coordinate in order to handle the max case effectively. If we would not do it, the tile would be drawn over the middle (you can experiment and see what happens if you take away “1 +” part from the equation).

public float getBaseScreenY(int baseY)
{
    return measuredStage.getHeight() / 2 - resources.TILE_SIZE * ((maxTileBaseY + 1) / 2 - baseY);
}

getBaseScreenY looks a bit different. We want to center it vertically (equal amounts of tiles on top and bottom): to do that, we take the vertical middle of the scene and substract the half of total possible base field height (we have 4 bases with 16 sized tiles), so we substract 32 right now.

 

Adding SizeEvaluator to our Game Screen

Time to implement it now! In our GameScreen, declare a private variable SizeEvaluator sizeEvaluator; Declare constants MAX_BASE_X and MAX_BASE_Y, that we’re going to pass to our SizeEvaluator.

private static final int MAX_BASE_X = 3;
private static final int MAX_BASE_Y = 3;

Initialize the SizeEvaluator in GameScreen constructor (right at the end of it, after we’ve already initialized gameStage). Here’s how my GameScreen constructor looks now, see final line:

public GameScreen(DodgingHero _game) {
    super(_game);
    batch = new SpriteBatch();
    bg = new Background();

    ExtendViewport viewp = new ExtendViewport(STAGE_W, STAGE_H); 
    gameStage = new Stage(viewp, batch);
    sizeEvaluator = new SizeEvaluator(gameStage, game.res, MAX_BASE_X, MAX_BASE_Y);
}

Now we can proceed to drawing the bases. Let’s add function drawBases(), right here, in GameScreen class:

private void drawBases()
{
    batch.begin();
    for (int x = 0; x <= MAX_BASE_X; x++)
    {
        for (int y = 0; y <= MAX_BASE_Y; y++)
        {
            batch.draw(game.res.base,
                    sizeEvaluator.getBaseScreenX(x),
                    sizeEvaluator.getBaseScreenY(y));
        }
    }
    batch.end();
}

Before every drawing, we start our batch batch.begin(). After we are done drawing everything, we call batch.end(). We’ll go through our cycle and draw MAX_BASE_X + 1 columns, each containing MAX_BASE_Y +1 elements. (4×4, like we’ve planned).

Add the drawBases call in our render function, right after we call bg.draw:

bg.draw(gameStage, game.res);
drawBases();

Run the game and see what happens.

Tiles, first version

Tiles, first version

Well, we got some results, right? But it does feel somewhat off. Firstly, the bases are too tightly put together. Let’s add some margin before them.

Get back to our SizeEvaluator class and implement a new int constant: BASE_MARGIN, which will be equal to 2 (pick any number you like, but be reasonable: it’s the distance between bases).

private final int BASE_MARGIN = 2;

 

Now add this to getBaseScreenX and getBaseScreenY equations. We want it to affect the distance between every tile, that’s why we’re putting it in the TILE_SIZE part (which essentially means the distance between tiles).

public float getBaseScreenX(int baseX)
{
    return measuredStage.getWidth() / 2 - (resources.TILE_SIZE + BASE_MARGIN)
            * (1 + maxTileBaseX - baseX);
}

Now do the same with getBaseScreenY:

public float getBaseScreenY(int baseY)
{
    return measuredStage.getHeight() / 2 - (resources.TILE_SIZE + BASE_MARGIN)
            * ((maxTileBaseY + 1) / 2 - baseY);
}

 

Run the game again.

Tiles, distanced

Tiles, distanced

Looks much better! We can clearly distinguish the separate walkable bases. Let’s just draw the player somewhere. We’re actually going to rework that part, but I want us to feel good about ourselves. Time for instant gratification!

In our drawBases function, right before batch.end() call, add the following line:

batch.draw(game.res.player,
        sizeEvaluator.getBaseScreenX(1),
        sizeEvaluator.getBaseScreenY(1) + 2);

 

Run the game.

tiles_v3

Oh no! The dreaded ‘cage’ effect, our player looks stuck between tiles. Obviously, this distance won’t do. Let’s reduce the distance between bases by 1/3. Rewrite getBaseScreenY function:

public float getBaseScreenY(int baseY)
{
    return measuredStage.getHeight() / 2
            - ((resources.TILE_SIZE * 2) / 3 + BASE_MARGIN)
            * ((maxTileBaseY + 1) / 2 - baseY);
}

basically, we’re multiplying TILE_SIZE by two thirds, essentially reducing the distance by 66%. Save the code and run it now.

tiles_v4

It does look better, looks more like our hero is standing on one of the bases instead of being stuck between two levels.

Good job, now you have a solid tiles positioning. In the next lesson, I’ll actually address the player movement.

Relevant git commit: https://github.com/vladimirslav/dodginghero/commit/3de79268966817849163eecbc538ba804fa7afd1

Developing Multiplatform Game With Libgdx – part 3 – tile background

Going Further: Background Implementation

So, Vladimir, are we finally ready to actually do something now? Damn right we are! In this lesson, let’s make a background and give our game the pixel-artsy feel. Go to our new amazing GameScreen, and add a new declaration at the start of the class:

private Stage gameStage;

In Libgdx, The stage is used to position UI elements in a nice way and read incoming UI events. It makes our job much easier.

We will initialize it with a new ViewPort. ViewPort limits the area of the screen which we are able to see. Since our game will be run on multiple devices with different screens, we need to make sure that every player will be able to play it, no matter his screen size. Libgdx offers lots of different viewports (you can read more about it here: https://github.com/libgdx/libgdx/wiki/Viewports). We’re going to use FixViewport, this will allows us to make sure that width/height proportions are kept, the main characters are going to be drawn in the middle and the background (which will be made from tiles) is going to be extended depending on the actual size of the screen.

First, let’s introduce a constant values for game width and height (these will be the minimal field width / height and will be extended according to window proportions). Since our tiles are really small, I’m choosing 192 for width and 128 for height (basically, 192 / 16 = 12 tile width, 128 / 16 = 8 tile height.).

public final int STAGE_W = 192;
public final int STAGE_H = 128;

Then, in our GameStage contructor, let’s initialize our gameStage, by passing our spriteBatch and new Viewport as parameters.

The whole part of code will look like this now:

public final int STAGE_W = 192;
public final int STAGE_H = 128;

public GameScreen(DodgingHero _game) {
    super(_game);
    batch = new SpriteBatch();

    ExtendViewport viewp = new ExtendViewport(STAGE_W, STAGE_H);
    gameStage = new Stage(viewp, batch);
}

 

Basically, we tell our gameStage to use our new extendviewport and to scale the screen accordingly. No matter the window size, the coordinates on the screen are always going to be at least STAGE_W x STAGE_H (192×128 in this case).

Splitting game update logics from drawing

Now, let’s split the screen update part from the actual drawing part. Make a new function update:

private void update(float delta)
{
    gameStage.act(delta);
}

The function updates the contents of the stage. We don’t really have any right now, but it will be useful later on. Delta is the time that passed since the rendering of the previous frame. If our stage has any animations, it basically adjusts them accordingly.

Now, let’s add a call of our update function inside the render function. After the screen is cleared (glClear command), issue a draw command to our stage. It will apply the stages camera settings and our further drawing will be done in the coordinates system we requested during constructor call.

Change the values in glClearColor to 0, 0, 0, 1 (Red, Green, Blue, Alpha). This will set the clear color to black, away from annoying red.

@Override
public void render (float delta) {
    update(delta);

    Gdx.gl.glClearColor(0, 0, 0, 1);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

    gameStage.draw();

    gameStage.getBatch().begin();
    gameStage.getBatch().draw(game.res.ground, 0, 0);
    gameStage.getBatch().draw(game.res.wall, 0, 16);
    gameStage.getBatch().end();
}

Finally, in dispose() function, call gameStage.dispose(). The gameStage takes up resources that needs to be manually disposed of when we exit our game. Add super.dispose() call, which is a call to parent’s (DefaultScreen) dispose method (nothing’s there yet, but it’s a good idea to do it nonetheless in case we change something in the future).

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

Run the game. You should see something like this:

How Tiles Look At First

How Tiles Look At First

As you see, the tiles have increased in size! However, if you try resizing the window, the image stretches uncomfortably.

Uncomfortable Resize

Uncomfortable Resize

This is because our viewport is not being updated. In GameScreen, add resize function:

@Override
public void resize(int w, int h) {
    super.resize(w, h);
    gameStage.getViewport().update(w, h, true);
}

This one is called on every resize, effectively resizing our viewport on every change of window size.

Proper Resize

Proper Resize

The image is smaller, but dimensions are at least kept (and not stretched).

Filling the background with tiles

Finally, let us get to the background. In our main game package, create a new one called “graph” In my case, it is com.coldwild.dodginghero.graph

Inside that package, create a new Java Class, named “Background.” Create an empty public constructor (we’ll need it in later lessons).

Then, get to the drawing function. The current goal is quite simple: make a floor background with a wall behind. Let’s introduce the draw method, which will draw the background on the given Stage using Resource pack that we’ve loaded.

public void draw(Stage stage, Resources res){}

Make sure to include the proper stage package (alt+enter when your cursor is on Stage, then select the Stage from libgdx).

The current background idea is simple: fill the top row of the screen with wall tiles and the other parts with floor tiles. We’ll need two for cycles for that. One that goes from top to bottom and the other one inside it that goes from left side to right side. But first, go to Resources and introduce new constant TILE_SIZE (which, obviously, indicates our file size). We will use it for background drawing.

Get back to Background class file. Let’s raw the ground first, and then we’re going to worry about the walls.

public void draw(Stage stage, Resources res)
{
    stage.getBatch().begin();

    for (int y = (int)stage.getHeight(); y >= -Resources.TILE_SIZE; y -= Resources.TILE_SIZE)
    {
        for (int x = 0; x < stage.getWidth(); x += Resources.TILE_SIZE)
        {
            stage.getBatch().draw(res.ground,
                    x, y,
                    0, 0,
                    Resources.TILE_SIZE, Resources.TILE_SIZE,
                    1.01f, 1.01f,
                    0);
        }
    }
    stage.getBatch().end();
}

We’re going from the height of the stage (stage.getHeight) to the lower border and filling every row with tiles. Hold on a second, why are we using such a complicated draw procedure? We’re doing it because otherwise the images will experience tearing on stage resize. (If you figure out a better way – let me know, seriously).

Uncool black lines (poor resize result)

Uncool black lines (poor resize result)

Now, let’s add the Background declaration and initialization to our GameScreen. Add the line    Background bg; near the other declarations. In GameScreen constructor, add bg initialization:

bg = new Background();

 

And finally, we must make a call to bg.draw during our rendering. Add it before gameStage.draw() call. bg.draw(gameStage, game.res);

Run the game. The screen should be filled with floor tiles now. The only thing left now is to add wall tiles.

Right before stage.getBatch().end();, add another for cycle:

for (int x = 0; x < stage.getWidth(); x += Resources.TILE_SIZE)
{
    stage.getBatch().draw(res.wall, x, stage.getHeight() - Resources.TILE_SIZE, 0, 0, Resources.TILE_SIZE, Resources.TILE_SIZE, 1.01f, 1.01f, 0);
}

 

Run the game, see the background that stretches and handles any screen size well. Congratulations! Your background is complete.

Git Commit with code changes from this lesson: https://github.com/vladimirslav/dodginghero/commit/b15fa65097d8d1366955000e3b9dac594a6085cc

More on viewports:
https://github.com/libgdx/libgdx/wiki/Viewports

Developing Multiplatform Game With Libgdx – part 2 – project structure

Heya! The next lesson adresses the project structure and introduces asset packing. The video turned out to be a bit confusing, but the extended transcript is below. Let me know if you have any questions!

What is a game and how we build it

If we think about it, what is a game? Let’s check out the main file, DodgingHero. If we really dumb it down, the game is a cycle of displaying info and getting user’s feedback. The game screen actually renews many times per second (FPS, frames per second, actually indicate this exact value). The render() function in Libgdx is doing exactly this. It cleans the screen (glClear command), then it draws our own things.

The create() function initializes our game. Those are the operations that need to be done once. Mainly, it’s resource allocation. We need to load the textures/sprites only once (the line img = new Texture(“badlogic.jpg”); does exactly that). We also initialize SpriteBatch (batch = new SpriteBatch();), essentially this is the structure that sends the commands to our graphic card.

On the opposite side, we have dispose() function, that is called after our game is done running. We need to free up resources. And this is exactly happens in this particular case: both batch and img are being disposed.

Now that we have a very general idea what’s going on, I’m going to tell you how I usually structure my projects. A good project structure ensures that project maintenance and code updates will go much smoother. As they say, “hours of planning can save you weeks of programming.”

Preparing our art

First thing first, let’s find some art for our prototype. I usually use opengameart if I want to build something fast, and this case will be no exception. After some search, I found http://opengameart.org/content/tiny-16-basic – tileset with some monsters and humans which we can use for our game prototype. I’m going to pick the tiles they have, pick two of them and will use them to show our initial background, repeated the tiles for the background. Essentially I’m doing some extra work here (because the tilesets on the link are already very neatly organized), but I need to show you what’s going on by an example.

In our project root folder (the same folder where we have “android”, “core”, “html” … folders) , let’s make a folder named “assets.” Inside that folder, make another folder, named “unpacked.” From the tileset, cut out one floor and one wall tile (I usually use paint.net, http://www.getpaint.net/index.html for that purpose, but the simple ‘paint’ will do for now).Each image should be 16×16 pixels in size, save them as ground.png and wall.png accordingly. Now, we have two tile sprites, but what do we do with them? For a better performance, all sprites should be put into spritesheets. (It takes time for the graphic card to switch between textures/sprites). It’s really not a problem for modern computers most of the time (for a small game), but I’d rather teach you to do things the ‘proper’ way first. In our Android Studio, go to desktop package and open DesktopLauncher. For Desktop version, we’re going to add texture packing. (Whenever we run desktop version, the sprites are going to be packed into one file. We’ll be able to use this this pre-generated file in the other platforms, like android). The main reason I’m doing it this way is because TexturePacker is not supported by some of our platforms (at least HTML), so I’d rather execute it on Desktop only.

In DesktopLauncher class, add the following private function:

static void Pack()
{
      TexturePacker.Settings settings = new TexturePacker.Settings();
      settings.maxHeight = 2048;
      settings.maxWidth = 2048;
      settings.pot = true;
      TexturePacker.process(settings, "../../assets/unpacked", "packed", "game");
}

Then, right at the start of main() function, add the call to Pack() function, it will look like this now:

public static void main (String[] arg) {
   Pack();
   LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
   new LwjglApplication(new DodgingHero(), config);
}

Loading the art

Select the DesktopLauncher configuration and run our program on it (first launch might take some time). Now go and check the android\assets\ folder. There should be a new directory, “packed” there. Inside that directory, there should be two files: game.png and game.atlas. First one is the picture of two tiles put together. The other one is actually a text file (you can check it out with any text editor, I use Notepad++). It is, like extensions says, an atlas, that describes different sprites in it and coordinates of those sprites in our new big picture.

Now we’ll have to load this atlas. The next thing we do, make a resource class, which will hold the graphical data. Make it in the same package as your main game class. In my case, I right click on “com.coldwild.dodginghero”, choose “New” and pick “Java Class.”

create-new

New Class Creation

Name it “Resources.” This one will be responsible for loading and storing the assets for our game. Go to your new file, and inside Resources class declare the public constructor and TextureAtlas variable gameSprites.

public class Resources {

    TextureAtlas gameSprites;

    public TextureRegion ground;
    public TextureRegion wall;

    public Resources()
    {
        gameSprites = new TextureAtlas(Gdx.files.internal("packed/game.atlas"));
        ground = gameSprites.findRegion("ground");
        wall = gameSprites.findRegion("wall");
    }

    public void dispose()
    {
        gameSprites.dispose();
    }
}

Before constructor declaration, we declare TextureAtlas named “gameSprites”– this is the thing that is going to store our spritesheet  with game characters and background.

dispose() function will be called after the end of our program, to unload all resources that have been used.

We put the initialization of the gameSprites into our constructor with the following line:

    gameSprites = new TextureAtlas(Gdx.files.internal("packed/game.atlas"));

This will take the generated atlas from ourproject/android/assets/packed/ folder. After that, declare two TextureRegion variables, ground and wall right after gameSprites atlas.

TextureAtlas gameSprites;

public TextureRegion ground;
public TextureRegion wall;

 

Great, now let’s assign some values in our constructor. It’s not hard: just add the following lines:

ground = gameSprites.findRegion("ground");
 wall = gameSprites.findRegion("wall");

 

The final result should look like this:

public class Resources {
 
     TextureAtlas gameSprites;
 
     public TextureRegion ground;
     public TextureRegion wall;
 
     public Resources()
     {
         gameSprites = new TextureAtlas(Gdx.files.internal("packed/game.atlas"));
         ground = gameSprites.findRegion("ground");
         wall = gameSprites.findRegion("wall");
     }
 
     public void dispose()
     {
         gameSprites.dispose();
     }
 }

 

Testing what we have

Now ground and wall point to the specific tiles and we’re be able to draw them! Now go to your main class file (in my case it’s DodgingHero.java) in core folder and add new public variable, Resources right at the start of the file. You should initialize it at the start of create() function. Remove the “img” variable and all code related to it from the file. You won’t need it anymore. Let’s just test if we can draw our simple tiles. In dispose function, add res.dispose(); Final result should look like this:

  
 public class DodgingHero extends ApplicationAdapter {
     public Resources res;
     SpriteBatch batch;
 
     @Override
     public void create () {
         res = new Resources();
         batch = new SpriteBatch();
     }
 
     @Override
     public void render () {
         Gdx.gl.glClearColor(1, 0, 0, 1);
         Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
         batch.begin();
         batch.end();
     }
 
     @Override
     public void dispose () {
         batch.dispose();
     }
 }

Now, for the sake of testing our tiles, let’s add simple drawing between batch.begin() and batch.end() inside our render() function:

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

This way we should draw the wall above the ground. The first parameter is the sprite that we want to draw, the next is the coordinates(x, y). Unless you change something, the x coordinates are going from left side of the screen to right side (0->width) and y is going from bottom to top (0->height). 0 means the lowest point of the window. Run the program and you should see both small tiles drawn at the left side of the screen:

gamescreen

Our work in progress!

Adjusting Code Structure

So, Vladimir, are we ready to build the game right here? Hell no. It might seem like a good idea to write all code here, but it will quickly become bloated if nothing is done: imagine that we have to program all the menus and screens in one file. The way I usually do it is to split every separate screen into a separate file and do the rendering/control checking there. The good news is that libgdx allows you to do this quite easily.

In our core/java/com.yourname.gamename package, create a new package called “screens.” There, we’ll add the DefaultScreen parent class, which will store the link to our game object (and will be able to access our resources from there), from which we’ll inherit the next screens.

newpkg

New Package Creation

Right click on the “screens”, package select “new” -> “Java Class.” Name it DefaultScreen, make it implement Screen (public class DefaultScreen implements Screen), add the necessary import from Libgdx by placing map cursor over “Screen” and pressing alt+enter. Press alt-enter again to automatically implement the missing methods. Don’t touch them. (for now). Now, we’ll do two things:

  • Declare a variable of our main class (it will point out to game)
  • Create a constructor for DefaultScreen

That should not take much time:

public class DefaultScreen implements Screen {
 
     public DodgingHero game;
 
     public DefaultScreen(DodgingHero _game)
     {
         game = _game;
     }

 

Very good, our DefaultScreen class is ready.

Now we should implement the actual game screen. Right click on screens package, add new Java Class, let’s name it GameScreen. GameScreen should extend the Default Screen. (public class GameScreen extends DefaultScreen). Press alt+enter to implement the default constructor. Your class should look like this:

public class GameScreen extends DefaultScreen {
     public GameScreen(DodgingHero _game) {
         super(_game);
     }
 }

 

Now go to your main class (in my case it’s DodgingHero), and blatantly cut-paste render() function from there to GameScreen. Change the input parameters to accept float delta (public void render (float delta)). We now have this:

 

public class GameScreen extends DefaultScreen {
     public GameScreen(DodgingHero _game) {
         super(_game);
     }
 
     @Override
     public void render (float delta) {
         Gdx.gl.glClearColor(1, 0, 0, 1);
         Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
         batch.begin();
         batch.draw(res.ground, 0, 0);
         batch.draw(res.wall, 0, 16);
         batch.end();
     }
 }

batch is unresolvable. We need to move it from main class here. Main class should be very small now:

 public class DodgingHero extends ApplicationAdapter {
     public Resources res;
 
     @Override
     public void create () {
         res = new Resources();
     }
 
     @Override
     public void dispose () {
         res.dispose();
     }
 }

 

The last thing to do is to change batch.draw calls. We don’t have res variable here, but we can access it via our game variable. Change batch.draw(res.ground, 0, 0); to batch.draw(game.res.ground, 0, 0); Do the same change with wall. The final GameScreen class should look like this:

public class GameScreen extends DefaultScreen {
 
     SpriteBatch batch;
 
     public GameScreen(DodgingHero _game) {
         super(_game);
         batch = new SpriteBatch();
     }
 
     @Override
     public void render (float delta) {
         Gdx.gl.glClearColor(1, 0, 0, 1);
         Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
         batch.begin();
         batch.draw(game.res.ground, 0, 0);
         batch.draw(game.res.wall, 0, 16);
         batch.end();
     }
 
     @Override
     public void dispose()
     {
         batch.dispose();
     }
 }

Run the game now. Oh no! What do we have in front of us? It’s a black screen! Something went wrong. No worries, the issue is that we moved the code to the separate screen, but did not instantiate it in any way. We need to tell our game to explicitly switch to it. Go back to our main class, and do two things:

  • Change class declaration: public class DodgingHero extends ApplicationAdapter { should change to public class DodgingHero extends Game {
  • At the end of create() function add the following line: setScreen(new GameScreen(this)); Press alt+enter to resolve and auto-import GameScreen class

Run the game now. You should see the red screen with two tiles at the bottom. It might not look as much, but our project has changed a lot. After this, we’ll be able to independently work on specific screens, and adding new screens (like main menu, credits, etc) won’t be a problem.

 

Git Commit: https://github.com/vladimirslav/dodginghero/commit/d02228f6ecb39fdbf98bb4ad54e57b5fb8f29b73

I’ve taken assets from: http://opengameart.org/content/tiny-16-basic, they are made by Lanea Zimmerman. I’ve cut separate tiles so it would be easier to follow (see my git repo).

You might want to check https://libgdx.badlogicgames.com/documentation.html for more details and in-depth descriptions.

Developing Multiplatform Game With Libgdx – part 1

Hey everyone!
After learning things from different tutorials on Internet, I wanted to contribute something. There are lots of tutorials on how to make games. I want to make a tutorial that would go through the whole process: from setting up the work environment to game publishing.

Here’s the video of the project, but in case you’re more into reading, the transcript is given below.

Setting up our project

I’ll be making a multiplatform game that you will be able to run on PC, but my end goal is to publish it on Android. You don’t really need the Android device to follow this tutorial: I’ll explain how to make the game run on your desktop machine, without the need to launch it on Android.

The game idea is simple: on half of the screen, we have a 4×4 field and a character that moves between tiles to dodge enemy attacks. On the right side, there’s an enemy (or group of enemies) that stand and attack the hero (or, rather, some of the tiles).

Game Idea

Game Idea

If anyone promises to make you a gamedev expert simply from doing one tutorial – he’s probably lying. In this tutorial, the end goal is to make a game, but it’s up to you, my reader, to continue perfecting your skills. To me, game programming is a matter of curiosity and experimenting. You’ll have the initial base, but it’s up to you to try new things and experiment by trying out new ideas in the way you want to.

Requirements (In order of installation):

Here’s more info on preparing the environment in case you’re struggling with something: Link to Libgdx Article

Extra tools I’m using:

  • Git Client (For Source control), I’m using the command tools, but you can GUI at https://desktop.github.com/
  • Far Manager (For easier file managing + command line tools), get it for free at http://www.farmanager.com/ If you don’t want to use it, simply use windows explorer + command prompt

Creating Version Control Repository

You can skip this step if you want to, but I strongly advise you to store your code somewhere. Version control, like git/svn/mercurial is a perfect way to do this. Since this is a public project (you will be able to see my code), I will use github to create a project. If you want to focus on private projects, you can use mercurial (hg) or git, in combination with http://bitbucket.org, which provides free storage for your code soruce control.

First, create a new project (repository). Then, pull it to your machine. With git, I use the following command:

git clone http://linktomyrepo

With hg, it’s something similar:

hg clone http://linktomyrepo

Setting Up The Game Project Itself

After you install JDK8 and Android Studio, it’s time to launch Libgdx Setup App.

Gdx Project Setup Screen

Gdx Project Setup Screen

You can name the project however you want to. I’ll name mine Dodging Hero. The package name should be somewhat descriptive. The usual format is com.yourname.gamename, in my case (Since I’m the owner of coldwild games studio), I’m going to name it com.coldwild.dodginghero.

The game class is where the initial setup and high-level launch things happen. The name should not contain spaces.

The destination is up to you, if you are using source control, just pick the folder where you’ve checked out the Git repository. Try not to have destinations with spaces though. Might save you for potential issues later on. Android SDK is the folder of your android software development kit. It should have been installed with Android Studio. In my case the folder is G:\android

In sub Projects, you generally pick the Platforms that you want to support. This will probably require extra work, but we’re not here to rest. Mark “Desktop”, “Android”, “Ios”, “Html”

Extensions are the helping tools/code snippets and libraries that can make development much easier. Put the checkboxes under following options: “Freetype”, “Tools”, “Controllers”. Uncheck everything else. If you hover the mouse buttons on checkboxes, you are told what every tool means, feel free to read up on the other ones on internet and use them wisely when developing your next games.

To explain a bit more of our choices: “Freetype” – this is the font generation, OpenGL (which is basically behind libgdx) cannot simply display True Type Fonts (.ttf) that are used in our operating systems, so we’ll need to generate the images that contain letters in order to. “Tools” are various supporting functions, in our case we’ll need Texture Packer that comes with them. It will allow us to pack all of our smaller images into one big image, which can be faster process by graphic cards. “Controllers” is the controller/joystick support, I think it will be nice if we add it for our desktop if we have time.

Finally, press “Generate.” You might get a warning telling you that android build tools version is newer. Don’t mind it, confirm the build. After that, you’ll get a warning about Freetype extension not compatible with sub module HTML. This is perfectly fine, we’re not going to use it there. Go ahead and say “Yes, build it!” After that, the process starts, the dependencies are downloaded and after some time the generation is complete.

The time has come to import our project into Android Studio. Open up Android Studio, go to “File” -> “Open” -> go to your generated project folder and select “build.gradle” file. After that, the project is being imported. Great, we have our project opened! Congratulations on finishing the first step.

Setting up the Desktop Version

First thing’s first, let’s make testing the game comfortable without having to run it on Android. We’re going to configure libgdx project to run as a desktop application. In Android Studio, go to Run -> Edit Configurations -> Press the ‘+’ Icon (Add new configuration) -> select ‘Application.’

runsettings

Launcher Settings

At the top of the window that appeared, in the “Name” field, replace “Unnamed” to “Desktop Launcher.” (or whatever name you want to, this is purely cosmetical and is there for your own convenience).
In Main Class field, select your “DesktopLauncher” class.
The working directory should be located in YourProjectFoler/android/assets. This is necessary so that our desktop application would be able to read sprites intended for android.
Use Classpath of module” should list “desktop.”
Press OK.

The new option should appear in the dropdown list on top of the screen (near the run button triangle). Choose it.

Then press “Run” button. (The green triangle to the right) or simply press “Shift + F10.” This will build and launch your program. Here’s what you should see:

Great, you’re the boss! You see the initial screen, this is what the template project for libgdx looks like.

result

Initial Screen

Going Further, Project Structure Explained

In the panel on the left, you see the list of our subprojects/packages.

There’s the core module, which contains the code of our game. It is universal for all platforms (Desktop/Android/Ios/Html). But if you go for the desktop folder, you’ll see that it contains DesktopLauncher class. It is responsible for running our game on Desktop Platforms. We’ll be writing the Desktop Specific code here. Same is relevant for all the other platforms. For example, our Android Package Folder will contain ad handling code. Since the mechanism of how ads are displayed will probably be different on every platform, we can’t put Admob’s code (google’s library for displaying ads on Android) into core folder.

Project Structure

Project Structure

That concludes lesson 1. In lesson 2, we’ll try loading sprites and create a simple background.

Git commit: https://github.com/vladimirslav/dodginghero/commit/c37a9292d8bf06551abb8f5db289e1f033d5effc