Categories
Uncategorised

GD2 Blog: Week 30

Collaborative Project

As of the 16th of May, I’ve been adding some further adjustments to the game. I’ve gotten plenty of feedback from Jerome for the current level design as well as some certain aspects of the player and widget (See Figure 1). I’ve also been working on the second level of the game based upon this feedback and their suggestions.

Figure 1

One issue players had with the game was that the projectiles fired by spawners seemed too small, and that their size had to be upped slightly more. This meant that the projectiles felt a bit too easy to dodge and thus giving the spawners less of a challenging presence.

Another issue is that the light projectiles seemed far too small, and were being fired too much by the spinning projectile spawner (See Figure 2).

Figure 2

For the spinning projectile spawner, I changed the size of the light projectiles it fires to be slightly more larger and noticeable by the player as well as delaying the amount of time it fires. The result is a much easier room to encourage movement as less projectiles make it less intimidating.

As for the other projectile spawner down the hall, I simply switched out the base projectiles for a heavier one, which is a much more larger and noticeable projectile (See Figure 3).

Figure 3

Another requested change was to reduce the player’s speed, however I disagreed with this change.

I feel that the argument of having the players speed through rooms is more of a problem with the level design rather than the player themselves – tuning down the player’s speed would also mean slowing the player’s ability to traverse through the current projectile spawners made within the game as well. I personally think slowing down the pace of the player would go against the point of it being a bullet hell as well, as it makes dodging more harder.

As for the other requested changes, health was requested to be shown in a different way. The previous gameplay hud in the game felt a bit too small and hard to see, it also didn’t display lives.

I’ve changed this to have a much more prominent presence within the game, moving the health up to the top right and making the text much bigger and clearer to see – lives and health are also coded to be different colours (See Figure 4)

Figure 4

I’ve also been making sure to help port more assets created by the artists of the team, Emre Kulac has also so far been adding details towards the first level of the game (See Figure 5).

Figure 5

Here are the model assets I’ve help import into the game, these have been done by Jordan (See Figure 6).

Figure 6

Some more feedback towards the game was to add some more complex projectile spawners (See Figure 7).

Figure 7

Following this feedback, I introduced a new type of projectile spawner which fires a configurable amount of projectiles in a circular pattern at once, it also calculates an angle for each projectile.

Figure 8 and 7 show the customizability of this, it allows people to set the amount of projectiles to spawn, at whichever spawn rate speed and which type of projectile in particular.

Figure 8
Figure 9

To achieve this within my code, I needed to change some things within the Base Projectile Spawner’s code. In the header file before I created a child class for it, I moved the function that shot the projectiles and moved it under “Protected” and changed it into a virtual void that would be overridden by the child spawner (See Figure 10).

Being moved under a Protected access specifier makes it so that the void will be able to be accessed within inherited classes of the actor.

“Protected members cannot be accessed from outside the class, however, they can be accessed in inherited classes.”

w3schools.com, 2022

Figure 10

Within the circular projectile spawner’s header file is just the virtual void for the function being overridden as well as an integer variable that determines the amount of projectiles to be fired (See Figure 11).

Figure 11

Within the CPP code, I’ve set a for loop that will repeat through the spawner for as many times as the projectile amount is set.

Within the loop, it will also get the rotation angle of each projectile and add it onto the rotation of the projectile to be spawned through each loop – as the rotation angle is the projectile amount being divided by 360, this means that all the projectiles will always be able to form a circular shape no matter the amount (Figure 12).

Figure 12

As soon as these got added, I started development on the second level within the game using these in mind using a design plan (See Figure 13).

Figure 13

The player is lead on a linear path towards their first circular projectile spawner room, this room will introduce a projectile spawner that spawns a low amount of weak projectiles which will conveniently avoid the entrance door the player enters through – this prepares the player for the following future rooms.

Figure 14

The player will require opening the door to the other half of the level by choosing a side room to go into, each one has a switch that will unlock one part of the door – the player decides which room they head into by operating a single moving block towards two pressure plates that unlock their respective doors, the player here is free to choose whichever door they want to open first (See Figure 15).

Figure 15

