Categories
Uncategorised

GD2 Blog: Week 25

Collaborative Project

As of the 11th of April, I’ve worked on implementing mouse control into the game.

This will be using the Player Controller to help detect mouse inputs throughout gameplay, for this I’ve managed to implement a crosshair and decal that will follow the player’s cursor in-game. The player will be able to use this input to help aim for when they’re able to turn and fire projectiles.

The PlayerController implements functionality for taking the input data from the player and translating that into actions, such as movement, using items, firing weapons, etc.

docs.unrealengine, 2022

Once creating a Player Controller class in the game, I set it as the default Player Controller within the Gamemode’s Blueprint so that once the game begins it will activate.

Within the constructor of our Player Controller, I’ve enabled showing the mouse cursor and then setting the Default Mouse Cursor to a Crosshair (See Figure 1).

Figure 1

Once we preview the game, you’ll notice that we now have a crosshair that follows our mouse’s position (See Figure 2).

Figure 2

Next, we’ll need to create the input functions within our Player Controller’s header file. Using a virtual void, we override SetUpInputComponent and then create some voids based on pressed and released inputs as we’ll be using mouse clicking (See Figure 3).

Figure 3

Within Project Settings under Input, I create a new action mapping labelled “Attack”. This will allow us to use Key Presses and Releases for our inputs (See Figure 4).

Figure 4

Once the Action Mapping is created, we go back into the CPP file of our Player Controller and add in the inputs and void functions (See Figure 5).

Figure 5

To test whether these inputs work, we also include debug messages that’ll appear once the inputs have been pressed (See Figure 6).

Figure 6

Before we actually enter any code, I tried to implement a special material that would act as a decal that appeared under the location of the cursor on any location in the world.

To make a decal from our material, we change its properties from within the details tab. Under Material Domain, we set it to a Deferred Decal – the blend mode is also set to emissive to help our material glow in the dark.

Using RadialGradientExponential, we set a circular gradient for our material by adding values to the radius and density of them (See Figure 7).

Figure 7

For this material, I wanted to create a ring shape. I achieved this was that I had two different Radial Gradients, with one containing a slightly smaller radius than the other determining the thickness of the ring. I think added both gradients into a Lerp, with the smaller ring taking the alpha.

Figure 8 shows what the material looks like once placed into the game world.

Figure 8

Next up we’ll need to implement our decal into the player character’s header file, as shown in Figure 9.

Included is also a FORCEINLINE, which will help return our cursor as a sub object for when we need to use it in our Player Controller.

Figure 9

Within the constructor of the Player Character’s CPP file, I create the decal and set the material of it to a reference of the material I just created before. I set the cursor’s decal size to something smaller as well – included is a Quaternion for setting the cursor’s relative location (See Figure 10).

Figure 10

A Quaternion can represent a rotation about an axis in a 3D space, this will allow our decal to rotate about multiple axis’s simultaneously. It can also help consume less memory.

Quaternions consume less memory and are faster to compute than matrices.

Harold Serrano, 2016

Now in our Player Character’s tick function we’ll set it so that we set the decal’s location to the player controller’s mouse.

Once casting to our Player Controller, we’ll use an FHitResult struct to help us place a hit result under our Player Controller’s cursor. Once we get a result, we then set our Decal’s location and world rotation to it (See Figure 11).

Figure 11

In-game, we can now see that our decal is following our cursor’s position every tick when we move it around (See Figure 12).

Figure 12

Now that there’s a decal that follows the location of our cursor, I’ll be using the FORCEINLINE subobject of our decal from the Player Character to use within the Player Controller’s Attack void.

Figure 13 show’s the function containing a debug message, one the player presses left click on any location within the game, it will set a pointer towards the Player Character and return GetCursorToWorld’s component location – for this to display within the debug message we also convert it to a string.

Figure 13

Once the attack key is pressed, our debug message will display the current location of the cursor. With this, we know that we’re able to pinpoint a certain location each time the left mouse button is pressed (See Figure 14).

Figure 14

Later on in development, I’m hoping to use this for player attacks and projectiles. The plan is to have the player always constantly facing and attacking towards the location of the cursor – this is how most traditional Top Down games handle controls for attacking.

Bibliography

Docs.unrealengine.com. 2022. PlayerController. [online] Available at: <https://docs.unrealengine.com/4.27/en-US/InteractiveExperiences/Framework/Controller/PlayerController/> [Accessed 23 April 2022].

Serrano, H., 2016. Developing a Math Engine in C++: Implementing Quaternions — Harold Serrano – Game Engine Developer. [online] Harold Serrano. Available at: https://www.haroldserrano.com/blog/developing-a-math-engine-in-c-implementing-quaternions [Accessed 23 April 2022].

Categories
Uncategorised

GD2 Blog: Week 24

Collaborative Project

As of the 4th of April, I’ve worked on implementing several parented actors into the game by building off the base projectiles and base pickups. Including some modifiable variables accessed within blueprints to allow for non-programmers to tweak and edit.

First off, I will go over a couple of new projectiles added into the game. As shown on the left is the base projectile, which includes all the default stats for the projectiles (See Figure 1).

The middle is a heavy projectile, which is a child object of the base projectile, it overrides the speed and size from the base projectile to make it much more slower and larger, it even does more damage.

The right has a smaller projectile, which is faster but does a lot less damage than a heavier projectile would.

Figure 1

The base projectile has a integer variable that is able to be set within the blueprint, this being the damage, this is declared within the Base Projectile and carries over to all its children (Figure 2).

Figure 2

Included in the header file of our base projectile are our default values. These are values that we’ll be able to access from the child classes of our projectile. Included is also several virtual voids that determine the projectile speed, size and damage (Figure 3).

Figure 3

We can also use a similar form of inheritance with virtual voids, these enable our child classes to override said functions and to implement their own logic.

“The majority of the inheritance work is by creating a base class that our children can derive from which contains the primary logic that all children are always expected to perform.”

Wojtek, 2021

Another actor within the game I created is a pickup base which utilizes this, it contains a virtual void for an overlap event as well as variables determining the size of the pickup (See Figure 4).

Figure 4

Figure 5 shows what the function looks like within the base pickup, whilst keeping the variables we can override and change what this entire function does in our child actor – the base function contains a debug message and a simple cast to the player character.

Figure 5

In Figure 6, we change and override the function completely. This means that previous code within the function will be overridden with everything written in the child function – we replace the debug message with a different one and include a pointer to the player to add onto their health.

Figure 6

Figure 7 shows both pickups, the base one on the left and the health on the right.

Figure 7

Once overlapped, our different types of debug messages will display. However as we didn’t override the overlap ended function from our basepickup, our Health will keep that function as normal (See Figure 8).

Figure 8

Within our Base Projectile’s constructor, there is a projectile movement component in-which we define our base stats for the projectile’s behaviour (See Figure 9).

Figure 9

Included in some of the component definitions, we include our virtual variables in them, these return our set variables from the header file (See Figure 10).

Figure 10

As most of the projectile movement component is sorted out within our base projectile, we won’t need to reimplement most of the entire code for it again.

Instead we can just easily change what we need by changing the variables in the constructor code as well, which is what our virtual variables will return to the collision component definitions.

For example, we can change the variables in the heavy projectile’s constructor to have a higher size, slower speed and higher amount of damage (See Figure 11).

Figure 11

So far I have managed to set up a good base for creating any different projectiles or pickups off of if necessary, I’ve also managed to make a variable that is editable via blueprints.

However, if my current collaboration team asks for more variables to be editable, I could try and improve this system by making more of them blueprint editable such as the size and speed – this can enable for other people working on the game to easily change these without having to get into the code.

Bibliography

Jolly Monster Studio. 2021. Unreal Engine C++ Fundamentals – Using Inheritance by moving the player & particles along a spline. [online] Available at: http://jollymonsterstudio.com/2021/10/17/unreal-engine-c-fundamentals-using-inheritance-by-moving-the-player-particles-along-a-spline/ [Accessed 12 April 2022].

Categories
Uncategorised

GD2 Blog: Week 23

Collaborative Project

As of the 28th of March, I’ve worked a bit more on the collaborative project using Unreal Engine 4.

This time I decided to experiment with adding multiple checkpoints using an Array to store them all in, this is done by using an ActorIterator to search and loop over the following actors within the world.

Unreal has an in-built Actor Iterator that will loop over all actors in a given world.

Jamie Holding, 2020

For this, I created an actor that’d store all the following checkpoints within the level called a “SpawnPointManager”.

Within the private section of this actor’s header we include a TArray, which is a dynamic list that’ll be storing our spawn points (See Figure 1).

Figure 1

Using “EngineUtils.h” in the header file gives us access to our ActorTIterator that can be used to iterate the actors within the current level of a certain class (See Figure 2).

Figure 2

In our BeginPlay function, we start by having a pointer going towards the game world. This’ll give us access to using “GetWorld()” within our ActorIterator.

Figure 3

We then finally use the TActorIterator to search the world for Spawn Points, the iterator is done using a For Loop and is incremented with the ++ syntax to go towards the next entry (See Figure 4).

Figure 4

To access an entry, we create a pointer for each actor found within the loop by the iterator, we then check if the item we’ve found is NULL – this is to make sure the current item is defined and accessible. Once this step is done, the actor is added to our array (See Figure 5).

Figure 5

To test this array out, I created a function that we can use to select an actor from the array and destroy it – we’ll know if this works whether the selected checkpoint that gets deleted is a specific one.

Within this function, we first check if there are spawns present in the array we just stored our spawn points into with the first few lines of code – if this is equal to 0, we’ll simply return and not use the function.

However, if there are some spawns, we’ll set a pointer to the earliest placed spawnpoint within the level and delete it (See Figure 6).

Figure 6

