Categories
Uncategorised

GD2 Blog: Week 28

Collaborative Project

As of the 2nd of May, I’ve worked on the player character more by implementing FindLookAtRotation into their code so that they’re able to aim and look towards the cursor. As well as starting on several actors used for levels such as doors and a spinning projectile spawner.

I’ve also guided some of the team onto what I currently need for my game build. In-which, I asked for some models to block out the level with and some widgets that declare the game’s main menu, the ability to pause and level opening and closing screens.

They have been able to provide some assets for the game such as models and several widgets. Figure 1, 2 and 3 show some early stage widgets made by Jerome. Including a menu, pause and end screen.

Figure 1
Figure 2
Figure 3

As well as new widgets, assets created by Jordan have also been imported into the game – although not textured yet, I plan to use these ones in level blockouts (See Figure 4).

Figure 4

As for what I’ve been working on, I’ve improved the current player character by making them turn towards the cursor in-game.

This was fairly simple as I had to only use “FindLookAtRotation” from the Kismet Math Library to assign an FRotator variable. I then set the actor’s relative location to rotate only the Yaw of the player, so that they could only rotate left and right (See Figure 4).

Figure 4

What this does is simply find a rotation for an object using a start position and then pointing it towards a targeted one – in this instance, the start position was the actor’s location, and the target for them to look at was the Trace Hit Result for underneath the mouse.

“Find a rotation for an object at Start location to point at Target location.”

(docs.unrealengine, 2022)

However, there was one issue using this. As the decal would rotate alongside the player and thus change it’s position from the intended space underneath the actual mouse cursor (See Figure 5).

Figure 5

To fix this, I had to set the rotation and location of the decal to absolute ones instead. What this does is set parts of a component to have their location, rotations and even scale to be relative to the game world rather than the parent.

“Set which parts of the relative transform should be relative to parent, and which should be relative to world”

(docs.unrealengine, 2022)

Figure 6 and 7 show the result of me setting enabling absolute location and rotations on the decal.

Figure 6
Figure 7

For the player, I’ve also implemented an ammo system for them. The player starts with a max amount of bullets, and has a boolean to determine whether they’re currently reloading or not (See Figure 8).

Figure 8

Within the code to fire projectiles, I modified it to only fire if the player has more than 0 bullets present.

In-game, the player will have the ability to fire a certain amount of bullets as fast as they want, once they fire the first bullet the game will set the reloading boolean to true and thus set a timer to trigger a function known as “ReloadAmmo()” that resets the player ammo count to their max ammo and then set reloading to false (See Figure 9).

Figure 9

In-game, this enables the player to fire their ammo out as fast as they can click, however they’ll have to wait out on the timer for their ammo to fully restock.

This may give a sense of strategy to the game in that firing slower at a lower pace allows you to consistently keep in stock with ammo, however for certain situations you may choose to fire very fast but have to wait (Figure 10).

Figure 10

Starting on the first level, I set out a plan for what I intend to do. Later on I’ll be able to fill this with some more assets. The first level will contain several rooms where the player must avoid some projectile shooters in order to reach two switches that’ll open the level exit (See Figure 11)

Figure 11

Figure 13 shows a room using a standard projectile shooter made from awhile ago, once the player enters the room, the projectile spawner will activate – however it will deactivate once they leave the room.

This room is just a projectile spawner shooting down a straight hallway that the player must get through without being hit, there are several pockets of cover the player can take to shield themselves from oncoming bullets – their timing to reach these must be adequate.

Figure 13

Within the header file of our camera trigger, I’ve included an actor reference that takes from projectile spawners. This is so that we can set up a trigger area to activate a certain projectile spawner (See Figure 14).

Figure 14

Within the CPP file of the camera trigger zone, the projectile spawner is referenced will have their “IsActive” bool set to either True or False depending on whether the player is currently in the trigger zone or not (See Figure 15).

Figure 15

The reason why I’ve done this is to keep off-screen projectiles from spawning and taking up a lot of possible space during gameplay: for optimization reasons, the player won’t be able to see these projectiles if they were not in their rooms so they are disabled until they enter.

As seen in Figure 16 is a new type of projectile spawner, it is a child of the projectile spawner blueprint and has a “RotationMovement” component that allows it to rotate constantly and fire bullets in a spiral-like pattern (See Figure 16).

Figure 16

This version of the projectile spawner also spawns the light projectiles and a much lower projectile spawn speed than the regular projectile spawner (See Figure 17).

Figure 17

As we’re now getting onto putting levels together, the team will be focusing on getting our first couple of levels for the game done. Although time constraints may prove to be an issue and we might not be able to fully finish our game before the 20th.

