Three different level generation algorithms to produce visually different levels.
This technique is being employed to optimise the level generation and reduce the burden on hardware resources.
The gameplay sees the player returning to previously explored levels to escape the dungeon. Therefore these level's data is saved to ensure the level and its state is the same.
The player can carry items in their inventory as long as there is space and their carry weight is not exceeded. Depending on the item type it can be equipped to have its stats applied to the player or consumed to use its effect.
Player abilities that are dependent on the currently equipped weapon.
A fog of war system using shaders and masks to show where the player has explored while hiding enemies and interactable objects which are not without the player's vision range.
This game was made during a three-week sprint following a multi-page script given for an assignment during my Master’s degree. The goal was to create a turn-based roguelike dungeon crawler in which the player has to delve deep into a dungeon to find the Talisman of Boletaria. Doing so will awaken the monster named Dorian. The player is unable to attack Dorian and therefore must attempt to escape by backtracking through the dungeon to return to the surface while being chased by Dorian.
There are 30 levels to the dungeon. All levels are completely randomly generated and populated with game objects except for levels 1 and 30. There a level ranges which have a higher chance of generating a particular layout with the overall goal being to have the early levels being caverns, followed by broken-up dungeons and lastly a more traditional dungeon level featuring hallways and rectangular rooms. Throughout the player's journey, they will encounter monsters which upon being defeated may drop loot which will aid the player in delving deeper.
The player can assign a name to their character and select a class, which will impact the die used to roll for their stats. To simulate the rolling of a die, I used a coroutine to cycle between sprites. The delay between sprite changes increases as the animation progresses to show that the die roll is slowing down, before landing on the number rolled.
There are three types of level generation algorithms present in the game which allow the generation of different level layouts. Each type of generation extends from the same class, which makes it possible for all the different generation classes to be invoked using the same method and code structure. The parameter values for these generation algorithms are stored in scriptable objects so I could simply load the set of values I wanted depending on the type of level which needs to be created.
This algorithm randomly walks around placing floor tiles. It will walk for a predetermined amount of steps. After which it will start another iteration of randomly walking. An iteration can either continue from the previous iteration's last position or start at a new position.
The result is a cave-like layout which depending on the parameter's values can be small and neat or vast and unruly in stucture.
This method generates 1-tile-wide corridors in one direction. At the end of a corridor, there is a chance to create a room or continue the corridor in a different direction. Depending on the parameter's value the room generated is a rectangular room or broken room with holes and uneven walls.
The outcome is a dungeon layout with long and winding corridors, with the option of broken or more traditional rectangular dungeon rooms.
This approach starts by generating the rooms in the level. After which the algorithm goes about attaching the neighbouring rooms. The rooms generated can either be rectangular or broken up, depending on the generation parameters given.
The output of this approach is a more traditional dungeon level featuring a large number of rooms which vary in size all being connected by short corridors.
Two asset packages are being used to further evoke the differences between levels. One asset package is being used for the cavern levels, while the other is being used for the dungeon levels. A scriptable object is used to assign sprites to the different tiles needed in a level.
Two asset packages are being used to further evoke the differences between levels. One asset package is being used for the cavern levels, while the other is being used for the dungeon levels. A scriptable object is used to assign sprites to the different tiles needed in a level.alls which visually matched up.
The game features a fog of war system which was implemented using shaders and masks. There are two cameras in place, one for saving the known fog and showing the known fog, and the other for showing the visible area which the player can see through. The camera handling the known fog was set to never clear its flag, resulting in the known fog areas. This was then applied to the render texture which is attached to the camera, resulting in saving the fog of war for that level. Then by swapping out this render texture, it was possible to have saved the fog of war for each of the levels. This way the player would have a new fog of war for new levels while maintaining their existing fog of war for when they eventually go back to previous levels. Furthermore, the game objects were hidden in the fog by setting their mask interaction to only be visible when inside the secondary mask (the visible area around the player).
When the player has an interaction range attached to its game object which when it collides with a game object on the “Interactable” sorting layer will make a button appear. Clicking this button will perform the game object’s interact action which is handled by having the game object's script extend an abstract class for interactables.
There are two types of items present in the game. Equipable items and consumable items. Both use the same class as this made it easier to maintain the player’s inventory in one list using this method given the time constraint of the project. Scriptable objects are used to assign the generation properties for these items, with equitable items having a modifier applied based on how far down into the dungeon the player has gone. Resulting in the player getting better equipable item stats as they progress further into the dungeon.
Hovering over an item will present the player with a tooltip which outlines the details of that item. The tooltip is capable of ensuring it is on screen and will adjust itself should it need to. The player can drop or pick items from their inventory, monster drops and chests. Furthermore, they can equip and consume depending on the item type. The consumable items are stackable, with a system in place to check if the player already has that consumable item and continue the stack. When the player drops an item, in places it into a loot bag onto the floor, which the player can interact. This will store all the items the player has dropped in that spot. The loot bag window is designed to group items by pages. Therefore the player can access more items by clicking to the next page and be able to view the rest of the items. If the player’s inventory is full or their weight limit is exceeded then they will be unable to pick up more items.
Throughout the dungeon, the player may encounter shops. Here they will be able to purchase equipment and consumables using the gold they earned from killing monsters in the dungeon. The items in the shop are random, and in the case of the consumables, the amount of a consumable is also random with the price scaling depending on the size of the stack. The size of a level will influence the number of shops which can spawn on that level.
The dungeon is inhabited by bats, goblins and slimes. All these monsters use the same class to track their stats, health and manage their logic. Each monster has different parameter values which affect the monster’s stats. A monster will randomly move around the level when the player is not within their aggro range. When the player enters their aggro range then the monster will move towards the player choosing the tiles which will bring the monster closest to the player. Once the player is within attacking range the monster will stop moving and instead attack. The number of monsters on a level is determined by the size of the level.
The boss of the dungeon is called Dorian and uses a class which extends from the other monster's class. Dorian can not be attacked and is consistently within range of the player throwing out telegraphs. These telegraphs will go off after a certain amount of turns damaging the player. Since Dorian is always near the player throwing out abilities, I chose to make it a UI element as this saved time by not needing to code this logic.
The combat between two game objects is handled in the GameManger class using the Attack method. This takes two game objects (the attacker and the defender) and compares their stats to calculate the damage the defender will receive. At least 1 damage is guaranteed, regardless of the defender’s armour class. Additionally in the player’s case, their weapon will lose durability when attacking, while their armour and shield will lose durability when defending.
The player has access to three ability slots. The first ability makes the player immune to being attacked and chased for 10 turns. The remaining two ability slots depend on the weapon equipped. For a sword, this will be a close-range attack while the other ability damages all enemies surrounding the player. A bow will shoot a long-range arrow, while the other ability is a medium-range attack which hits an enemy three times. Lastly is a staff which has a long-range attack and a long-range AOE attack that damages all enemies within its radius.
Clicking the ability will first show the ability’s range, then clicking on an enemy within range will perform the ability given that the player has sufficient fatigue. The player can cancel an ability by clicking on the ability again. Hovering over the ability icon will bring up a tooltip which will detail what that ability does, its cooldown and its fatigue cost.
The ability's range is being dynamically drawn at the start of the game. This makes it possible to change an ability's range without having to update any sprite visuals. By drawing the range once and not every time the player clicks an ability helps in reducing computing power.
The player’s turn ends whenever they make an attack or movement action. This progresses the in-game time by 4 minutes and signals for all other game objects to perform their turns. This logic is handled by the GameManager using the ProgressGame method. This method cycles through the dictionary of active game objects for that level (stored in the AssetManager) and calls each game object’s Action method.
Copyright © 2024 Kooldiagon - All Rights Reserved.
Powered by GoDaddy