The room on the right side is a very large room, it proposes a single spawner that shoots a large amount of heavier projectiles across the whole room. Although they’re firing slow projectiles, an enemy is added into the room as well to provide supporting projectiles that fire more frequently and faster towards the player constantly (See Figure 16).

Figure 16

This introduces the player rooms that make use of multiple hazards, and makes sure that once the player enters the room, they will have to deal with the enemy as well as looking out for heavy projectiles emitted from the spawner.

The left side of the room introduces two moving block sequences as well as providing some cover unlike the other room which was more open, the objective of this room is to try and get the moving blocks onto both switches whilst also concentrating on the patterns of the projectile to make sure you avoid them (See Figure 17).

Figure 17

The player will also have to go across to the end of the room to complete the puzzle, which will require them to use cover and to time their movement carefully – this room teaches the player that sometimes they must be patient with the game and to not rush as it requires good timing.

The second half of the level will involve some more different uses of circular projectile spawners, featuring one more combat room with an enemy and a puzzle (See Figure 18).

Figure 18

The first room features a unique circular projectile spawner with only two differently facing projectiles set to fire from it, this results in a horizontal or vertical line of fire, this spawner fires the heavy variation of projectiles and each form a gap inbetween them that the player can slip through.

There’s also an enemy on the other side of the room that the player is unable to reach, due to this room being much more smaller than the last enemy room the player will have to be even more careful to not touch the incoming projectiles firing at them – once the enemy is cleared, the door then opens allowing them to progress out of the room (See Figure 19).

Figure 19

The second room in the player’s path is a long hallway with a projectile spawner at the end of it, this spawns a ton of projectiles that fill the hallway and are almost impossible to dodge without getting into any cover of sorts.

The tactic here is to use the moving block as cover to try and get closer to the exit out of the room, they’d need to move this closer to the exit to progress. Like the enemy and projectile spawner room, this is an attempt at making a room that involves mixing two mechanics together to form a puzzle (See Figure 20).

Figure 20

Not only could this player use a moving block as their shield to traverse through the hallway, but they can also use it to block most of the oncoming projectiles by placing it directly in front of the spawner (See Figure 21).

Figure 21

Although not exactly a puzzle room, this makes use of the circular projectile spawner in a way that makes it form a barrier from the other half of the room.

It could arguably serve as a good indicator to show where the player needs to progress (See Figure 22).

Figure 22

The final room afterwards has a centered circular projectile spawner, in this room are also several moving blocks the player has to slide onto pressure plates.

However the challenge of this room is to try and to take things slow, as the pressure plates aren’t placed at dead ends so that moving blocks can easily slide over them if the player fires too many bullets and gives them too much force – This teaches the player to patiently fire their shots whilst under pressure by fire and to not overly rush or else they’re more likely to overshoot the moving blocks (See Figure 23).

Figure 23

As shown in Figure 24 is the full layout of Level02, it is the longest level out of the whole game.

Figure 24

As shown in Figure 25, responses to the second level were mostly positive, and its shown to be a step up from level01 – as level01 is easy, it only makes sense to ramp up the difficulty for level02, as it is harder it also serves as preparation for the boss fight.

Figure 25

I’ve also been able to try and test Jerome’s boss battle level and some good progress has been made as the boss is fully functional and can be beaten (See Figure 26).

Figure 26

I’ve given my following feedback for the boss, requesting that the arena be smaller as there’s plenty of room to dodge projectiles and the difficulty of the boss should somewhat rely on being in a closer quarters space to make it harder (See Figure 27)

Figure 27

I’ve also gotten testing on the final stage of the game done from a third-party source, this being another Games Development student. They overall liked the gameplay and idea of our game and appreciated the concept of it.

They gave some feedback that the game needed some better audio and visual cues, such as indications for when doors get unlocked or the player being able to indicate taking damage – we unfortunately cannot add audio in our game due to none of the team having experience with working on audio, there’s also time constraints to worry about (See Figure 28).

Figure 28

As for my progress, I seem to be done with all I need to do for the game whilst I’m waiting for everyone else to finish. I’ve marked my Trello progress as completed (See Figure 29).

Figure 29

One feature that had to be cut was giving the enemies the ability to move, simply due to how it wasn’t needed throughout the current level design of the game – Time constraints were also a problem which also contributed to the feature being scrapped.

Although, as this was our last week working on the game. We unfortunately weren’t able to make all the progress as we’d hoped, but still managed to pull through with a prototype that’s playable from start to finish which I am overall proud of.

One particular main issue we had with working was that the group had a weak direction, as no one took a lead in the project which led to many of the group not working too much on the game – this led to communication between most of the group being much more harder. I took the lead and set up a GitHub to make progress on work much easier for the the group and encouraging as many to work on the game as possible – We weren’t fully able to completely follow through with our game testing plan.

If I were to start another group project, I’d try to focus and make sure that the next team has a more stronger directive and to take the initiative more often in organizing and helping set up things to further ensure we make the best progress as possible with our time.

Bibliography

W3schools.com. 2022. C++ Access Specifiers. [online] Available at: https://www.w3schools.com/cpp/cpp_access_specifiers.asp#:~:text=In%20C%2B%2B%2C%20there%20are,be%20accessed%20in%20inherited%20classes. [Accessed 18 May 2022].

Categories
Uncategorised

GD2 Blog: Week 29

Collaborative Project

As of the 9th of May, I’ve worked on implementing levels into our game piecing together the assets and mechanics I’ve made so far – there are moving block puzzles, locked doors and basic enemies within the game as well as a simple level transition.

I’ve also instructed Indie Developer Jerome to work on a Boss Fight level, from this we both also have provided feedback on each other’s levels via playtesting.

The boss designed by Jerome has a set moving path where it moves around the edges of the room, and fires a multitude of different projectiles towards the player (See Figure 1).

Figure 1

I personally thought this was a good start on the boss, as it made good use of the bullet hell concept and encouraged dodging for our player. However, I expressed concern for the difficultness of the fight, the current arena was small and there wasn’t any way for the player to replenish health – which of course made the fight too hard (See Figure 2).

Figure 2

My feedback for this was approved, and Jerome considered adding it in for his next push to the game later on.

Figure 3

As for my own progress…

The game now contains some basic enemies based off of pawns that face towards the player and shoot projectiles at them once activated, they have an Active boolean which determines when they should attack and also health which destroys them once reached 0 (See Figure 4)

Figure 4

Similar to the projectile spawners, enemies have variables that determine their projectile spawn speeds and also contain a subclass that spawns projectiles as well as a timer. They are also activated once the player enters a camera trigger zone, and deactivated once outside.

The main difference between these is that enemies will be able to look towards the player and track their shots on them, as well as being able to be defeated, and sometimes are needed to unlock doors to progress (See Figure 5).

Figure 5

As for how enemies are able to look towards the player, we first need to a reference to the player. However as the player is spawned into the level rather than already existing into it, we need to declare this cast within the beginplay function of our enemy by getting the player character within the world (See Figure 6).

Figure 6

Once we have a reference to the player set up, we use a KismetMathLibrary function known as “FindLookAtRotation”. Similar to how we made the player look towards the cursor, we get the location of our enemy and then get the location of our player, then set the actor to rotate towards this within the tick function once activated (See Figure 7).

Figure 7

Figure 8 shows the enemy in action, as you can see I’ve moved over to the right and the enemy is still able to point towards the player to fire its projectiles towards me.

Figure 8

To improve upon these enemies, I may expand on them and add in something like a PawnMovement component to allow them to move about during the level, however this will depend on how much time I have left to work.

The level now includes sliding block puzzles, which consist of a simple MovingBlock pawn, and a pressure plate with overlap functions (See Figure 9).

Figure 9

The MovingBlocks are pawns with UPawnMovement components attached to them, this makes it easier to update movement for an associated pawn.

“PawnMovementComponent can be used to update movement for an associated Pawn.”

docs.unrealengine, 2022

With this movement component, not only could it update movement for its associated pawn but we could make it slide along surfaces if it’s currently being blocked by any object, this allows our moving blocks to slide along walls smoothly (See Figure 10).

Figure 10

Players can move the moving blocks by shooting into them, to do this, I gave the moving block 4 different trigger box components of each side that could possibly be fired upon by the player projectiles which is as shown by Figure 11 and within the constructor on Figure 12.

Figure 11
Figure 12

The moving block also has a timer, which determines for how long it should keep moving as well as resetting the acceleration and speed variables of the block (See Figure 13 and 14).

The timer set function also has some parameters helping determine the force of the shot and the amount of time to add onto the slide timer.

Figure 13
Figure 14

Within the CPP of our moving block, once the timer set function is active, it will take the parameters from the projectiles and add them onto the timer as well as change the current speed of the moving block as shown in the tick function.

Once the timer has stopped, it will call the “StopFVector” function which will reset most of the variables to 0 (See Figure 15).

Figure 15

Now onto the Player Projectile’s OnHit function.

If the projectile is colliding with a Moving block actor, we will test to see if the correct component is being hit by using a debug message that will output the current component being hit within the code by using “GetName()”.

Using “GetName()”, we can also check to see if the component being hit by the projectile has a specific name, for instance we want all the components we intend to use as triggers to move the block – once hit, it will change the SlidingTo vector within the Moving Block’s variables and then activate the timer set function whilst inputting parameters.

These parameters will be added on top of the current ones within the moving block to gradually increment them the more the player hits it before time runs out, this means the more the player shoots a moving block, the faster it will go and the longer it’ll slide (See Figure 16).

Figure 16

As shown in Figure 17, our debug message is outputting the current component our projectile is colliding with and then moving the block forwards where we shot it.

Figure 17

Doors within the game now have new properties that determine whether they’re unlocked or not.

The “Lock” bool keeps the door from opening if it is left on true, this is determined by if the “LockAmount” integer is above 0, this means the door could potentially have multiple numbers of locks the player will have to try and unlock (See Figure 18 and Figure 19).

Figure 18
Figure 19

Both Enemies and Pressure Plates have actor references alongside a UPROPERTY(EditAnywhere) to Doors within their code.

This will allow us to have both multiple enemies and plates attributed to a single door if we wanted, like how in the first level a door is locked by two pressure plates (See Figure 20).

Figure 20

Figure % shows the overlap functions within a pressure plate, if the pressure plate is currently being overlapped then it will unlock the door by subtracting from the lock amount, however if something is taken off it, the lock will then be added back on (See Figure 21).

Figure 22

Although more simpler, once an enemy’s health reaches 0, the code checks to see if they currently reference a door and if so, it’ll subtract from the lock amount (See Figure 23).

Figure 23

Included within the game now is finally a level transition, once overlapped by the player this will allow them to transition to the next level. To do this, we first need to contain an array of all the level titles we want to transition through – this will be an FString array defined within our Header file (See Figure 24).

Figure 24

Within the constructor, we add our level names as strings into our declared Array, for the game, there will be only 4 levels; the main menu, level 1, level 2 and level 3 (See Figure 25).

Figure 25

Within our overlap code, I created a local FString variable called “Current”, this gets the map name from the current world the level transition is in, we also remove the StreamingLevelsPrefix from that start of the FString – within the UE4 editor, the engine adds a prefix that we must remove in order for this to work.

I then created a For Loop which helps determine which level the player is in currently, and then decides which one to transition to next.

As we’re iterating through our levels we want to check which index our level name matches, using this we can determine whether to go forward a map or back. Within the context of the game, once the player beats the final level they will be taken back to the very first, which will be our main menu – we do this by making a handler to check and see if the current level is at the final order of our array, if so we then go back to the first instance.

Afterwards, we use UGameplayStatics to open a level by converting our current FString into an FName and then add 1 onto our for loop variable to open the level directly next to our current one (See Figure 26).

Figure 26

Once finished with my work for the week, I updated my progress on the group’s Trello board. I’ve also included what I’ll be working on for next week on the project, which I will be trying to finish implementing the second level within the game and possibly expanding upon enemy AI (See Figure 27).

Figure 27

With the following new assets in, the first level of the game is now finished gameplay wise (See Figure 28), albeit lacking details. I’m hoping to communicate more with the art side of my team to fill in the remaining levels of the game with some more models and details.

Figure 28

Bibliography

Docs.unrealengine.com. 2022. UPawnMovementComponent. [online] Available at: https://docs.unrealengine.com/4.27/en-US/API/Runtime/Engine/GameFramework/UPawnMovementComponent/ [Accessed 16 May 2022].

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