Developing Multiplatform Game with Libgdx, part 9: losing the game!

Life and Death

Today we have an important day: we actually get to implement an important part of the game: the losing process. To make it simple: if player does not get out of harm’s way in time – he gets punished (his lives are reduced). After the lives drop down to zero: the game ends. Since we don’t have any fonts attached, we don’t have a way to inform the player about this. So we’ll just exit the game. Yes, pretty abruptly. We’ll deal with this later. Also, don’t freak out. I’ve replaced my horribly-drawn tiles with the ones that my girlfriend has drawn for me. You can get them in the project repo.

Modifying our Effect

First, we need to modify our warning effect so that it would inform our logic that it is actually over (timed out). In our WarningEffect class, add a public interface:

public interface WarningEffectListener
{
    public void OnEffectOver(WarningEffect effect);
};

Declare the variable which will point to the actual interface.

private WarningEffectListener listener;

Modify our init method and Create function to include the interface parameter.

public void init(int x, int y, EffectEngine parent, Resources res, WarningEffectListener _listener)
{
    super.init(parent);
    listener = _listener;
    resources = res;
    fieldX = x;
    fieldY = y;
}

static public WarningEffect Create(int fx,
                                   int fy,
                                   Resources res,
                                   EffectEngine engine,
                                   WarningEffectListener _listener)
{
    WarningEffect effect = warningPool.obtain();
    effect.init(fx, fy, engine, res, _listener);
    return effect;
}

Also, make fieldX and fieldY variables private and create a getter for them.


public int getFieldX()
{
    return fieldX;
}

public int getFieldY()
{
    return fieldY;
}

Great, this part is done. Now we only have to call it as effect ends. Modify our update function:

@Override
public void update(float delta)
{
    super.update(delta); // pass the time change
    // add an aditional security in order not to call death trigger twice
    if (timeAlive > WARNING_TIME && isAlive)
    {
        isAlive = false;
        if (listener != null)
        {
            listener.OnEffectOver(this);
        }
    }
}

To expand upon this: we’ve added additional check in our condition: isAlive should be true, this is to prevent double calls of OnEffectOver.

If listener has been set (let’s leave an option not to set it, might be useful later) – call OnEffectOver and pass the pointer to this effect.

Cool, we can call our effect over checks, but we can’t reduce player’s lives yet. Because he does not have them defined. Go to our Player class. Add a private integer field that indicates the lives of our player. In our constructor, let’s pass the amount of lives our player will have.

private int lives;

public Player(int fx, int fy, Resources res, int _lives)
{
    lives = _lives;
…

Great. Now the two things we need to do is: get the amount of lives player has and reduce the lives of the player. This should not be too hard:

public void takeDamage(int amnt)
{
    lives -= amnt;
}

public int getLives()
{
    return lives;
}

Done! Now the only thing left is to modify our logic. Create a constant DEFAULT_PLAYER_LIVES (private static final int) and set it to three. Adjust the player initialization to pass amount of lives.

Make GameLogic implement WarningEffectListener. It’s quite simple:

public class GameLogic implements Enemy.EnemyAttackListener, WarningEffect.WarningEffectListener {

Press alt+enter to implement the missing method. It will be very simple. We will compare the effects position to player’s current position and if they match – reduce the lives of a player.

@Override
public void OnEffectOver(WarningEffect effect) {
    if (effect.getFieldY() == player.getFieldY() &&
        effect.getFieldX() == player.getFieldX())
    {
        player.takeDamage(1);
        if (player.getLives() <= 0)
        {
            Gdx.app.exit();
        }
    }
}

Now run the game and try to get hit intentionally 3 times. The game will exit. Not pretty (yet), but it shows the point.

Relevant commit: https://github.com/vladimirslav/dodginghero/commit/39613aa57334e37f57817c4ac53059575ad3c4f7

Leave a Reply

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