Categories
Uncategorised

GD2 Blog: Week 18

Hyper Casual Game

As of the 31st of January, I’ve added much more towards my Hyper Casual Game. The game now features a lives system, as well as infinitely spawning blocks.

There is also some optimization measures included, such as an actor that helps set the boundaries of where objects can exist and be deleted if outside of – this is so that the infinitely spawning blocks won’t take up too many resources if they leave the game area.

As represented by the highlighted box, this is the boundary area all in-game objects will be in (See Figure 1).

Figure 1 (Personal Collection)

The code to do this was fairly simple, using an OnOverlapEnd function, we can determine when an object is no longer overlapping the boundaries and thus we can get rid of (See Figure 2).

Figure 2 (Personal Collection)

There is also a debug message that displays using an FString which allows us to take the value of the OtherActor and insert it into an %s parameter, we then print this off using FString (Figure 3). This debug message helps keep track of what actor goes off-screen.

(docs.unrealengine, 2022)

Figure 3 (Personal Collection)

I’ve also added a child class to the blocks, being a faster and more smaller version of it.

Going over several changes since last time, the blocks main variables that determine their amount of hit points and speed are now changed into virtual variables in the header file as to make overriding them in the child classes much easier (See Figure 1).

Figure 5 (Personal Collection)

On the left of Figure 5 is a child class of block. By overriding the virtual variables from the parent class as identified on the right, I am able to change their speed and hit points (See Figure 5).

Figure 5 (Personal Collection)

Within the Block.cpp, I added in in a new variable called BlockHP which replaces the original hit points variable. This essentially sets its health of the block to whatever the amount of hit points are declared by the virtual variable (Figure 6).

Figure 6 (Personal Collection)

Whilst creating a blueprint class of the child blocks, I’m also able to set and change their own meshes within the blueprint.

This is done by having a setting their UPROPERTY to be visible anywhere and also be writable in Blueprints, this is as so to make adding and resizing meshes to the actors much more faster and efficient. Figure 7 shows the class of UStaticMeshComponent being mentioned in the header file of the block.

Figure 7 (Personal Collection)

As our new block type is a child of this parent actor, this carries over into their blueprint and thus requires no need to rewrite the function in their header file (Figure 8).

Figure 8 (Personal Collection)

For the game, I’ve also implemented some actors to the sides of the level which spawn in the incoming blocks – essentially acting as the block spawners (Figure 9).

Figure 9 (Personal Collection)

This is done using “TSubclassOf”, which enables for us to assign an actor for our spawner to spawn.

“Let’s imagine that you are creating a projectile class that allows the designer to specify the damage type. You could just create a UPROPERTY of type UClass and hope the designer always assigns a class derived from UDamageType or you could use the TSubclassOf template to enforce the choice.”

(docs.unrealengine, 2022)

Within the blueprint of our spawner, we’re also able to set which type of actor the spawner will use (Figure 10).

Figure 10 (Personal Collection)

Within the CPP code of the spawner, a looping timer is set as soon as the game begins to start.

The amount of time for each loop is taken from the virtual float BlockSpawnFrequency, once the timer is up it will activate our BlockOnSpawn function.

This then calls our SpawnBlock function which actually gets the spawn parameters of our actor and spawns it at the following location – those of which being from the spawners current location and rotation (Figure 11).

Figure 11 (Personal Collection)

As shown by Figure 11, there are two spawners on either side of the level. Both are pointing in different directions as well as to which way the direction of the spawned blocks will move.

Figure 11 (Personal Collection)

Figure 12 shows what this looks like in-game, as the blocks spawn, they are able to travel towards the direction the spawner was facing. Spawned blocks also become deleted once they are no longer overlapping the level boundary as shown by the debug code.

Figure 12 (Personal Collection)

Using a bit of blueprint code, I’ve also created a type of material for the blocks using a blend parameter which will change depending on the amount of health left in the block. Figure 13 shows me connecting two color parameters to a lerp, which is also connected to our blend.

Figure 13 (Personal Collection)

In the blueprint code of the blocks, there’s an event tick function that will automatically change the blend parameter of the material to the corresponding block, this is done by using a Set Scalar Parameter on the material and naming our Blend.

We then get the block’s health variable for the value of the parameter, it is also multiplied by a float which makes the colour changes more drastic (Figure 14).

