Developing Multiplatform Game With Libgdx, Part 7: Adding Enemy

Adding basic enemy

In the previous lesson, we’ve implemented a possibility to show the effect before the enemy attack. But to actually send attack effects, we need an enemy to do that. Today, let’s try adding the enemy.

First thing: open our character tileset (http://opengameart.org/content/tiny-16-basic) and cut out any enemy that you’d like. It should be a 16×16 sprite. I’m going to save it as spider.png (It’s up to you how you want to save yours, just make sure you load it properly in our resource class).

Spider

Spider

Now go to your project, and open Resources class. In it, declare:

public Sprite enemy;

Initialize it as we initialize the player sprite (make sure to change the region name though!):

enemy = new Sprite(gameSprites.findRegion("spider"));

Next, right beside our Player object (in our logic.objects package), let’s declare another class, called Enemy. It, too, will be derived from Sprite class.

Opposite from player, it won’t have fieldX and fieldY (we’re always drawing our enemy in one place, right?), so in constructor let’s simply set the sprite value to be equal to our spider sprite. For that, we need to pass Resources to our constructor, just to be able to set the enemy sprite properly.

public class Enemy extends Sprite {

    public Enemy(Resources res)
    {
        set(res.enemy);
    }
}

We’ll also need a draw method(), which will take our size evaluator and set the enemy position accordingly.

To make it possible, let’s go to SizeEvaluator class and introduce two new methods that return float values: getEnemyX() and getEnemyY(). Both will accept enemy Sprite and use it’s length to center the enemy at the right half of the screen.

public float getEnemyX(Sprite enemy)
{
    return (measuredStage.getWidth() * 3 / 4) - enemy.getWidth() / 2;
}

public float getEnemyY(Sprite enemy)
{
    return measuredStage.getHeight() / 2 - enemy.getHeight() / 2;
}

In case of X coordinate, we take the coordinates of second half of the screen (first half is measuredStage.getWidth() / 2, and add an half of an half (measuredStage.getWidth() / 4), thus resulting in (measuredStage.getWidth() * 3 / 4). From that value, we’re decreasing enemy width divided by two, so that our enemy will be exactly centered in the middle of the right half.
In case of Y, we simply take the vertical middle of the stage and substract half of enemy height (for the same, exact centering purpose).

Now go back to our Enemy class. Let’s introduce the draw method, which will set position of our enemy sprite in the necessary coordinates and then will call parent’s (sprite’s) draw method. We should get something like that:

public void draw(SpriteBatch batch, SizeEvaluator sizeEval)
{
    setPosition(sizeEval.getEnemyX(this), sizeEval.getEnemyY(this));
    super.draw(batch);
}

A bit of side thoughts: I’ve been reevaluating my Player class, and I think it’s a better idea if we make constructor similar to enemy’s contructor. Pass the resource class to constructor, everything will be set inside the class itself. It’s a good idea to make class modifications inside the class itself. So, let’s rewrite the Player class in this way:
Constructor:

public Player(int fx, int fy, Resources res)
{
    fieldX = fx;
    fieldY = fy;
    set(res.player);
}

Add a draw function:

public void draw(SpriteBatch batch, SizeEvaluator sizeEval)
{
    setPosition(sizeEval.getBaseScreenX(fieldX), sizeEval.getBaseScreenY(fieldY));
    super.draw(batch);
}

It will do the same thing as our enemy’s draw function. Now let’s do some refactoring. Go to GameScreen, remove RefreshPlayer function.

Also, in GameScreen constructor, remove following line:

player.set(game.res.player);

We won’t be setting a sprite in GameScreen anymore, this should be an inner doing of Player class. In our render function of GameScreen’s class, player drawing should look like this:

player.draw(batch, sizeEvaluator);

After that, let’s adjust our GameLogic class. I think it’s fair if we let it store the pointer to our DodgingHero class (which, in turn, will allow to access game resources). In GameLogic class, declare DodgingHero game; variable. Modify GameLogic constructor to actually assign the variable value and pass game.resources to our player Constructor. Here’s how it looks now:

DodgingHero game;

public GameLogic(DodgingHero _game)
{
    game = _game;
    player = new Player(
            MathUtils.random(MAX_BASE_X),
            MathUtils.random(MAX_BASE_Y),
            game.res
    );
    effectEngine = new EffectEngine();
}

This should suffice for now. In GameScreen class, make sure to change logic initialization:

logic = new GameLogic(game);

Try running the game. Try resizing the window. Everything should work fine now.
Let’s finally get to our enemy now. Go back to GameLogic, and, besides our Player, let’s declare our Enemy:

Enemy enemy;

Make the necessary import (alt + enter), there won’t be a choice. Initialize our enemy in GameLogic constructor.

enemy = new Enemy(game.res);

Create a getter that will return the pointer to our enemy object (similar to getPlayer function).

public Enemy getEnemy()
{
    return enemy;
}

The only thing that remains to do is to draw our enemy in our GameScreen! We are not going to do the same thing we did with Player in GameScreen (where we called logic.getPlayer() only once, inside the constructor), because our enemies might change while player remains the same. So simply do this. After our:

player.draw(batch, sizeEvaluator);

call, add

enemy.draw(batch, sizeEvaluator);

Run the game, it should show something like that:

Our Enemy!

Our Enemy!

Now we have an enemy which will attack us!
Don’t worry, I still remember that we made an Effect which will show above the battlefield. We’re definitely going to use it in our next lesson, in which we are actually going to teach our enemy how to attack.
Don’t forger to commit your changes! Also note that you have to run manual git add command every time you add a new file. I actually had to add spider drawing by using „git add” command before commiting.

Here’s the relevant git commit: https://github.com/vladimirslav/dodginghero/commit/1e86d0af762486ad9425e28c82e4e46a59033522

Leave a Reply

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