Developing Multiplatform Game with LibGDX, part 21: Gold Gathering

Lesson 21: Gold Gathering

Last lesson, we’ve added multiple characters and made it possible to pick them. We’ve also introduced  the levelling stats. Unfortunately, since there are no levels, there’s no point of stats.

First thing’s first, how are we going to level up our characters? Well, this is quite easy! They’ll have to push the “Upgrade” button! What’s that? We cannot simply allow player to mash the upgrade button? Fine, we’ll introduce in-game currency to solve the issue of infinite upgrading.

First thing: we’ll add a coin that can be picked on the battlefield. Yes, similar to health / attack. Here’s how it looks (drawn by https://twitter.com/ElenaNazaire):

coin

First, go to our Bonus.java file. Add a new static byte to mark our coin bonus.

public static byte BONUS_TYPE_COIN = 2;

In our “setup” function, add a case for bType == BONUS_TYPE_COIN:

else if (bType == BONUS_TYPE_HEALTH)
{
    set(res.healthBonus);
}
else if (bType == BONUS_TYPE_COIN)
{
    set(res.coinBonus);
}

You’ll notice that coinBonus is not defined yet. That’s allright. Go to Resources class and right under our healthBonus sprite, define a new sprite:

public Sprite healthBonus;
public Sprite coinBonus;

Then, down below, load it the same way you would load healthBonus.

healthBonus = gameSprites.createSprite("health");
coinBonus = gameSprites.createSprite("coin");

Now, make sure we create the bonus in-game. In GameLogic, let’s adjust oru SpawnBonus function. Now if you’ve played the game as much as I did, you can already notice that hearts spawn a bit too much. Let’s reduce their rate and increase the attack spawn rate a bit. Say, 5 out of 8 times we want attacks, 2 out of 8 times we want coins and 1 time we want health bonus.

Replace this part:

bonuses.add(Bonus.Create(fx,
        fy,
        MathUtils.random(3) < 1 ? Bonus.BONUS_TYPE_HEALTH : Bonus.BONUS_TYPE_ATTACK,
        game.res));

With:

byte activeBonus = Bonus.BONUS_TYPE_ATTACK; // use it by default
int rnd = MathUtils.random(7); // 0 .. 7
if (rnd > 6)
{
    activeBonus = Bonus.BONUS_TYPE_HEALTH;
}
else if (rnd > 4)
{
    activeBonus = Bonus.BONUS_TYPE_COIN;
}

bonuses.add(Bonus.Create(fx,
        fy,
        activeBonus,
        game.res));

Use attack bonus by default, then in a few special cases switch it to health and coins. Let’s run the game! You now see that the coins are spawning, but picking them does nothing. Let’s fix that!

Handling the logic behind coins

Great, so what do we do now? How do we make coins work? We need to introduce a separate variable that would store the coins. Let’s handle it in GameProgress.

public static int currentGold = 0;

Add saving/loading at once.

private static final String SAVE_KEY_PLAYER_GOLD = "playergold";

In our Load() function, let’s handle the loading of our gold:

currentGold = prefs.getInteger(SAVE_KEY_PLAYER_GOLD, 0);

And a bit further, in our Save() function, let’s handle the proper saving of the value!

prefs.putInteger(SAVE_KEY_PLAYER_GOLD, currentGold);

Good, the gold is saved, but it is not gathered properly. Time to implement that. Remember, in our GameLogic class, we have the AssignPlayerPosition function? In it, we process the bonus pickups. Let’s alter it to actually handle the coin pickups. Here’s how my full check looks now:

if (currentBonus.getBonusType() == Bonus.BONUS_TYPE_HEALTH)
{
    player.addLives(1);
}
else if (currentBonus.getBonusType() == Bonus.BONUS_TYPE_ATTACK)
{
    enemy.takeDamage(GameProgress.playerDamage);
    if (enemy.getLives() <= 0)
    {
        GameProgress.currentLevel++;
        player.markVictorious();
        eventListener.OnGameEnd(true);
    }
}
else if (currentBonus.getBonusType() == Bonus.BONUS_TYPE_COIN)
{
    GameProgress.currentGold += 1;
}

That should do it.

Displaying the coin amount to the player

Now let’s ensure we display our coins both in GameScreen and CharacterSelectionScreen.

Start with CharacterSelectionScreen. We want to display coins on the bottom left side of the screen. To do this, we’ll show the coin image and write amount of coins we have beside it. Open our CharacterSelectionScreen class. Go to prepareUi() function, and add the following lines to the end of it:

// coin image
Image coinImage = new Image(game.res.coinBonus);
coinImage.setPosition(1, 1);
uiStage.addActor(coinImage);

// amount of coins
Label.LabelStyle textStyle = new Label.LabelStyle(game.res.gamefont, Color.WHITE);
Label coinAmntLbl = new Label("" + GameProgress.currentGold, textStyle);

// set X position to the right of our coin and Y to be exactly in the middle of it
coinAmntLbl.setPosition(coinImage.getX() + coinImage.getWidth() + 3,
        coinImage.getY() + (coinImage.getHeight() - coinAmntLbl.getHeight())/ 2);
uiStage.addActor(coinAmntLbl);

Now let’s add it in our GameScreen now. Since we don’t use Stage in gamescreen for ui elements, let’s just draw it “roughly”. Go to our DrawUi function and add the following code:

batch.draw(game.res.coinBonus,
        gameStage.getViewport().getScreenX() + 2,
        gameStage.getViewport().getScreenY() + 5
);
DrawShadowed("" + GameProgress.currentGold,
        gameStage.getViewport().getScreenX() + game.res.coinBonus.getWidth() + 4,
        gameStage.getViewport().getScreenY() + 10 + game.res.coinBonus.getHeight() / 2,
        gameStage.getWidth() - 5,
        Align.left,
        Color.WHITE);

Pretty self-explanatory, first we draw a coin, then: the amount of gold we actually have. Run the game! You’re going to see the coins on our main screen and in the game, as well as notice how the amount increases after you pick them.

final

This took a bit more time and changes that I’ve expected, so I’ll try to cover levelling in our next tutorial.

Relevant git commit: https://github.com/vladimirslav/dodginghero/commit/6eb79301a6ce8727379edc00b431c6a17b6ff506

Tags:

Android game tutorial, game development, multiplatform game development, beginning game development, gamedev tutorial, libgdx, android gamedev

Leave a Reply

Your email address will not be published. Required fields are marked *