top of page

Games Practical Project Development Blog - Run up to the End

Writer: Neil Beattie
Neil Beattie
May 17, 2019
5 min read

Well guys, its definitely been a while since the last blog post, and a lot has changed since then. The project has advanced in almost every way you can imagine, but unfortunately I fell completely off of planning and writing blog posts, and put my focus entirely on the project for the remainder of my time at University. This post will be extra long, so I hope you've got some free time before reading on! Throughout the images, you'll see the good old UE4 mannequin has been retired, in favour of some characters from the "Modular RPG Heroes Polyart", available here:

Firstly, the FPS problem that was left as a cliffhanger last time, the solution ended up being quite the simple one, but one that avoided my thought process for far longer than I'd like to admit. While generating the level, each cell needs to be set to movable to get set into the correct places. Once the level is laid out, I then run through each cell that was spawned, and change the movability to Static. This simple change has put my FPS from 20-40 on average, to being solidly maxed on 120 consistently.


Next, I want to discuss the main focus of my project, the Cellular Automata, and it has evolved massively from the state it was in previously, including some actual art and lighting! After this was a lot of improvements to almost every section of the blueprint, far too much to discuss in length while showing images, so below is the large majority of the blueprint, broken down with quick descriptions of what each section does.

The final version of Cellular Automata Generation

The event graph for the Cellular Automata Blueprint, showing the previously functioned remove from array, moved to the green comment box as a custom event

The start of the Blueprint, setting reference to the game instance, initiating the Grid and Iterating the layout of the cells

Finding the outer sides of each wall and adding meshes for walls and corners, then beginning the population process

The process of finding the outward facing sides of each wall cell

The process of finding the outward corners of each wall, and spawning columns on each one while avoiding spawning any on the inner side of the wall

Setting a spawn point for the return ladder, removing that cell from the array, and syncing that location with the players spawn

Similar to above, setting finding a point to spawn the ladder down, then removing that cell from the array

Storing important information for the pathfinder ai to make sure the player can make it from point a to point be, regardless of level generation

Pictured in gold, the almighty, yet incredibly simple optimisation fix, then spawning the pathfinder ai at the same point at the player will spawn

The Pathfinders event graph, including some previous, failed attempts at achieving the same thing

The important bit, finding the points along a hypothetical path from the return ladder to the progress ladder, and checking if it's within a certain distance from the final point in the index, essentially checking if the player can ever get close enough to the ladder down to interact with it

Either spawning a new ladder down at the final point of the hypothetical path, somewhere the player would ALWAYS be able to reach, then/or continuing with the Level generation and destroying the pathfiner Ai as it's purpose is complete

After the pathfinder is finished, sets all remaining floor cells as possible spawn locations, and begins populating the floor one actor at a time. The minuscule delay between each is to allow for the "removing used cells" event to run before the next location is chosen

The event to remove cells from the spawn point list, originally a function until dubugging found that stopped it working

The Function for populating the floor randomly, with a scalable max number of spawns per floor

Setting up the necessary settings for the game to begin, moving the player into the correct position, adding the HUD to the screen, and playing the widget to show the current floor number to the player

Checking if the current floor is the floor the player previously died on, if true spawns a unique ai who holds the loot the player had on them at the moment of their death, and signalling the end of the Level Generation

Next thing that needed attention was the dialogue system, which had been criminally under developed up to this point, simply existing off of a random int and a print string. As you can see below the ui matches the camera and characters.

The new and improved Dialogue system

The event graph for the Master Interact Ai

For future facing and scaling reasons, I made sure to make the specific names and NPC dialogue incredibly flexible, making use of public text arrays for both the names and dialogue, as well as an option for cut scene specific dialogue, this can be entered in the level editor or at spawn, along with a max number of dialogues so the game knows when to start looping text after exhausting the dialogue options.

The public vairables used for the Dialogue UI

The designer window for the text boxes, showing that this same widget is also used for showing the players current debt to the shopkeeper, and where the player can pay it off

The event graph for the dialogue UI

The shop and debt systems, including purchasing upgrades for the players stats

Showing the increase of Debt after 7 days has passed

After this, as you may have noticed from the above gifs, the players HUD needed to be improved from the very plain Green rectangle for health, and plain text for the date, gold and loot. Along with a more stylish look, I gave the gold and loot symbols rather than text to keep the HUD more concise and less test busy. I also added some numbers above the players health bar so the more attentive can have a much more accurate reading of how much health they have, and what sort of damage the enemies are currently dealing per swing.

The designer window for the HUD

Still on a polishing rush, I decided that if the player is expected to return to the Hub on a fairly regular basis, it would have to have something more going on, and why not follow the mantra of the rest of the game. So now, there is a low chance on returning to the hub, that there are some very ambient raining noises outside, to really sell the passage of days with procedural weather. This then evolved into a much lower chance if its already raining to cause a thunderstorm, randomly interrupting the rain to flash lightning outside the window, followed shortly after by the crack of thunder somewhere.

Random chance for lightning and rain at the Hub

The ambient rain BP, while simple has a very powerful effect on the relaxing atmosphere of the hub, with lightning being a rare surprise

A final overview of the players event graph, while not too terribly different from earlier in the project

Wanting to ensure the player didn't suffer from visual fatigue, I needed to make sure the different floors started to feel different too. In order to set this up, I decided to use the same system I use to check the deepest floor the player has reached, in multiples of 5, and if 5 floors have past, the colour will change.

Showing the lighting and feeling difference on different floors

The improved solution to finding if 5 floors have passed since the last time

Storing the different colour options in the Game instance, ready to be selected when necessary

An overview of the Game Instance, where many variables used over multiple Blueprints are stored, and some overall events are ran from

After this was all set up, I knew I had to spend a chuck of time on the moment to moment game play, with an improved level generation and look, the combat needed to be improved both mechanically and visually to keep up. I made sure to get plenty of public testing on every change I made along the way.

The buffed up combat system, showcasing the new damage flash, enemy and player knockback, slowdown on enemy kill, massive slowdown on final enemy kill, hit particles and damage numbers

Stored in the Game Instance, the way the game slows down to sell the importance of killing an enemy

The function for applying knockback, shown is the enemies version, making sure they get knocked away from the player. The same function is used in the player, with a different start and end location for the look at rotation node to make sure the player gets knocked out of immediate danger

Altered math for the enemy stats and loot scaling from before, after taking playtesting into consideration

Some of the balancing graphs set up for the game, to alter and test things like enemy stats and loot scaling, alongside player stat upgrades and increasing prices

Along with these changes, the AI has gotten a whole lot smarter, initially exploring the map freely until their attention is caught by the players antics, at this point the AI will chase down the player, attempting to get in close enough to swing, however if the player outmanoeuvres the enemy, and manages to get outside of a certain distance from the pursuing AI, it will give up and return to freely roaming the level.


The snippet of code that chooses where the ai will roam to on a case by case basis

Cracking open a rare chest

With the combat a lot juicier, I felt the player needed something other than combat to justify exploring through these generated levels, so I set up treasure chests to be an exceedingly rare spawn throughout the dungeon, with loot that scales to the level, much above the average loot dropped by enemies during combat. Well worth keeping your eyes peeled for!

The new death visuals and showing the thief enemy who holds the dropped loot

Still unhappy with the look of the visuals for death from before, I continued to tweak and change how they worked. Eventually settling for the players core outline, along with any nearby enemies outlines being the only things visible through the fade to black. With this gif, also shows the new enemy created, being a looter, only spawning on the same floor as the player died on, they hold on them the loot the player was carrying at the moment of their death. This gives the player a hail Mary attempt to reclaim the lost good they had on them. This enemy doesn't have the means to attack the player, but will try to get away from the player while choosing points to run to.


Reaching the end of development, ironically, I decided to set up a main menu to wrap the game up nicely. This menu holds a stripped down copy of the hub level, only keeping anything that is in view of the camera, I then set up a few different camera angles, that the menu takes on randomly at run time, as a final random selection, and in a meta sense to start the game as it means to go on. With this, and an incredibly simple start and quit, the game was finally in a state I could call it ready.

The stripped out level for the menu

The actual Widget, mainly relying on the random camera angles for the background



Finally, I want to leave you with a quick play through of the game from the start. Thank you so much for reading my ramblings, and following my progress throughout the project. I plan on continuing the project in my personal time, and may keep the blog going, but if this is the last post made, it's been an amazing ride, and I hope you enjoy. In the video you can see the on screen controls at the time of play, and experience the audio work I put in better than any text of GIF could show. I will be attempting to package the project to upload to Itch, but unfortunately due to changing UE4 engine version, the version of Visual Studio 2017 causes issues packaging, and causes failure.


 
 
 

Comments


© 2023 by Neil Beattie. Created with Wix.com

bottom of page