maandag 2 april 2018

Procedural Dungeon - Part 3: making the dungeon gameplay ready

Procedural Dungeon - Part 3

Introduction: 

In the previous posts I showed you how I have laid a solid foundation for the procedural dungeon. Now all we need to start using it is adding collision and textures.
So let's get started!

Collision: 

All I had to do was add a mesh collider component in code and set the sharedMesh to the wall-mesh I already generated.
It really can't get any easier ;)

Creating a player controller: 

Not so much special stuff about this.
For the player I created a simple player controller, where you can walk, sprint and hit with a hammer. Furthermore I came up with the idea that you can spawn stuff to find out where you have been already in the maze. So I made this too.

Pathfinding: 

What I really struggled with was the pathfinding for the AI. Luckily I found out that you can bake a navmesh surface over a mesh in game-mode. To do this, I first had to find out how to make a custom ground mesh from the data that I already had. 
After I managed to do so, I only had to attach the navmeshsurface to it and build the navmesh.

If you want to check out the navmesh components git that I've used, check it out here:
https://github.com/Unity-Technologies/NavMeshComponents

Spawning Objects: 

For the spawning I retrieved the data from the rooms, and used a random tile-position as a spawn position. 
To prevent stuff from being spawned at the same room I created the following recursive function:


zaterdag 31 maart 2018

Procedural Dungeon - Part 2: detecting regions and connectivity

Procedural Dungeon - Part 2

Introduction: 

In the previous posts I explained how I managed to get the basic system of a procedural dungeon. However, there is still a lot to be done! We don't have a connected room system yet, so this will be the main focus of this post.

Detecting regions:

The maps that we generate now still have a few flaws. One of which is that I don't have any control over the minimum size of rooms or wallRegions. This will be the first thing to fix!
However, to do this we first have to detect the regions. To do this I used the floodfill method. This algorithm simply checks for all (horizontal and vertical) neighbours if they have the same value, and if yes, the neighbour is added to a 'region' list. In code this looks like this:


Now that we have the floodfill system, we can easily detect which areas should be removed. Here you see it in the Gizmos:


Detecting connectivity:

The next step is to detect whether rooms are connected or not. I do this by comparing the edgeTiles of all the rooms that have left with each other. For each room the following is true: the room with the closest available distance to roomA is the closest of roomA.
However, that all rooms are connected to the closest room, does not mean that all rooms are connected to each other. This is however, very important if you want the player to see all of the dungeon.


Ensuring connectivity:

The next challenge is to make sure that all of the rooms are connected. To do this I have changed the ConnectAllRooms function. I did this by making it recursive: The first call makes sure that all of the rooms where at least connected to the closest room. After this I split up all of the rooms in two Lists: one that contains all rooms that are not connected to the starting room, and one that contains all of the rooms that are connected to it.
The rest of the checking-which-room-is-best functionality basically remained the same. Now the rooms that are not connected to the starting room only try to connect themselves to the rooms that are connected to the starting room!

Creating passageways:

Now what we need to do is make sure that the passages between the rooms are being generated. We do this by creating a list of Coordinates between the start and the end position of a passage.                                                        The logic of this process is the following:                                 -we calculate delta x and delta y (dx and dy)                         -we compare the absolute value of dx to dy and the greatest value will determine in which direction we will traverse the line (the sign of dx or of dy)                                                   -we make a gradientAccumulation variable that will be used to track our line-traverse-progress                                           -we then start a for loop, where i < longest and in each iteration, a point will be added to the line and we will track if we have to update both x and y, or on of both                          Hopefully this explanation will help to understand the block of code displayed on the right.






So far:

What I have right now is a dungeon where all of the rooms are connected, and a mesh is created out of that data. Here is a GIF to show you the generation process over time:

vrijdag 30 maart 2018

Procedural Dungeon - Part 1: cellular automata and creating a mesh from it

Procedural Dungeon - Part 1

Introduction: 

In this post I will describe the first progress that I've made with my dungeon!
To be honest, I have never done anything quite like this in Unity before. So this will be a challenging and long trip for me! However, I like learning new stuff, so I'm looking forward to it! I hope you do too ;)
To create this dungeon I use the great tutorial series of Sebastian Lague: 
https://www.youtube.com/watch?v=v7yyZZjF1z4&list=PLFt_AvWsXl0eZgMK_DT5_biRkWXftAOf9

I will try to describe the steps that I've taken as clear as possible for you!

game of lifeThe natural dungeon shape:

Cellular Automata is a mathematical model that is often used to reproduce natural looking structures. The core of this model is that repopulation of cells is based on the amount of adjacent cells.The most famous example of this is 'Game of Life', a game where you see the population of a grid evolve over time. 
The difference with between 'Game of Life' and with what I want to create is that my dungeon will not evolve over time. Instead I will use this model to repopulate the grid x times when the game starts.
This then results in what I have already shown in the previous post!

Generating the mesh:

So far so good, this was all pretty straightforward. But now we come to a more difficult part: generating a mesh from a grid of tiles. All of the data we have is a grid full with nodes, containing 1 or 0 meaning they are filled or not. 

Marching Squares:
To make sure the mesh will not as cubic as it is right now, we use a algorithm called 'Marching Squares'. The idea behind this is that we check the neighbours for each cell, and based on the position of our neighbour cells, we determine what each cell will look like. Here is you can see all of the different cases: 
Afbeeldingsresultaat voor marching square
Triangulate squares:
The next step is to triangulate the mesh based on the data we created with these marching squares. I had barely ever created a mesh in code before so it took some time for me to really grasp what I was doing here ;)
However, what we want is to be able to devide these different shapes into triangles, that will together form the mesh. 
Important about this is that we make sure to fill these triangles clockwise, so that the normals will be correctly. Furthermore the triangles should start where the 'open space' starts. So for the 'single pentagon 1211' we start at the top center, and go from there to the center right to the bottom right to create the first triangle.
This will be really usefull if we need to know the bounds of an open area!

Creating the walls:
To create the walls, I had to figure out where the outlines where of the flat mesh. Luckily there is one simple rule for this: each vertice is part of a triangle, and if two vertices are only share one triangly they are part of the same outline. You can see it displayed underneath: there are 5 vertices, and the two white vertices only share triangle 'A'.

Once I have the outlines, it is quite easy to extrude this downwards. What I did was loop through all of the outline-vertices, and create triangles from them by adding vertices below these outline-vertices as well and then connecting them.

The Result:

To give you an idea of what it looks like now, I've splitted the generation process over time. Here is the result so far:

zaterdag 24 maart 2018

Desert Bandits: A Procedural Dungeon Crawler!

Desert Bandits

The concept: 

Desert Bandits is WIP game about treasures, danger, and bandits that will try to kill you for your treasure.

How it will be made:

The game will be played in a procedurally generated dungeon, and the bandits(AI) will behave using a Utility System.
To make this game I am using C# and Unity. The foundation for the Utility System has already been layed in a previous school-assignment of mine.
The focus of this project will be on the dungeon, which I will create using Cellular Automata.

Here is a little preview on what I have so far with the dungeon: