Class Inheritance

Space exploration can be very boring when you're alone, I think it's time to add some action by spawning enemies around the map.

While thinking about the functionalities needed by the enemy ships, I noted that many of them are the same of the player ship. For instance, both need the arrays for directions, the same functions to move and rotate, etc. This is the typical case where class inheritance comes in handy.
Class inheritance is one of the core concepts of many OOP (Object Oriented Programming) languages. It basically lets you create a base class where all the common behaviours and properties are stored; you can extend that class to other more specialized classes, where you can write methods and store variables that affect that particular subclass only.

We already used this concept in the project, but Unreal Engine managed it for us behind the scenes: all our classes extend the Actor class, so all the basic methods like drawing the mesh, etc. are already written for us.

Now we're going to extend the concept, and this will be the hierarchy of our classes:



This will simplify a lot our playerShipClass and enemyClass, moving all the common stuff in the new base class spaceship, and avoiding duplication of variables and methods.

As you can see, I can use the same principle to differentiate enemies: each one will have its own subclass, with its own logic and pointing at different assets.

I will implement the first, basic enemy for now: I'm going to use the red asset I created before, import it in Unreal and reference it in the class constructor:

Base enemy ship


Constructor for the new class EnemyClass

The main difference between the player ship and enemies is their behaviour: while the player ship waits for user input, the enemies will update their position every turn, using their (very simple) AI.

So let's create an enemy with a fixed position and direction at game start from the PlayerController class:


And then perform its logic when we are in gamestate == 2:

Changes to the Tick() method of MyPlayerController.cpp


Here you can see the power of inheritance: we can add a Logic() method to the enemy class only, and not to the player ship:



In this method, I set the destination of the ship based on its direction, check if it will end up in a tile, and in case it's not (meaning we're going out of the map), simply set the flag "destroy", declaring that the ship is eligible to be destroyed by the PlayerController. Let's go back there and see how it will manage the destruction of the Actors with the flag set to true:



In gameState == 3 we check if the enemy ship exists and if it has finished moving to call the DestroyItems() method and switch back to gameState = 0 (player turn).

Here is the body of the method DestroyItems():

If the enemy ship exists and if its "destroy" flag is set to true, I call the Destroy() method inherited from the AActor class, and set the pointer to nullptr.

All of these methods now take care of the e1 pointer only, but in the next iterations it will be changed to a dynamic list of enemies and resources, managing all the items that can interact with our player ship.

This is the final result, an enemy ship crossing the map and beying destroyed once it reach the opposite side:



Commenti