I plan on making sure the rest of the group will be working towards the game, as well as polishing and refining it as much as possible once finishing my current tasks – so far my goal is to add more mechanics and levels.

Bibliography

Docs.unrealengine.com. 2022. UKismetMathLibrary::FindLookAtRotation. [online] Available at: https://docs.unrealengine.com/5.0/en-US/API/Runtime/Engine/Kismet/UKismetMathLibrary/FindLookAtRotation/ [Accessed 10 May 2022].

Docs.unrealengine.com. 2022. USceneComponent::SetAbsolute. [online] Available at: https://docs.unrealengine.com/5.0/en-US/API/Runtime/Engine/Components/USceneComponent/SetAbsolute/ [Accessed 12 May 2022].

Categories
Uncategorised

GD2 Blog: Week 27

Collaborative Project

As of the 25th of April, I’ve looked into opening up a GitHub so my group for the collaborative project can test out the game as well as make changes and additions towards it.

Once adding the game build onto GitHub, many of the artists within the team will be able to push and then provide their own assets into the game. I’ve also started to update my notes within my Trello board to help show others my progress on the project.

Unreal contains built in support for GitHub using Source Control. This’ll be what the rest of the team can use to update a single build of the game by adding in their own assets, blueprints and etc.

“The Unreal Editor has built-in support for source control packages. Source control is used to manage changes over time to code and data, and enables teams to coordinate their game development efforts.”

docs.unrealengine, 2022

Opening up the game project, I go onto the top bar of the editor and connect to “Source Control” (See Figure 1).

Figure 1

To connect the project, I set the provider as Git and simply initialized the project with it (See Figure 2).

Figure 2

Using GitHub Desktop, for our game to show up in the repository. I’ve added an existing repository which was directed towards the folder of the game (See Figure 3).

Figure 3

With this, I am able to publish the build publicly. To test to see if this worked, I added in a new material and pushed it as a new update towards the build of the game I’d uploaded – the changes I’ve made would show up as well as containing a list of all the new assets added in (See Figure 4).

Figure 4

To test whether this can work for the other team members, I got Liz from the Collaborative Team to add in player sprites as well as any other changes into the project and to push them onto the current build of the game on GitHub.

Before pushing their build of the game, they made a comment on the exact changes they had made towards the project (See Figure 5).

Figure 5

Once they’d pushed the build to the master build, the GitHub page updated to their current version of the game (See Figure 6).

Figure 6

I’d downloaded and opened the build from the GitHub page, I was able to see all the new changes they’d made. As shown in Figure 7, Liz implemented some new player sprites as a test.

Figure 7

Following this progress, I contributed to the group’s Trello board and marked the progress I’d made setting up the GitHub.

I’ve also added in what I’m currently working on so the team is able to check my current progress as well (See Figure 8).

Figure 8

With the GitHub and Source Control now set up, the rest of the artists within the team can now try and import their own assets into the game to try and see what their art looks like.

Indie developers will also be able to set up Blueprints and modify the game as well, building on top of the base I’ve provided.

Bibliography

Docs.unrealengine.com. 2022. Source Control. [online] Available at: https://docs.unrealengine.com/4.27/en-US/Basics/SourceControl/ [Accessed 7 May 2022].

Categories
Uncategorised

GD2 Blog: Week 26

Technical Proposal

As of the 18th of April, I’ve conducted some research into my topic for my Technical Proposal. For my proposal, I’ll be doing an investigation into using Virtual Reality and its uses for possible enhanced interactions during gameplay.

What this will be covering is how Virtual Reality games handle interactions within the game, and to what extent players are able to do so. This can depend on what control schemes the game uses, as for Virtual Reality there is a multitude of different ways this can be handled.

The most common methods of interactability in Virtual Reality consist of; Selection, Manipulation and Locomotion.

Using selection, the player is able to interact with a UI or object via their controller input. This involves usually the player pointing towards something directly and then allowing them to interact with said object.

“In its simplest form, selection involves telling the system which object or UI element the user wishes to interact with. Once selection is confirmed by user, the selected entity becomes the focus of further interaction inputs by the user.”

FutureLearn.com, 2022

An example of a Selection can be seen in Figure 1, where a player is using a ray-cast from their controller to point towards a sphere to select it. These are typically used for objects that are far out, and usually out of physical reach for the player – this makes it easier and more accessible.

Laser pointer
Figure 1, FutureLearn.com (2022)