Figure 15 (Personal Collection)

In-game, once the blocks lose health, they will dynamically change colour as shown in Figure 16. This is a visual guide to help the player to discern how much health a certain block has, and makes it overall easier to track which blocks to go for.

Figure 16 (Personal Collection)

One instance I did not detail before was that the player’s pawn was controlled by using a PawnMovementComponent.

To get the player character’s paddle moving, I used one of the official Unreal Engine 4 C++ tutorials as a reference for this – This tutorial being called Components and Collision:

https://docs.unrealengine.com/4.27/en-US/ProgrammingAndScripting/ProgrammingWithCPP/CPPTutorials/Components/

This tutorial shows you how to connect specific components towards your actors or pawns, in this instance I created a Pawn that utilized a PawnMovementComponent for its movement and collision settings (Figure 17).

Figure 17 (Personal Collection)

The reason why you’d do this is that the component already has built-in features that you could utilize, for optimization purposes having components separated from the main Pawn also reduces the amount of clutter in the main Pawn’s code.

“Pawn Movement Components have some powerful, built-in features to help with common physics functionality, and are a good way to share movement code between many Pawn types.”

(docs.unrealengine, 2022)

The code in Figure 18 is our customized Pawn Movement Component, this makes sure that the Pawn will move smoothly around the world, sliding off surfaces and having a maximum speed of 1300 units.

The features present in this component are; ConsumeInputVector, SafeMoveUpdatedComponent and SlideAlongSurface.

ConsumeInputVector reports and clears the value of a built-in variable used to store movement inputs.

SafeMoveUpdatedComponent uses physics to move the Pawn while respecting solid barriers.

SlideAlongSurface handles calculations and physics involved with sliding smoothly along collision surfaces.

Figure 18 (Personal Collection)

In order to use the custom component, we add a variable to the Pawn class to keep track of it – alongside this are also other components that define the paddle’s mesh and collision body (Figure 19).

Figure 19 (Personal Collection)

We then create the Pawn Movement Component and associate it with our Pawn – alongside this are also many of the other variables being set up. In my constructor this is identified as PaddleMovement (See Figure 20).

Figure 20 (Personal Collection)

Pawns have a function called GetMovementComponent, these are used to enable other classes in the engine to access the Pawn movement Component that our Pawn is using.

The function will be overridden as to return our custom Pawn Movement Component inside the header file (Figure 21).

wordpresssucks
Figure 21 (Personal Collection)

In our CPP file, we then add the definition of our overridden function as shown by Figure 22.

Figure 22 (Personal Collection)

As shown by Figure 23 and 24, this is how the player input is affected by the paddle movement. Figure 23 sets up our PlayerSpeed variable to the current AxisValue inputted by the player (This can range from 1 if going right, -1 if going left or 0 if nothing is being inputted).

Figure 24 takes place within the tick function of our paddle, so movement is constantly being applied. Our paddle movement uses acceleration, and is clamped to go only inbetween -1.0 and 1.0 for its full values. These values are slowly added or decreased up by the player acceleration in order to create movement that feels weighty – this all depends on which direction PlayerSpeed is moving in.

Figure 23 (Personal Collection)
Figure 24 (Personal Collection)

For this week, I feel as if I’ve learnt to implement some useful methods into Unreal such as using Blueprints alongside C++ and having separate components to apply to my actors. I feel as if the game is almost near a complete state as well, and I hope to add in some more mechanics and necessary features such as a menu and score system.

Bibliography

(Docs.unrealengine.com. 2022) FString. [online] Available at: https://docs.unrealengine.com/4.27/en-US/ProgrammingAndScripting/ProgrammingWithCPP/UnrealArchitecture/StringHandling/FString/ [Accessed 4 February 2022].

Docs.unrealengine.com. 2022. TSubclassOf. [online] Available at: https://docs.unrealengine.com/4.27/en-US/ProgrammingAndScripting/ProgrammingWithCPP/UnrealArchitecture/TSubclassOf/ [Accessed 5 February 2022].

Docs.unrealengine.com. 2022. Components and Collision. [online] Available at: https://docs.unrealengine.com/4.27/en-US/ProgrammingAndScripting/ProgrammingWithCPP/CPPTutorials/Components/ [Accessed 5 February 2022].

Leave a Reply

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