Within editor view, we can see two spawnpoints placed next to eachother. The first one being our “SpawnPoint_BP” on the left, if this function were to work then it would destroy the spawnpoint on the left once the game starts (See Figure 7).

Figure 7

Once the game is set to play, our first spawnpoint should be destroyed as shown in Figure 8.

Figure 8

Setting our function to destroy the next number in the array should then destroy our second placed spawnpoint within the level as shown in Figure 9.

Figure 9

I feel as if I now have a basic understanding of how to use an array system to account for multiple of the same actors in Unreal. Although this was an experiment to try and learn arrays, I hope to plan on expanding on the checkpoint system using this same array system.

Bibliography

Holding, J., 2020. Unreal Engine 4 – Object & Actor Iterators. [online] Jamie Holding. Available at: https://blog.jamie.holdings/2020/04/07/unreal-engine-4-object-actor-iterators/ [Accessed 10 April 2022].

Categories
Uncategorised

GD2 Blog: Week 22

Collaborative Project

As of the 21st of March, I decided to work more on the collaborative project using Unreal Engine 4.

After implementing some basic movement and trigger activated camera angles, I implemented a health and damage system using projectiles on the player to test it.

As shown in Figure 1, there is a widget that displays the player’s health and a projectile spawner represented as a small cube. Projectiles come out, and once they overlap with the player they deal damage.

Figure 1

First off, I set up a Projectile actor using a sphere component for collision, a projectile movement component and a mesh component (See Figure 2).

“ProjectileMovementComponent updates the position of another component during its tick.”

docs.unrealengine, 2021

The projectile movement component enables me access to plenty unique functions that will allow our projectile to shoot forwards – these are applied every tick within the game.

Figure 2

Included in Figure 3 is the constructor of the projectile. Here we are setting up our collision component’s body and collisions – we also give it an OnComponentHit event which allows us to call a function whenever the projectile collides and hits an object.

There are also settings for our Projectile Movement Component, for the purpose of the game, I set the speeds of the projectiles to low numbers as to make them easier to dodge within a bullet hell setting.

Then there is the set up of the mesh component, this is purposefully left unassigned as we’ll be using blueprints to assign the mesh instead. Very briefly we also set the initial life span of the projectile to 3 seconds, this simply destroys our projectile after a certain amount of time – this will be useful for optimization reasons as to not have too many active projectiles at once for too long.

Figure 3

Once the projectile was set up, I started to work on a spawner that’d spawn projectiles on a looped timer that’d constantly shoot projectiles.

In the header file, I’ve included UPROPERTIES that declare the spawner’s Offset, TSubClassOf (This allows us to select a class that our spawner spawns) and Mesh Component.

Included near the bottom is our Timer Handle, which will be used later on in our CPP file (See Figure 4).

Figure 4

In the Beginplay function, we set a timer that initiates a shoot projectile function. The projectile spawns at a frequency set from a float variable – this being the Projectile Spawn Speed.

The looping part of the timer is set to true, and the first projectile will spawn in 0.5 seconds (See Figure 5).

Figure 5

The shoot projectile function allows our spawner to spawn a projectile at its current location and rotation (This is so we’re able to rotate which direction the spawned projectiles can go in).

Included is a spawn offset, as well as getting the spawn parameters for our projectile (See Figure 6).

Figure 6

Within the blueprint version of our spawner, we’re able to set the TClassActor to our BaseProjectile from earlier.

Figure 7

Next up is the implementation of adding in a widget that simply displays player health, inside the widget display is a couple of text boxes, one has a set binding to it as seen from the highlighted box (See Figure 8).

Figure 8

In the event sheet, we set our bind to cast to the player character, we then get the health variable and link it to the return node (See Figure 9).

Figure 9

In our player’s code, I have an OnOverlapBegin function set up that detects whether the player is being hit by a projectile or not – once hit, the player will lose health and the projectile will be destroyed (See Figure 10).

Figure 10

Within the player’s constructor is a set up for their health and an onDestroyed event for which will get triggered once the player loses all their health (See Figure 11).

Figure 11

So far, player health is kept track by a tick function. It constantly checks every frame to see if the player health is equal to 0, if it is, then the player will be destroyed (See Figure 12).

Figure 12

Once the player is destroyed, this function will then be activated. So far we have a debug message display instead to make sure the code works (Figure 13).

Figure 13

In-game, once the player collides with the projectiles, their health will subtract (See Figure 14).

Figure 14

Once the player’s health drains down to 0, they will be destroyed – once destroyed our debug message will display in the upper left corner (See Figure 15).

Figure 15

So far, I’ve managed to successfully implement a basic system for damage and gameover conditions. Afterwards I may need to consider some more elements, such as respawning the player at checkpoints and include ways for them to refill their health.

Bibliography

Docs.unrealengine.com. 2022. UProjectileMovementComponent. [online] Available at: https://docs.unrealengine.com/4.27/en-US/API/Runtime/Engine/GameFramework/UProjectileMovementComponent/ [Accessed 5 April 2022].