Figure 2 shows another example of Selection within Virtual Reality, these are known as Gestures. With this, hand gestures are captured by the headset and allow the player to directly interact and grab objects that they can reach – many headsets may also support native hand-tracking which allows for this to be accurate and possible.

Gesture based
Figure 2, FutureLearn.com (2022)

Gesture based interactions within a virtual reality game can also lead to a much more immersive and natural experience for the player. A more natural feeling experience can also help users with physical disabilities to interact with games much more easier.

“Gesture interaction is intuitive, natural, and flexible. Therefore, it is also very important for some users with physical disabilities, such as visual impairment and hearing impairment, to interact through gestures.”

Beijing Key Laboratory of Human-Computer Interaction, 2022

Manipulation within Virtual Reality allows the user to manipulate selected entities in a multitude of ways, this can range from orient an object or move it – the choice of technique depends on the available capability of the controllers, which can range from simple controllers with scroll-wheels to gestures like pinching and stretching.

“This set of interaction actions occurs once an object is selected by the user.”

FutureLearn.com, 2022

Figure 3 shows an example of a user with a HTC Vive dual-hand controller interacting with a virtual environment to manipulate 3D objects as shown on the right. The left is also an example of a user-defined gesture using the Vive controller.

figure 1
Figure 3, Human-centric Computing and Information Sciences (2018)

Locomotion involves the use of controllers to navigate throughout a virtual environment.

Although one problem with this method is that it tends to cause sickness due to a discrepancy between what the user detects through vision and the movement-related systems within their inner ear detect (Ivy Wigmore, 2018).

“This set of interaction techniques enable user movement within the virtual world. They re-position or re-orient the user in the virtual world”

FutureLearn.com, 2022

One method of locomotion within Virtual Reality is teleportation, where a user can point to their destination and automatically move there as seen in Figure 4.

Teleportation base
Figure 4, FutureLearn.com (2022)

The accessibility of this method allows the player use this movement method to avoid any motion sickness, or perhaps are also restricted by the physical limitations of their room scale.

Another method for locomotion would be redirected walking, which allows people to move freely within a cleared space of their own – this accommodates to the space’s boundaries as well.

As shown in Figure 5, this is Walkabout Locomotion developed by Tekton Games.

Figure 5, Tekton Games (2016)

This system allows players to freeze the environment when they reach boundaries, players can turn around but unfreeze the game from the perspective that they have stopped within.

“Tekton Games’ WalkAbout locomotion system allows users to physically walk anywhere in virtual space using a room-scale VR setup.”

Tekton Games, 2016

This is possibly the most natural form of locomotion within virtual reality as it allows the player to fully walk within their space whilst showing boundaries without having them take off the headset.

Bibliography

FutureLearn. 2022. Interaction Techniques in VR. [online] Available at: https://www.futurelearn.com/info/courses/construct-a-virtual-reality-experience/0/steps/96390 [Accessed 3 May 2022].

LI, Y., HUANG, J., TIAN, F., WANG, H. and DAI, G., 2019. Gesture interaction in virtual reality,. [online] sciencedirect.com. Available at: https://www.sciencedirect.com/science/article/pii/S2096579619300075#:~:text=VR%20has%20three%20distinct%20characteristics,the%20real%20world%20through%20feedback [Accessed 3 May 2022].

Nanjappan, V., Liang, H., Lu, F., Papangelis, K., Yue, Y. and Man, K., 2018. User-elicited dual-hand interactions for manipulating 3D objects in virtual reality environments. [online] springeropen.com. Available at: https://hcis-journal.springeropen.com/articles/10.1186/s13673-018-0154-5#:~:text=In%20the%20real%20world%2C%20%E2%80%9Cmanipulation,manipulations%20of%20these%203D%20objects. [Accessed 3 May 2022].

Wigmore, I., 2018. What is VR locomotion (virtual reality locomotion)? – Definition from WhatIs.com. [online] WhatIs.com. Available at: https://www.techtarget.com/whatis/definition/VR-locomotion-virtual-reality-locomotion#:~:text=VR%20locomotion%20is%20technology%20that,translate%20to%20in%2Dgame%20movements. [Accessed 3 May 2022].

Tektongames.com. 2016. WalkAbout Presskit |. [online] Available at: http://tektongames.com/walkabout-presskit/ [Accessed 3 May 2022].

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].

Categories
Uncategorised

GD2 Blog: Week 21

Collaborative Project

As of the 14th of March, we started to get into groups with students from other games classes for a collaborative project on a game with the theme of “A conversation that changes the world”.

After brainstorming several ideas with the group, we had the idea to create a top-down game in the style of a bullet hell. Where the player will be avoiding projectiles from a birds eye view.

To get started on the project, I started work on the prototype by creating some basic movement and a camera that changes from room to room via the use of box component triggers, Figure 1 shows the system in place.

Figure 1 (Personal Collection)

To do this I set up an Actor that contains a box component and uses an onOverlapBegin function – included is also a boolean that activates a camera on start.

This is used as a trigger that covers a whole room, and once overlapped will trigger a function that sets the player controller’s current view target with an assigned camera – as seen on the bottom of Figure 2, we have an actor reference we will be using.

Figure 2 (Personal Collection)

Figure 3 shows the actor reference is used to select any camera within the environment, this will then be referenced within the CPP section of our code.

There is also a UPROPERTY with EditAnywhere assigned to it, this is so that we can easily assign it to any camera in-editor – this helps let other people working on the project to easily do this themselves without having to code.

Figure 3 (Personal Collection)

Before we set a view target on our cameras, we need to possess the player within our scene. This is done by including “Kismet/GameplayStatics.h” in our CPP file.

Figure 4 (Personal Collection)

We need to possess the current player by doing UGameplayStatics::GetPlayerController(this, 0). This will get the first player in the game scene.

Harrison McGuire, 2017

Within the CPP file of the actor is an overlap begin function. First included is a debug message to confirm that our overlap event is working, secondly is a local variable used to set the time of the camera blend – this is used to make it so the camera transitions smoothly to the next.

We then include a reference to the player character to detect if they’re colliding with the trigger, then once we find the actor that handles control for the local player we get the view target of the player’s current camera and set it to move to our referenced actor.

Figure 5 (Personal Collection)

As shown by figure 6, this is the player walking into a room with a different trigger. Once overlapped, the viewtarget is set towards the camera assigned to the trigger – the image shows the blend in motion.

Figure 6 (Personal Collection)

Bibliography

Unrealcpp.com. 2017. Unreal C++ | Set View Target. [online] Available at: https://unrealcpp.com/set-view-target/ [Accessed 24 March 2022].

Categories
Uncategorised

GD2 Blog: Week 20

Hyper Casual Game

As of the 14th of February, I’ve decided to finish adding towards my Hyper Casual Game by finally implementing a menu for it as well as a way for a game over condition that lets the player simply restart the game.

As shown in Figure 1 is a functional menu that shows up once the game is loaded, in this menu the player is able to start or exit the game. Included is also a high score that keeps track of the player’s high score throughout the game and records the highest possible one they achieve.

Figure 1 (Personal Collection)

Figure 2 shows the menu widget changing to a game widget, which displays the players lives and current score. The score system works by giving the player points with each block destroyed, bounce pad interacted with and each extra life taken – each has a varied amount with long blocks giving the player 100 score, to extra lives giving them 1000.

Figure 2 (Personal Collection)

To do this, I had to set up UMG (Unreal Motion Graphics) using one of the official Unreal C++ tutorials as linked below:

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

(docs.unrealengine, 2022)

This goes over how to build a basic menu system with multiple screens and buttons.

To start off, UMG is dependent on a few modules so they’ll need to be added to our project build’s cs folder and add UMG to the list of included public modules.

Within my code’s file, I modified line 11 to include “UMG” in its brackets, and then uncommented PrivateDependencyModuleNames as we’ll be using UI (See Figure 3).

Figure 3 (Personal Collection)

As the menus we create will be made from User Widgets, we’ll need to write a function that helps display and create new User Widgets. This function will be called once the game starts, it also keeps track of what we have created so that it can be removed later.

This is done by opening our GameMode class and adding in the following functions and properties for Figure 4.

We’ll be making a function called ChangeMenuWidget which removes the current menu widget to create a new one from the specified class if provided.

In our protected variables, we have StartingWidgetClass which will be used as our menu for when the game starts.

Next is CurrentWidget which is the instance we are using as our menu. Included is also ‘#include Blueprint/UserWidget.h’ in the header.

These will all mostly be Blueprint compatible, as we’ll need to use them for widgets later.

Figure 4 (Personal Collection)

Moving onto the CPP file, on begin play we set the menu widget to our StartingClassWidget. We then define how we change between menus and remove whatever User Widget is active from the viewport, if any. We then create a new user widget to be added to the viewport (See Figure 5).

Figure 5 (Personal Collection)

Finally, we need a player controller that sets our input mode. For this, we just only need to make sure it overrides the beginplay function in the header file and sets our input mode once the game has started (See Figure 6).

Figure 6 (Personal Collection)

Afterwards in the CPP file, we set the input mode to UI only once beginplay is activated.

Figure 7 (Personal Collection)

As for next, I designed the following widgets to be used in the game. Figure 8 shows the menu, which introduces two interactable buttons that trigger events on clicked.

Figure 8 (Personal Collection)

Once the start game button is clicked, an event plays which casts towards the game mode to change the current blueprint. Also included is a cast going towards the player’s paddle, which activates a function from it that is callable from the blueprint (See Figure 9).

Figure 9 (Personal Collection)

As shown in Figure 10 is in the paddle containing the BlueprintCallable function in the header file.

Figure 10 (Personal Collection)

This function essentially just restarts the players variables including Lives and Score as to start them off fresh each time the game is started.

Included is a call to a function that spawns the ball, the actor’s location is also set to their starting location in the middle of the screen.

Figure 11 (Personal Collection)

To configure our game mode to work with the current UI, we add a blueprint class based on our project’s game mode which makes it possible to set exposed variables to whatever values we want.

To see our mouse in-game, we’ll need to create a blueprint of our player controller as we did with the game mode, as seen in Figure 12 is the class defaults of the player controller with Show Mouse Cursor enabled.

Figure 12 (Personal Collection)

In our game mode blueprint, we set our starting widget class to the menu we want to display, this being our Menu_BP – The player controller we created is also set.

Figure 13 (Personal Collection)

In our world settings, we also set the game mode override to our game mode, this means our asset is now in effect on our level. Once the game starts, our menu will be loaded and use our player controller to set input to UI (See Figure 14).

Figure 14 (Personal Collection)

The second widget is our game widget, this simply just keeps track of the player’s lives and score (See Figure 15).

Figure 15 (Personal Collection)

Using binds for each text box on the bottom left and right, we are able to cast to the paddle to display their variables (See Figure 16).

Figure 16 (Personal Collection)

As displayed in Figure 17 is the game menu in action, it is constantly tracking the paddle’s variables.

Figure 17 (Personal Collection)

Within the blueprint of the game widget, is an event tick function that constantly checks whether the player’s lives have reached zero. Once reached zero, it will then decide whether to set and change the high score depending on if it is higher than the previous. The High Score is a declared variable within the game mode blueprint which changes to the paddle’s Current Score if the latter is higher (See Figure 18).

Figure 18 (Personal Collection)

However if this is not the case, the event will simply just move onto the next sequence and change the widget back to the menu and set the player controller’s input to UI only.

Figure 19 (Personal Collection)

As shown by Figure 20 is the high score being set in the menu widget after the player loses all their lives and causes a game over condition. As this is a game mode variable this is active for as long as the game mode remains.

Figure 20 (Personal Collection)

As for this, I believe my Hyper Casual Game is now within a completed state, the game now contains fully functional UI for the menu and in-game which keeps track of player lives and score.

As this is the final week before submission, I believe that I did quite well with the project with what I was able to achieve and I’m quite happy with how the game ended up.

However I do feel as if I could’ve added more to the game such as further polish, which could’ve been done by having more effects and sounds to flesh out the game.

I have mentioned in my GDD receiving feedback for the game as well where a tester asked for additional effects to help convey the ball hitting the blocks more easier by adding a brief flashing effect on collision. This is useful to know from player feedback as it is a good way to know what players need to understand the gameplay better.

Bibliography

(Docs.unrealengine.com. 2022) User Interface With UMG. [online] Available at: https://docs.unrealengine.com/4.27/en-US/ProgrammingAndScripting/ProgrammingWithCPP/CPPTutorials/UMG/ [Accessed 16 February 2022].

Categories
Uncategorised

GD2 Blog: Week 19

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.

Figure 1 (Personal Collection)

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).

Figure 2 (Personal Collection)

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).

Figure 3 (Personal Collection)

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).”

(docs.unrealengine, 2022)

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).

Figure 4 (Personal Collection)

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).

Figure 5 (Personal Collection)

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.

Figure 6 (Personal Collection)

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.

Figure 7 (Personal Collection)

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.”

(docs.unrealengine, 2022)

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).

Figure 8 (Personal Collection)

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).

Figure 9 (Personal Collection)

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).

Figure 10 (Personal Collection)

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.

Figure 11 (Personal Collection)

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).

Figure 12 (Personal Collection)

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)

Figure 13 (Personal Collection)

As seen in Figure 14 is the Extra Life’s sphere material changing colour in-game.

Figure 14 (Personal Collection)

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).

Figure 15 (Personal Collection)

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).

Figure 16 (Personal Collection)

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).

Figure 17 (Personal Collection)

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.

Bibliography

(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].