Hyper Casual Game
As of the 7th of February, I’ve added some of the final mechanics towards my Hyper Casual Game.
The following that have been added are several mechanics to help aid the player such as Bounce Pads and Extra Lives to collect, the lives will serve as a goal for the player to earn so that they can continue playing the game.
In addition there is a UFO enemy in the game, using Unreal Engine 4’s socket system, this UFO moves across the screen and contains a static model with a socket attached to it – once it collides with the extra lives, it will steal them and attach said life to their socket. The UFO also has a custom 3D model that I made within Blender.
As showcased by Figure 1, this is the 3D model I created for the UFO in Blender. This was exported as an FBX model and then imported into Unreal Engine 4 as a Static Mesh.
Once imported as a Static Mesh, I was able to assign a material and socket to the model. I gave it the same colour changing material as the blocks and created a new socket for it, positioning it below the saucer (See Figure 2).
The Saucer is a child of the Blocks I created before, so it inherits the same characteristics that make it move and have hit points. It however has a unique function for firing projectiles.
Within its header file I defined two functions for it, one for it to spawn the projectiles at an offset so it could spawn below the saucer rather than inside it, another is a TSubclassOf function which gets an object’s class (This being the projectile we want to fire) and assigns it as “ProjectileToSpawn” (See Figure 3).
Within the CPP file of the UFO is a void function that gets called when the UFO fires a projectile, this essentially gets our “ProjectileToSpawn” and the current location of the UFO on where to spawn the projectile from.
Using this, we then set the spawn offset to appear 10 units away from the UFO as to not make the projectile spawn inside.
We then get the world of our game and then call in a struct called FActorSpawnParameters, which is passed onto SpawnActor functions – with this we can set the owner of the projectile to the UFO and set it as an instigator if it were to do damage.
“Struct of optional parameters passed to SpawnActor function(s).”
We then call the projectile class and set it to be spawned into the world using SpawnActor, we also include the variable for the location it spawns in and set the rotation of the projectile to be directly downwards.
Afterwards, is a debug message to help confirm to us that the UFO has in fact fired the projectile (See Figure 4).
Within game, the UFO is able to steal Extra Lives from the player. How this is achieved is by using a socket, within the code of the Extra Life is an overlapbegin function that has set triggers for certain actors like the Ball or UFO.
As seen in Figure 5, using casts, the Extra Life will call a function called “GiveLife” if touched by the ball and displays a debug message to confirm the event happening.
Afterwards is the part of the function that is enabled if the actor collides with the UFO, if it does, then it has a constant set calling UStaticMeshSocket which gets the Extra Life and Socket of the UFO’s model. Once collided with the UFO, the actor is then attached to the socket of the saucer (See Figure 5).
As displayed by Figure 6 is an in-game representation of a UFO firing a projectile and then collecting an Extra Life. As the Extra Life overlaps with the UFO it is then attached to its socket.
The projectile of the UFO has most of its components hard-coded, meaning that its mesh, material and movement were made within CPP.
Figure 7 shows the header file of the projectile. Contained within it is the collision component, movement component, mesh component and material instance dynamic as well as a light component.
In Figure 8 is the constructor code of the projectile. At first we create the body of the projectile, then set up a UProjectileMovementComponent for the projectile which allows us to give it settings to change its max speed, initial speed and gravity – this component essentially gives us variables based on how projectiles can move in-game.
“ProjectileMovementComponent updates the position of another component during its tick.”
Afterwards we include a light component to the projectile, this is so that once it is seen in-game, it is easily readable and visible for the player to see. The intensity is set to 50,000 and is given a distinct purple color.
Afterwards, we add a mesh to our projectile component. We first get the reference to the mesh we want to use in our game’s files using static ConstructorHelpers and finding the directory of the object we want to use. Afterwards we check to see if the mesh has succeeded in loading, and set the current component to the chosen mesh – we then attach this to the projectile’s collision component.
Another use with static ConstructorHelpers is that we can also get materials. For this we simply get a material called “M_ProjectileColor” and check to see if the material has been successfully loaded similar to the mesh (See Figure 8).
As the mesh and material has been hard-coded, the actor shows up exactly as it would look in-game without its blueprint copy (See Figure 9).
Within the game are the addition of extra lives, unlike the projectile their mesh and components were created within blueprint. Within CPP we will be calling these (See Figure 10).
Using “auto”, we are able to call these components to set them up within the constructor. In CPP terms, auto is able to direct the compiler to use the expression of a declared variable and to deduce its type. In this instance we are deducing it from blueprint to our CPP code.
“The auto keyword specifies that the type of the variable that is begin declared will automatically be deduced from its initializer and for functions if their return type is auto then that will be evaluated by return type expression at runtime.”
(Vrundesha Joshi, 2018)
Figure 11 shows the beginplay function of the Extra Life, within it we are using auto to get the blueprint components and to assign functions and or materials on them. For the Extra Life, I gave the SphereCollision an overlap function and the Sphere mesh a dynamic material.
The material assigned to the sphere is similar to the block one, where it as two colours linked to a lerp with a Blend scalar parameter serving to change the colours in-between each other (See Figure 12).
The Extra Life uses the tick function to change this color, by getting the blend variable and setting it to a float variable that constantly changes each tick by using the time of the world.
Included is the GiveLife function mentioned earlier, which calls a cast to the paddle using UGameplayStatics to get the player pawn within the game world. This simply adds a life onto the player’s lives variable and then destroys the extra life once it is collected (See Figure 13)
As seen in Figure 14 is the Extra Life’s sphere material changing colour in-game.
Contained within the game, is also a new bounce pad actor. This simply has an overlap function that triggers once it is overlapped by the ball (See Figure 15).
These are placed in the corners of the map, and are supposed to assist the player if they manage to hit them by giving their ball a boost to help break any further blocks.
What makes it unique is that the bounce pad extends outwards to push the ball to apply force towards it more naturally rather than through code. This is done by setting it a start location and a total distance for it to travel towards. In the header file are several protected variables that determine the direction, total distance, current distance and start location (See Figure 16).
Within the beginplay function, we get our start location by getting the actor’s current location when the level begins as well as the direction we want it to travel towards – which will be going upwards from its up vector. The total distance is then where the direction’s size is returned to add up the total distance needed for the bounce pad to travel.
We also include a debug message with this variable to help specify if the amount of total distance it needs to go is correct.
We then get a normalized copy of the direction’s vector using GetSafeNormal which checks if the vector length is too small to safely normalize or not. The current distance is then set to 0.0f.
Each tick, we then set the current distance to our actor’s current location minus the start location. If the current distance is less than the total distance whilst bounce is enabled, then the actor will move towards their targeted location. Else if the current distance is higher, we then revert the location of the actor to the start location as it has finished reaching its total distance (See Figure 17).
As for my progress made for this week, I feel as if I did a good job getting the final mechanics for my game in. I’ve also tried further learning how I could utilize actor components that were created either from blueprint or hardcoded in CPP with what I’ve done with the Extra Life and Projectile.
Creating a 3D model especially for the UFO was a fun task as assigning it a socket to help attach an extra life gave me some experience has to how the process of using sockets worked when using entirely new custom models. I hope to expand on this in the future with more complex models.
What needs to finally be done is to implement a basic menu which allows the player to restart and exit the game, it will need a proper game over condition for when the player fully runs out of lives as well.
(Docs.unrealengine.com. 2022) FActorSpawnParameters. [online] Available at: https://docs.unrealengine.com/4.27/en-US/API/Runtime/Engine/Engine/FActorSpawnParameters/ [Accessed 11 February 2022].
(Docs.unrealengine.com. 2022) UProjectileMovementComponent. [online] Available at: https://docs.unrealengine.com/4.27/en-US/API/Runtime/Engine/GameFramework/UProjectileMovementComponent/ [Accessed 11 February 2022].
(Joshi, V., 2018) What does an auto keyword do in C++?. [online] Tutorialspoint.com. Available at: https://www.tutorialspoint.com/What-does-an-auto-keyword-do-in-Cplusplus#:~:text=The%20auto%20keyword%20specifies%20that,return%20type%20expression%20at%20runtime. [Accessed 11 February 2022].
(Docs.unrealengine.com. 2022) UGameplayStatics. [online] Available at: https://docs.unrealengine.com/4.27/en-US/API/Runtime/Engine/Kismet/UGameplayStatics/ [Accessed 11 February 2022].