{"id":78,"date":"2022-09-28T09:38:51","date_gmt":"2022-09-28T09:38:51","guid":{"rendered":"https:\/\/summit-2223-sem1.game-lab.nl\/?p=78"},"modified":"2022-12-06T14:54:38","modified_gmt":"2022-12-06T14:54:38","slug":"dungeon-generation","status":"publish","type":"post","link":"https:\/\/summit-2223-sem1.game-lab.nl\/?p=78","title":{"rendered":"2D Procedural Dungeon Generation"},"content":{"rendered":"\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-28f84493 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:100%\">\n<figure class=\"wp-block-gallery aligncenter has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-full is-style-default\"><img loading=\"lazy\" decoding=\"async\" width=\"559\" height=\"562\" data-id=\"2762\" src=\"https:\/\/summit-2223-sem1.game-lab.nl\/wp-content\/uploads\/2022\/11\/titlecard.png\" alt=\"\" class=\"wp-image-2762\" srcset=\"https:\/\/summit-2223-sem1.game-lab.nl\/wp-content\/uploads\/2022\/11\/titlecard.png 559w, https:\/\/summit-2223-sem1.game-lab.nl\/wp-content\/uploads\/2022\/11\/titlecard-298x300.png 298w, https:\/\/summit-2223-sem1.game-lab.nl\/wp-content\/uploads\/2022\/11\/titlecard-150x150.png 150w, https:\/\/summit-2223-sem1.game-lab.nl\/wp-content\/uploads\/2022\/11\/titlecard-398x400.png 398w\" sizes=\"auto, (max-width: 559px) 100vw, 559px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"592\" height=\"558\" data-id=\"2742\" src=\"https:\/\/summit-2223-sem1.game-lab.nl\/wp-content\/uploads\/2022\/09\/titlecard.png\" alt=\"\" class=\"wp-image-2742\" srcset=\"https:\/\/summit-2223-sem1.game-lab.nl\/wp-content\/uploads\/2022\/09\/titlecard.png 592w, https:\/\/summit-2223-sem1.game-lab.nl\/wp-content\/uploads\/2022\/09\/titlecard-300x283.png 300w, https:\/\/summit-2223-sem1.game-lab.nl\/wp-content\/uploads\/2022\/09\/titlecard-424x400.png 424w\" sizes=\"auto, (max-width: 592px) 100vw, 592px\" \/><\/figure>\n<\/figure>\n<\/div>\n<\/div>\n\n\n\n<p>By Nicky Wu <\/p>\n\n\n\n<div style=\"height:90px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Table of Contents<\/strong>\n<ul class=\"wp-block-list\">\n<li>Introduction<\/li>\n\n\n\n<li>1.&nbsp;&nbsp;&nbsp; Dungeon Generation Algorithms\n<ul class=\"wp-block-list\">\n<li>1.1 Binary Space Partition (BSP)<\/li>\n\n\n\n<li>1.2 Cellular Automata<\/li>\n\n\n\n<li>1.3 Drunken Walk<\/li>\n\n\n\n<li>1.4 Diffusion Limited Aggregation<\/li>\n\n\n\n<li>1.5 Flood Fill\n<ul class=\"wp-block-list\">\n<li>1.5.1 Depth First Search (DFS) and Broad First Search (BFS)<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>1.6 Wave Collapse Function<\/li>\n\n\n\n<li>1.7 Delaunay Triangulation<\/li>\n\n\n\n<li>1.8 Minimal Spanning Tree<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>2.&nbsp;&nbsp;&nbsp; Testing and validation\n<ul class=\"wp-block-list\">\n<li>2.1 Choosing the right foundation<\/li>\n\n\n\n<li>2.2 Choosing PCG algorithms\n<ul class=\"wp-block-list\">\n<li>2.2.1 Drunken Walker<\/li>\n\n\n\n<li>2.2.2 Cellular Automata<\/li>\n\n\n\n<li>2.2.3 Diffusion Limited Aggregation<\/li>\n\n\n\n<li>2.2.4 Wave Collapse<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>3.&nbsp;&nbsp;&nbsp; Implementation\n<ul class=\"wp-block-list\">\n<li>3.1 Room Bounds\n<ul class=\"wp-block-list\">\n<li>3.1.1 Binary Space Partitioning<\/li>\n\n\n\n<li>3.1.2 Drunken Walk<\/li>\n\n\n\n<li>3.1.3 Cellular Automata<\/li>\n\n\n\n<li>3.1.4 Diffusion Limited Aggregation (By using a walker)<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>3.2 Room Regions\n<ul class=\"wp-block-list\">\n<li>3.2.1 Detecting Regions<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>3.3 Placing the walls<\/li>\n\n\n\n<li>3.4 Room Corridors<\/li>\n\n\n\n<li>3.5 Combining Algorithms\n<ul class=\"wp-block-list\">\n<li>3.5.1 Deducting floors<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>3.6&nbsp;Scriptable Objects<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>4.&nbsp;&nbsp;&nbsp; Conclusion<\/li>\n\n\n\n<li>5.&nbsp;&nbsp;&nbsp; What the future holds<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<div style=\"height:47px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h1 class=\"wp-block-heading\">Introduction<\/h1>\n\n\n\n<p>During the first four weeks of the semester, we took a look at different kinds of topics in Game Development such as shaders, performance, Machine learning and procedural generated content.<\/p>\n\n\n\n<p>At the end of the fourth week, I have decided I wanted to do something with PCG since it was the most interesting topic for me. I already wanted to do something with rooms being unique or have a different kind of layout to them and came up with the following idea:<\/p>\n\n\n\n<p><em>\u201cCreating dungeon rooms by using multiple PCG algorithms\u201d<\/em><\/p>\n\n\n\n<p>I find this idea quite interesting because a lot of PCG algorithms creates a certain pattern or something unique that only this algorithm can produce. By combining these, I think it might result to something more unique. For this R&amp;D project, I have decided to focus on creating a dungeon by using PCG algorithms with an emphasis on unique room structure.<\/p>\n\n\n\n<p>In this blog post I\u2019ll talk about the dungeon algorithms I have looked at, which of the algorithms I used and how I implement it to my framework.<\/p>\n\n\n\n<p>I have made two small sketches of how I want the level to look like and what the algorithms should output.<br><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/9o2_MSWHj7HVP8cDEE2hUWus4pGDR9heWqoY9overfUzAQpNBm7LgoN7a46s0zp_qYV0vdSTbe5GIXk8Xj8Y9rxdW9vWUZ3ZWeatX_mMuymaDqS6AEo8AxSzORNUWb-geBNlQqr5ARdkH8XTmEpuyYoDFve8ZV1lbKt4nGFe4posuXxftGupLi3S_Isy-yTr\" width=\"276\" height=\"290\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/lh3.googleusercontent.com\/z_OJtE4T9KtbVEiWQxncLUe8gu8J5GcifWfdim_7_QUm0DIlmtzsywR8TXXFxgm7VVfeb2JIOHxQ1HqcWxcpjsY7hhiawzNAOy1qgrD2hs8b_rkvPRxM2AlFseyvSh9MEl0ru4P9y1JtkSCV9rHw0x-8iLheyucDOgfcs59YZfPjXwNgE7MGg9KWnWYOXTG3\" width=\"326\" height=\"284\"><\/p>\n\n\n\n<h1 class=\"wp-block-heading\">1. Dungeon Generation Algorithms<\/h1>\n\n\n\n<p>There are a lot of different kinds of procedurally content generation algorithms which are used in games. In this chapter I\u2019ll explain how some of these popular algorithm works in a high-level context.&nbsp;&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1.1 Binary Space Partition (BSP)<\/h2>\n\n\n\n<p class=\"has-text-align-left\">This algorithm is very popular among the PCG games since it is easy to implement and understand. This algorithm sub-divides a (room) boundary until it reached its desired width and height. Then these boundaries will get added to a binary tree [See figure 1]. You can use this tree to connect every room and use the room boundaries for other purposes.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><img decoding=\"async\" src=\"https:\/\/lh5.googleusercontent.com\/Cqy5L6nJEEsn18x9pk3I7_xV_AbUCpUukt2OtFSlocPKM-GR9TDgSuKN7teHluSCyjGTMSB4A3td-qOup4ayEWG7mpqA5JETFcozQAZHEdjeP4I4pIxQaf9eRgqndHQ_3IwUaf3w4l_IJiVm6BbVRlRdiydSXSBTHhRJPlOvKmPcyurmhvvPSAR22Lwo2tgJ\" alt=\"https:\/\/media.geeksforgeeks.org\/wp-content\/uploads\/20200630014725\/space.jpg\" \/><figcaption class=\"wp-element-caption\">Figure 1: Binary Space Partitioning (GeeksforGeeks, 2020).<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">1.2 Cellular Automata<\/h2>\n\n\n\n<p>Another popular level generation algorithm is called Cellular Automata. This is an algorithm that uses the cells\u2019 neighbors to determine the outcome after each iteration. The cells have two possible states; dead and alive.&nbsp;<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/summit-2223-sem1.game-lab.nl\/wp-content\/uploads\/2022\/11\/image-73.png\" alt=\"\" class=\"wp-image-2232\" width=\"320\" height=\"320\" srcset=\"https:\/\/summit-2223-sem1.game-lab.nl\/wp-content\/uploads\/2022\/11\/image-73.png 699w, https:\/\/summit-2223-sem1.game-lab.nl\/wp-content\/uploads\/2022\/11\/image-73-300x300.png 300w, https:\/\/summit-2223-sem1.game-lab.nl\/wp-content\/uploads\/2022\/11\/image-73-150x150.png 150w, https:\/\/summit-2223-sem1.game-lab.nl\/wp-content\/uploads\/2022\/11\/image-73-401x400.png 401w\" sizes=\"auto, (max-width: 320px) 100vw, 320px\" \/><figcaption class=\"wp-element-caption\">Figure 2: Cellular Automata Example (Celusniak, 2019)<\/figcaption><\/figure>\n\n\n\n<p>These rules are defined in the algorithm and there are a lot of rule sets to use for this algorithm. One of the popular rule set is called \u2018Conway\u2019s Game of life\u2019. This rule set creates cave-like levels which is perfect for a cave level.<\/p>\n\n\n\n<p>The base cellular automata implementation can be summarized into these steps:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Fill the grid with noise (wall and floor tiles)<\/li>\n\n\n\n<li>Place random open cells in the grid&nbsp;<\/li>\n\n\n\n<li>Use a rule set to determine the fate of the cell in the current generation<\/li>\n\n\n\n<li>Get the next cell and repeat step 3 until desired output&nbsp;<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">1.3 Drunken Walk<\/h2>\n\n\n\n<p>The drunken walk algorithm involves a walker who randomly choose one of the four direction (north\/south\/east\/west) based on its current position to walk to. These walk points are saved in a list and are used to determine when the position of the grid is open or not.&nbsp;<\/p>\n\n\n\n<p>This algorithm is reliable to create levels because all the spaces are connected due to it being walked on once by the walker. You can add a fill percentage to the walker as well, to let it know how many spaces it still need to open in order to finish the generation.<\/p>\n\n\n\n<p>This can be summarized into these steps:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Fill the grid with walls (closed objects)<\/li>\n\n\n\n<li>Pick a start position for the walker<\/li>\n\n\n\n<li>Pick a random cardinal direction (north\/south\/west\/east)<\/li>\n\n\n\n<li>Take a step in this direction and save this point<\/li>\n\n\n\n<li>Repeat from step 3 until the desired amount of opened cells is reached<\/li>\n<\/ol>\n\n\n\n<p>This is the most basic form of the drunken walk, there are more complex and optimized algorithms based on the Drunken Walk algorithm to get different outputs and .<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1.4 Diffusion Limited Aggregation<\/h2>\n\n\n\n<p>Despite its complex name, the algorithm is quite simple to understand. It makes use of random placed particles throughout the canvas and moves randomly.<\/p>\n\n\n\n<p>&nbsp;When a particle hits a floor or something that is defined as \u2018open\u2019, the position of that particle will be added to the floor. Then it repeats with all the other particles until it reached a certain fill percentage. There are a lot of ways to implement this and it will create different kinds of fractal patterns.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/lh5.googleusercontent.com\/6M5pBodH9ABGnBfOlNJn06po2FhIHIhU5gHhIHQ6-nQI55P6rDpHbkVtUapkqfmej9zG1R4Sgp0Fy0TFj-SOP_dVLtvs5hSNiUZqtRUtuHzvlwPzc_9SQTZH59MZt7Sfx7TyuaZCwGT_5GY0oDJNaFnkv1tiBtxiM2f9DhY1PrFdAF5rTpRJEEQiS3rORrTQ\" alt=\"Diffusion-Limited Aggregation: A Real-Time Agent-Based Simulation - Wolfram  Demonstrations Project\" width=\"385\" height=\"262\" \/><figcaption class=\"wp-element-caption\">Figure 3: DLA simulation (Sayama, 2011)<\/figcaption><\/figure>\n\n\n\n<p>In figure 3, you will see how these particles connect with each other in order to create a fractal pattern. The blue particles will move indefinitely until it hits one of the red particles. The red particles can be seen as the \u2018floor\u2019 or \u2018open\u2019 tile.&nbsp;<\/p>\n\n\n\n<p>The basic implementation can be summarized into these steps:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Create a grid and spawn particles in the grid<\/li>\n\n\n\n<li>Make the particles move at random directions<\/li>\n\n\n\n<li>Convert some of the particles into floor tiles so they won\u2019t move<\/li>\n\n\n\n<li>When a particle touches a floor tile, turn it into a floor tile<\/li>\n\n\n\n<li>Repeat step 4 until desired fill amount<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">1.5 Flood Fill<\/h2>\n\n\n\n<p>The Flood Fill algorithm is used to detect all the tiles that belongs to the current region. The region is based on where you start. You can compare it to the \u2018paint bucket\u2019 tool in any paint program. Where it will eventually iterate over all the cells in the region.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/lh5.googleusercontent.com\/r_HS-SJ2fOG-Ck4O0edk99JXnO2vdiw4xxP6WIbMvLx8kJ6lURCgbfefWY4HrPyovZY9XUyYPeFv7HEt8LKlrIlnaz8cMva4t3mMhoT53IAgXGHmew5hUrl5xUzOsM-o5o2_AkR6-v7F5zFWZ02gjeyLdvbSjqHPrWSMKYdQRufGBcEO1ns0C_DuxkHMu-YA\" alt=\"https:\/\/www.algorithm-archive.org\/contents\/flood_fill\/res\/example.png\" width=\"184\" height=\"92\" \/><figcaption class=\"wp-element-caption\">Figure 4: Flood Fill Visual (Arcane Algorithm Archive, n.d.)<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">1.5.1 Depth First Search (DFS) and Broad First Search (BFS)<\/h3>\n\n\n\n<p>These methods of flood fills are used to change the way how the flood fill behaves. In the depth first search, the algorithm focuses first on getting towards the deepest part of the region. The broad first search is focusing on the surface, where its neighbors will get checked next iteration.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1.6 Wave Collapse Function<\/h2>\n\n\n\n<p>This algorithm makes use of the way the sprite is connected with other sprites. These are used to set the rules for what the algorithm can output for certain cells in the grid.&nbsp;<\/p>\n\n\n\n<p>The algorithm starts to put a random sprite in the grid and starts from there.&nbsp; Based on the adjacent cells, the algorithm gets a list of possible sprites to put in the adjacent cell. This will get repeated until every cell has been drawn.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/lh3.googleusercontent.com\/1z-VHn61wJbGFzdRyf5yR7bZHLaLZQF9KYc1Er5k4oTPMtLhhJApJt_3HT9zCCRz4ez4TmjBzATYER9DuNjXv_UEhSg5-baRinW_RgT2HaGqXWY4E9eiaDy29uUi1gH2ZdaDGZZ40xss4ikkYjpbOaxiTvB9kw2d76l64vDwnjXfUd9NCHZcwlDoorfqwNtN\" alt=\"https:\/\/robertheaton.com\/images\/wfc-examples.png\" width=\"307\" height=\"206\" \/><figcaption class=\"wp-element-caption\">Figure 5: Wave Collapse Examples (Heaton, 2018)<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">1.7 Delaunay Triangulation&nbsp;<\/h2>\n\n\n\n<p>\u201cBy definition, a Delaunay triangulation is a triangulation in which no vertex lies within the circumcircle of any triangle.\u201d (Simpson, 2015)<\/p>\n\n\n\n<p>Delaunay triangulation is a mesh algorithm to connect vertices together and keep making triangles out of it by using its edges. Watson\u2019s method is one of the more popular algorithms to implement this algorithm.<\/p>\n\n\n\n<p>There are a lot of application for Delaunay triangulation despite it outputs a meshes. You can use it in a different context as well which doesn\u2019t involve modeling.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1.8 Minimum Spanning Tree<\/h2>\n\n\n\n<p>A minimum spanning tree is useful to find the shortest path to connect all the vertices with each other. In game context, this tree can be used to find the shortest path to connect all the rooms with each other. The vertices can be seen as room centers instead. Delaunay Triangulation can be used in conjunction with the minimum spanning tree.<\/p>\n\n\n\n<p>There are a lot of methods to implement this algorithm, one of the more popular algorithm is called Primm\u2019s algorithm.&nbsp;<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/EtXLdxsH373pFA9KMqg5FctHaNaUbTMxIMBvXdHiPEFyfQSM7GLI6anSS-IdzS9oPycozRKlIeDQ7XlrWohQY5LbJV_2JMwMXVMIHr_OX1MI8oN-Es_9C1yu2vLGnatGOlO2ytsi0W7aAsCyPYIAKKex3vVeprgyYGwBPsOYrydOvyyQgLpHnk1T2kWLzfUR\" alt=\"https:\/\/miro.medium.com\/max\/451\/1*-gNoEeTMGYnCG5SSLi1Wtg.png\" width=\"330\" height=\"165\" \/><figcaption class=\"wp-element-caption\">Figure 6: Minimum Spanning Tree Visual (Chothe, 2021).<\/figcaption><\/figure>\n\n\n\n<p><strong>Primm\u2019s algorithm<\/strong><\/p>\n\n\n\n<p>Primm\u2019s algorithm starts with a vertex, then check its edges. It will then choose the edge with the lowest value. Then it will go to the next cell, the one that the chosen edge is connected to. All the vertex that has been visited will be put in a tree as well in case of a loop forming in the tree.<\/p>\n\n\n\n<p>This method is also known to be greedy since it always try to choose the lowest value without considering the other vertices.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">2. Testing and validation<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">2.1 Choosing the right foundation<\/h2>\n\n\n\n<p>I want to have a base project to work on; in order to implement the algorithms without having compatibility issues. I have searched around on the internet for a tutorial which also meets the following criteria:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>The framework contains two of more PCG algorithms that I have researched above<\/li>\n\n\n\n<li>The tutorial also looks back at previous code and refactor it<\/li>\n\n\n\n<li>Tutorial covers flexibility where users can simply play around with the framework without having the need to change tons of parameters<\/li>\n\n\n\n<li>Adding a new PCG algorithm should be fairly straightforward<\/li>\n\n\n\n<li>The framework makes use of a hashset to place the floors or walls etc<\/li>\n<\/ol>\n\n\n\n<p>There were a lot of tutorials that makes use of a 2D array or a list and they don\u2019t look back to refactor the code. These kinds of tutorials did not meet the criteria. I did found one tutorial series that fits the stated criteria which was the tutorial series from Sunny Valley (Sunny Valley Studio, 2020)<\/p>\n\n\n\n<p>Despite the long tutorial, it did cover a lot of the topics that I want to learn about. One of the many things are scriptable objects. Which are used to save the parameters for the algorithm. These can be used to get good results quickly.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2.2 Choosing PCG algorithms<\/h2>\n\n\n\n<p>I want to have three algorithms which one can fit in each criteria:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Algorithm outputs a cave-like room<\/li>\n\n\n\n<li>Algorithm outputs a pattern<\/li>\n\n\n\n<li>Algorithm outputs a chaotic\/random room<\/li>\n<\/ol>\n\n\n\n<p>All the algorithms should be customizable as well so it will be possible to influence the output.<\/p>\n\n\n\n<p>I have tested the following algorithms:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Drunken Walker<\/li>\n\n\n\n<li>Cellular Automata<\/li>\n\n\n\n<li>Diffusion Limited Aggregation<\/li>\n<\/ol>\n\n\n\n<p>Go to the implementation chapter for more information on how I implemented these algorithms.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2.2.1 Drunken Walker<\/h3>\n\n\n\n<p>The drunken walker outputs a random room, without any constant pattern. Every time you run this algorithm, it will generate a different kind of room. This drunken walker can be expanded as well to create more random rooms. The problem is that you don\u2019t have a lot of structural control to this algorithm which isn\u2019t a big issue for me. It will output a different kind of room depending on the parameters you give to the algorithm.&nbsp;<\/p>\n\n\n\n<p>I have implemented this in the framework and it seems to be fit the third criteria.<br><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/Kgwz6bWgTcFBRweSJAxxCK3XAurrznIU3hcK69ORRwMez8_ygUn0eKbdsgOQf-kVoNZs3FiAruBtEI3ObWJvlMREtStbS3fAl1peyjK4tngmqkqmNlwBMhpZBKwHSu4mo-t3KikvZJkzalD6vYqv9kuxP8hDLSC27HWnU5_wyd5oHTLon38SfS5ObkkwcvDb\" width=\"192\" height=\"190\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/lh6.googleusercontent.com\/TG717vaaogO0U0oeXo9T1Gt06ohZPy5eczrLEdKzH1TL3RiZLJige8yIKnVCD-Rth1AVnX34Q1XOZtZ-anEACg20RzC1Pnp52n9wCHC02TZrfHIxDKYn6HMKge7zCMoFTQXda_ZxG5fQPJI8wCdhM4bgUBxMxzjGPvtrCDsv6zz30bnVlo_LZnX_YatFsoFM\" width=\"174\" height=\"180\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/CfUO--nO73pDAxJ1pdeAr5cilX5-7S59EDkXqZiito-VocfENsgasdK8VyfzVeeeg_gv9yLaLnIkwCFGhpsuE2mLx4WPskMBp3dVf052svWagGbSbQza_cNA5Do5wOrEgYTNIetvFGidBXTnsbvXJtbU1sLNgEj1vCkmtaiSq90vhjn5wF41eenGOff__AbX\" width=\"149\" height=\"155\"><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2.2.2 Cellular Automata<\/h3>\n\n\n\n<p>This algorithm is pretty interesting, it outputs a different kind of room (structural wise) depending on the ruleset that it uses. It is very easy to just play around with the ruleset since it only uses its neighbors to determine the cells. There\u2019s a different output depending on the ruleset that you use. I have implemented the conway\u2019s game of life and the mazectric ruleset to see what they produce.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><img decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/t5v2AlJEpEWBCAbnQFysj4fvnU4iZ1rNukf5VawWawbtJGtTIwFCuAVKM96ukuSW_U-JXKf9Q2dMfFC7sOF0WOKdbkeVZlRmznUH4x4NIcSE4tJQjqB1lPT_iX-bMhB-seiiLAleCsUFiYmNgDzFq8SdEZnWougcasz_mKde5FpNfS9x3APFIJwjkStnJOaY\" alt=\"\" \/><figcaption class=\"wp-element-caption\"><em>Figure 7: <em>Cellular Automata Output (Mazectric)<\/em><\/em><\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><img decoding=\"async\" src=\"https:\/\/lh6.googleusercontent.com\/d5uY9_BzDDLqYJUknBqcmD7cdmMREWtIAv1N_SN_0FG5B8F4VxQjaHGzS3JlNZhvFiU5zSnnj1aHT_4fduZ68WP8Lfu3xp97JGEzlCbz_sEp8xdlz3KIxce0cyIQhNOKRqqY7gT-ln00OiRA9tJdBsPac8Me_TeOasaHbnaEeOUiAgFIl-koQ35hK0dj4g5b\" alt=\"\" \/><figcaption class=\"wp-element-caption\"><em>Figure 8: <em>Cellular Automata Output (Conway's Game Of Life)<\/em><\/em><\/figcaption><\/figure>\n\n\n\n<p>Conway\u2019s ruleset seems to produce a more cave-like with corridors while the mazectric ruleset, creates a maze with very long hallways. I do think this should fit the first criteria and is very customizable. During the feedback session, I had feedback regarding that this algorithm doesn\u2019t always make all tiles walkable so there\u2019s a percentage of useless floor tiles.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2.2.3 Diffusion Limited Aggregation<\/h3>\n\n\n\n<p>The last algorithm that I have implemented is the diffusion limited aggregation algorithm. I have played around with this algorithm and it seems to keep some kind of pattern based on the method that give to the algorithm. This will fit the second criteria. I\u2019m pretty sure I\u2019ll find more ways to extend this algorithm to create more kinds of patterns.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh3.googleusercontent.com\/vrKdd6w-_1wy-qvUZ-0qAb1HprJriGzf4npHGMO-w7AOHE--4ozwxJOIy_oh7EZTDCF8n_Kj-EEzV4KbPqXaPlVHfQChhUjSseVgqhmz8FK_xKaKbs5zAxYwOQKkQm8082YWdMrYYUR9qQR_0p2Ai7RMQX4t0VtZny237PSB8AArBl7deXYaIz89E6ckyRSX\" alt=\"\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh6.googleusercontent.com\/AwRNyXW_TZO1q0NHwVtZ7d6AsgV0Paz-c6Wzj3eqiDISOR6_o8IzNJqclnn0WQUbVxRLwdX2zuxtJENwNNX2iZfbS1yrfEVIQlKYTs6amV5JDer9XNP74vcNAuVCkICdH67ASCYVKgAQYGuAvzSfwboaDOkKzBdhjET7DHbHMb8J2pAIyWxbECmLs9BVctp4\" alt=\"\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh3.googleusercontent.com\/AiPSDE-2LZZI47vXR4cWO4VPRDjA0kBcUIbAFC-nIdfHNaxpbt3hI7IiSbXbIuiVpn21HdXmughTCIRyycM0YhkjW7gVW0Y8Lx0afi9B_AkyMgCwH8CZNLW2ZPs7FbffEjL2OKBeaZfO5IYk-0RBMUxTOo0hSGiV3jH1xa3UU6NyBjndgBXsXbITfJPBN2xo\" alt=\"\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">2.2.4 Wave Collapse<\/h3>\n\n\n\n<p>For the wave collapse I have used an already existing project because it might be taking too much time for me to implement it in the current framework. I have used this project () to see what the wave collapse is producing.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/lh6.googleusercontent.com\/-k25A8S1FOnOm-z2xwkpKbtOHe4wXq81HhBZK5HXLVguT6NeVDPRmYhPdJSwy6XlpIjVmPozL9lLBkTD9LNMFpS59JR-x5ki7xLSPEvWXM1a6Tlmv2UeVEFZ7JhEyXUZFg7v4PwGoqkfwTN7D4-309_vcS4iz9bpCgrfLN1rlQulflj6s3LfBQ9sxcQslDM7\" alt=\"\" width=\"267\" height=\"282\" \/><figcaption class=\"wp-element-caption\">Figure 9: Wave Collapse Simulator (Donald, n.d.)<\/figcaption><\/figure>\n\n\n\n<p>I played around with the online project and it seems to be producing pretty good results but I don\u2019t think I can make much use of this algorithm since it is really hard to control this algorithm. You only define the rules by saying how the sprite is connected with each other but at the end the algorithm chooses the sprite at random (based from a list of possible sprites). There\u2019s not much customization there besides changing the input (sprites) and how they connect with each other.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">3. Implementation<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">3.1 Room Bounds<\/h2>\n\n\n\n<p>In order to get the rooms with their own bounds, I have used binary space partitioning for it and converted it into an object. Then I have used a hashset to track what position within the bound should be a floor tile<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3.1.1 Binary Space Partitioning<\/h3>\n\n\n\n<p>The binary space partitioning algorithm is used to get all the room bounds in the level and I don\u2019t need the connections between the rooms so I only need a list and a queue to do this instead of a binary tree.&nbsp;<\/p>\n\n\n\n<p>These room bounds are used for the algorithms to create their room. Since I don\u2019t need the connection between the rooms, I only used a queue and a list of room bounds to keep track of the algorithm.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/cREt3BAD_bywS5PaBzyk7Ph3mXdgzN_SPkstYsp89dE6t3-byIXU3paAE528gwipyFepWu8Ix0ztRpSMn7NM2rvSHyZ5KrBvjwQRzJ1Hpwjqb1xFFiUkFPp68cO5apxp55YicgT5dQjJAZAuvgkDT1P9GevW3GMwL-pmsi8jhIX5MAgA_6HrVKbFuF9VSmeA\" alt=\"\" \/><\/figure>\n\n\n\n<p>First I start with one bound; this is the level bounds. Then I split this level bound into two smaller bounds. Every time a bound isn\u2019t at the right size, it will split itself again until it reaches the right size. When it reaches the right size it will stop and add the bounds to the room list.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3.1.2 Drunken Walk<\/h3>\n\n\n\n<p>The way how I implemented this algorithm is by making using a walker and put it at a random spot in a grid filled with walls. But since I have my own algorithm to place walls, this is not needed so a Hashset which represents the floor tiles is enough for me.<\/p>\n\n\n\n<p>I have added a walker who acts like a paint brush and will randomly move throughout the Hashset.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/lh3.googleusercontent.com\/JzPv9w5-XrkUg9ws-vBVuBWkcic9nIFyevqhTMpc-k7S6gwR8Tbo0O0yI4EN9T0jT21jtx48Y75VF7QN16DSpXVzsCBNElDCb3EWOAeb3KpM0Ropm4IV4dIRG_Rwhh9mSebrWXStYzNGVWfN4xaTIMx7ylOxPKxYG0gaHwLxzwTyAbALWY5xnstrwJLFxqmI\" alt=\"\" width=\"339\" height=\"339\" \/><figcaption class=\"wp-element-caption\"><em>Figure 12: Drunken Walker Drawing<\/em><\/figcaption><\/figure>\n\n\n\n<p>The walker it moves at random directions and save the positions that it has previously walked on. These spots are converted into floor tiles and saved in a Vector2int Hashset. This method will be called multiple times until it has opened a certain amount of tiles.&nbsp;<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/zQCpqyf7x02YLWq74RrClR4t4Qs5M3bBb5JOi2bjHTSdgnZ3-N-dORDHGTxzN_IFZNngARBdaAxrlutfrJsbxJliNzzO8UN-l-X1krI6Bmi-tFFOLh6MFSv5Ek7VBJhRS-ZvHWezNz50GQbrmlMO_BdD95_VDi3oh6jyG_LFJ_aePUbJuUc6IMKUlNlJkwl5\" alt=\"\" \/><\/figure>\n\n\n\n<p>The method accepts a start position and the walk length. The start position defines where the walker starts to walk. The walk length defines how many tiles the walker can open before it dies. You can call this method anywhere in the code and it only outputs a Vector2int Hashset.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3.1.3 Cellular Automata<\/h3>\n\n\n\n<p>In order to implement this algorithm, I started to add a way to add noise in the grid (Hashset) which fills the grid randomly with floor tiles. I have added the random starter cells (alive) around the center of the grid.<\/p>\n\n\n\n<p>Then I iterate over the whole grid and used its neighbors and a ruleset to determine the fate of the cell. The cell can either die, live or reborn (alive again). I currently have implemented two rulesets; the Mazectric and the Conway\u2019s Game Of Life.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh3.googleusercontent.com\/_8QtlnsE1GT_d8ihMwrvv4F4O0nvubsZZCsxOqpds4pbZhNUE7YAQTppT3CLSX1vcXfQWFBOiuhKJo9ZOH0LRggOaX-R0jSTvEakRp9XbYp4VLIWkXIidgcasBfRXTO10BrdjAnEoPoSVkjsesg3f7y4bHT_2B4Y5UJ6gtXnXMnAYLuJ32YiqNF5qgl20Oqn\" alt=\"\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/Nwl3-HB7CQFNIv3bh-5WRcmCsLPhtjqFZgq6gZl3EWDy5-rWmJLX8RBsFPMOgDYHiDEvI5UdA0b1rrvG3u6wiBwsFllxZ8BAXkCydLLrUmLG-AnUZcYVuVCLvIZGfwKuaUyDV4TRX4PXx0EjXBpaQterSvU3cHBELFBWsYo4jgjP2CTugPwoOUNq6IaJEs1I\" alt=\"\" \/><\/figure>\n\n\n\n<p>I make use of the 8 directions to determine the neighbors of a cell. I iterate over two for-loops, one for I do a neighbor check via checking all the 8 directions of the current cell. Then I add them in a list and return this to the caller. All the neighbors should be within the grid\u2019s boundaries so it won\u2019t continue infinitely.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/BdUJg3nau7tHZFAgqbGMnbNBXwnTuGGIcxzMy8rnP2v5c5sj0dapRDBgtv16KVJzLt9Bof-9n4SY5SDKYxt8xkp-VE9xBv4h50v0aHWEGhdGKD6or8IhdC9nLi0qOnedMbkDRZaMGc4KEHXLSlEuR3ihg7wEPABlLxaO979BwKaUjtVCYwd03Gah0AxfFL0U\" alt=\"\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh5.googleusercontent.com\/4OgWiuO13Dze_mf738i1GnIjkt1Ky6R_2I4x3kBP01fnWTcfqzNc6wqC8fz32qANKBkkkDD9o7z8cypQoO82udAVO5DaMnJ3BCc6EgovC6eLDXMY-JlqIkOtQ9ZRUjuZYzqh3bnVTVVESMcjRlbqlCCinKZeG5s-gk8PQ_mmwCM0Mcm92Yp43IkBHG2iw86C\" alt=\"\" \/><\/figure>\n\n\n\n<p>By using a switch to determine what ruleset I want to use. In this switch statement I check the cell\u2019s neighbors and determine what the state of this cell is in the next iteration.<\/p>\n\n\n\n<p>The maze ruleset makes use of the amount of neighbors that a cell has. The maze ruleset states that a cell survives when it has at least one or up to 5 neighbors. A cell will be alive when it has exactly three neighbors. This ruleset creates a maze with relatively short hallways, there\u2019s also a modified version which makes long hallway. This ruleset is called \u2018Mazectric\u2019, the only difference is that cells will die if they have 5 neighbors. I wanted the maze to have longer hallways and thus is why I chose for this ruleset instead of the maze one.<\/p>\n\n\n\n<p>I combined and simplified all the rules into two if statements; when there\u2019s more than 4 neighbors, kill the cell and when it\u2019s less the cell is alive.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3.1.4 Diffusion Limited Aggregation (By using a walker)<\/h3>\n\n\n\n<p>This implementation of DLA is based on bracket productions\u2019 implementation (Bracket Productions. (n.d.). Where it is also using a walker to simulate as a \u2018particle\u2019.<\/p>\n\n\n\n<p>The way I have implemented Diffusion Limited Aggregation is a bit different. The normal way of this would be to generate an amount of particles in the grid that randomly moves around the grid. When it hits a floor tile, then the particle will become a floor tile. Then you have to wait until a different particle hits a floor tile.&nbsp;<\/p>\n\n\n\n<p>The reason why I don\u2019t think this will work that well is because not all the particles will hit a floor tile and you have to iterate over all of them. I don\u2019t think this is performant enough which is why I strayed a bit away from the normal implementation. I do plan to test the performance in the future plans.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/mmdAqfhF9VELDSDSdFCVwuAPLStAcrcuqB-ILtOLI7XQ7H87___J4Y586v1Ulwy9axxBo7AP2mXkXNA28x30luWsn8ONmKV9J_Ue8t4aoyCFozo8nIA8oBJ2UG392Gpnym2JfbtE3XqVlkyQiihzSDPby81T9fqlBhdwsv8mlpQErTHIJrFZo3JVgK9T11Qz\" alt=\"\" width=\"344\" height=\"348\" \/><figcaption class=\"wp-element-caption\"><em>Figure 16: DLA Graph Visual<\/em><\/figcaption><\/figure>\n\n\n\n<p>I started opening some random cells in the grid (depending on the method). In case of the center attraction, I open the cells that\u2019s around the center of the boundary. I randomly open tiles if the center attractor is not the chosen method.<\/p>\n\n\n\n<figure class=\"wp-block-image is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/INwE5tcW-6PHSkU3kg2dfvS3d7cBSqhr2W4DC1zNPfYGWyyDLeztXwz6771nmhHx1ZNbC817-E3vH7_GsGoQteyo8FaGmCzGRJ9XjnSK3btc47LlLsKTFHmlE9r9kMbJMqBNq9hd96R_z6VvbaptcrdLa-Wrw-0-2w-gZ00UFJQSY88D1KhebMYAlVXgWKdF\" alt=\"\" width=\"687\" height=\"256\" \/><\/figure>\n\n\n\n<p>Instead of spawning hundreds of particles at once, I started to spawn a single walker, who walks towards a random floor tile. During it the walk cycle, the particle will \u2018jitter\u2019 which simulates the way how the particles are randomly moving in the grid but it still have a higher chance to head towards the right direction. This means that every walker will eventually hit a floor tile. <\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/summit-2223-sem1.game-lab.nl\/wp-content\/uploads\/2022\/11\/image-79.png\" alt=\"\" class=\"wp-image-2658\" width=\"412\" height=\"415\" srcset=\"https:\/\/summit-2223-sem1.game-lab.nl\/wp-content\/uploads\/2022\/11\/image-79.png 599w, https:\/\/summit-2223-sem1.game-lab.nl\/wp-content\/uploads\/2022\/11\/image-79-298x300.png 298w, https:\/\/summit-2223-sem1.game-lab.nl\/wp-content\/uploads\/2022\/11\/image-79-150x150.png 150w, https:\/\/summit-2223-sem1.game-lab.nl\/wp-content\/uploads\/2022\/11\/image-79-397x400.png 397w\" sizes=\"auto, (max-width: 412px) 100vw, 412px\" \/><\/figure>\n\n\n\n<p>The spawn area of a walker is near the boundaries of the room, I also do a distance check if this spawn position is too close to a floor tile. The walker behavior is also called \u2018<strong>Walking inward<\/strong>\u2019. I also have implemented the central attractor and walking outward methods to this algorithm.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><em>Central Attractor<\/em><\/h4>\n\n\n\n<p>This walker method involves a walker who is placed randomly in the room. This walker heads towards the center of the room (or one of the starting positions). Then when it hits the center tile (or any other open tile) it will open the previous tile. This modification creates a room with an open center.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><em>Walking Outward<\/em><\/h4>\n\n\n\n<p>This is similar to the central attractor except it starts the walker at the center and is trying to walk to one of the wall boundaries. When it hits a wall, it destroys the wall and it repeats again until a certain amount of walls are broken.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3.2 Room Regions<\/h2>\n\n\n\n<p>During the feedback session, someone mentioned that some of the floor tiles aren\u2019t reachable, making it useless. I received some feedback of how I can deal with this problem. One of the suggestions was to use the flood fill algorithm to detect the walkable tiles and then find a way to connect these not walkable tiles with the walkable tiles.<\/p>\n\n\n\n<p>Not all floor tiles are walkable after the floor generation. This is where the flood fill algorithm comes in. This algorithm makes it possible to detect all the regions in the room and will assign the tiles accordingly. When a tile isn\u2019t reachable from the main region, it will create a new region.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3.2.1 Detecting Regions<\/h3>\n\n\n\n<p>The way how I implement this is quite simple. I have used the flood fill algorithm for this. I start from a point and add the neighbors (four ordinal directions) to a queue to be checked in the next iteration. This will continue until all of the tile of that region has been added to the list. <\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/summit-2223-sem1.game-lab.nl\/wp-content\/uploads\/2022\/11\/image-80.png\" alt=\"\" class=\"wp-image-2659\" width=\"402\" height=\"307\" srcset=\"https:\/\/summit-2223-sem1.game-lab.nl\/wp-content\/uploads\/2022\/11\/image-80.png 805w, https:\/\/summit-2223-sem1.game-lab.nl\/wp-content\/uploads\/2022\/11\/image-80-300x229.png 300w, https:\/\/summit-2223-sem1.game-lab.nl\/wp-content\/uploads\/2022\/11\/image-80-768x587.png 768w, https:\/\/summit-2223-sem1.game-lab.nl\/wp-content\/uploads\/2022\/11\/image-80-524x400.png 524w\" sizes=\"auto, (max-width: 402px) 100vw, 402px\" \/><\/figure>\n\n\n\n<p>Here I check for a starting point in the (new) region. <\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"701\" height=\"332\" src=\"https:\/\/summit-2223-sem1.game-lab.nl\/wp-content\/uploads\/2022\/11\/image-81.png\" alt=\"\" class=\"wp-image-2660\" srcset=\"https:\/\/summit-2223-sem1.game-lab.nl\/wp-content\/uploads\/2022\/11\/image-81.png 701w, https:\/\/summit-2223-sem1.game-lab.nl\/wp-content\/uploads\/2022\/11\/image-81-300x142.png 300w, https:\/\/summit-2223-sem1.game-lab.nl\/wp-content\/uploads\/2022\/11\/image-81-600x284.png 600w\" sizes=\"auto, (max-width: 701px) 100vw, 701px\" \/><\/figure>\n\n\n\n<p>Now I put their neighbors in a queue to be checked if it belongs to the region.<\/p>\n\n\n\n<p>When there are more tiles that are not reachable, I\u2019ll manually add this tile back to the queue so it will start the flood fill all over again. This repeats until all tiles are added to their own regions.<\/p>\n\n\n\n<figure class=\"wp-block-image is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/EhFvxF74LCsTIINpgeE2T38U3jR3OHZ8SB4GR3gRS-g6HrD9HLWDhwHSLmDX-bTF5Y_51jiZBgmqj66opHDe0-7AsfvbZ4TebBG1rmE0EKLzcb23l7oDDQwfS_nwfi1ZdgPxSTxxGN3sxxDApFl0lzh7joUgdGGnZWm7XRBNVjJNXJm3w8YlrSl17dSgkHKJ\" alt=\"https:\/\/cdn.discordapp.com\/attachments\/1016336564667814018\/1032403047567085611\/unknown.png\" width=\"302\" height=\"397\" \/><\/figure>\n\n\n\n<p>In order to turn these regions into a single region, I used a simple distance check between these two regions. The two closest coordinate will have a walker that walks from point A to point B in order to open these regions. It repeats this until there\u2019s only one region left.<\/p>\n\n\n\n<p>If you can look at image below, you will see a cell with an orange background, this means that this tile has been opened because of the walker. To make it less performant heavy, I limited this algorithm to a room instead of the whole level.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh3.googleusercontent.com\/E28PSOvUaJTWFbNMTYW9YmP9PhPF2BWdxgk3TGLSbW2-S0ggsDzl7MhBJFUu1N-p8zYo2JoHH-wLGu794tPk05unPiPsU2q-ZVbeMQ9DTbtlxvJTD8qXK1gJyH72YsK5Uee-c_ccrWv1QPubXaNEkKdZlkk64U9oQDp5csIyy5V4vyJxUYn-ZncsJyFBvIGb\" alt=\"https:\/\/cdn.discordapp.com\/attachments\/1024650869200920576\/1033123857210548316\/unknown.png\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">3.3 Placing the walls<\/h2>\n\n\n\n<p>In order to place the walls, I iterate over all the floor tiles and check its neighbor.&nbsp;<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/JDJcYnTVRi-Zcwu-02W-sfdsVKnX4EhfT1njtMBpi6GadmhrPEOWkAShBWOHjb7TKSU07GvFqXDf6hiwT-QFfm-03K4Mhc4nOKKcpHKMJyBT9PsC8t_yzfjeU1e-gAkTKidJrFRCMOwaU3jOG8AFiKHeQHcxQzs6gcWf0WKfeWxtl1Hn2voKogFmQiDotKwq\" alt=\"\" \/><\/figure>\n\n\n\n<p>I check all the eight directions for the neighbors and when there\u2019s no neighbor in that direction (an empty tile), a wall will be placed there. This will be done for the corridor floor tiles as well.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3.4 Room Corridors<\/h2>\n\n\n\n<p>I also wanted to connect the rooms by using corridors. The current implementation of this is by using a walker that goes from one room center to the other. All the tiles the walker has walked on, will be turned into corridor floor tiles.&nbsp;<\/p>\n\n\n\n<p>To make sure the walker doesn\u2019t walk to the same room, I have created a list of rooms then choose a random index to start then check the shortest distance to the next room. After the walker has walked to that room center, I remove the previous room then the walker repeats with all the other rooms.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh3.googleusercontent.com\/B5TZ3rlTYMKV6sXIsJBgyFf33sHgdXVUd4sk2a6XlabP0DqwyXeZr5qx-xiircNHtAwO57n-v1T03KS6vLKa1zPk-7vmP3FXJK-gjXhQ02DiUOy18S9EC9tCj-R2usfmpJuDWpXf_hpFP_3OKcjGNEesLNrrdsIVXTw3dJdcpGMhUFU7ZtydBDMsWAPUY3J8\" alt=\"\" \/><\/figure>\n\n\n\n<p>As you can see on the image above, there\u2019s no way to know when the walker goes through a room, it will create a corridor that goes through the rooms. This is not a result that I want to see. I could used the connections that are created through the BSP algorithm but then I have a problem with the dungeon being too linear.<\/p>\n\n\n\n<p>This could be fixed if I used the Delaunay Triangulation algorithm. Where I use the room center to connect with each other (I see it as a vertex). Then I can use the edges of the triangles to connect the rooms together. By creating a minimum spanning tree, I can get the shortest path to connect all the rooms. Then I can use the remaining edges to make loops in the dungeon so it won't be linear. Unfortunately I did not have enough time to implement this. <\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/summit-2223-sem1.game-lab.nl\/wp-content\/uploads\/2022\/11\/image-82.png\" alt=\"\" class=\"wp-image-2704\" width=\"263\" height=\"262\" srcset=\"https:\/\/summit-2223-sem1.game-lab.nl\/wp-content\/uploads\/2022\/11\/image-82.png 604w, https:\/\/summit-2223-sem1.game-lab.nl\/wp-content\/uploads\/2022\/11\/image-82-300x300.png 300w, https:\/\/summit-2223-sem1.game-lab.nl\/wp-content\/uploads\/2022\/11\/image-82-150x150.png 150w, https:\/\/summit-2223-sem1.game-lab.nl\/wp-content\/uploads\/2022\/11\/image-82-401x400.png 401w\" sizes=\"auto, (max-width: 263px) 100vw, 263px\" \/><\/figure>\n\n\n\n<p>I did manage to use a Delaunay Triangulation library and applied it to the framework. But since I don't have a minimum spanning tree, I can't really use it to draw the corridors.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3.5 Combining Algorithms<\/h2>\n\n\n\n<p>In order to combine the algorithms to create one room, I have used a hashset for it. A hashset is a unordered list data type where all the elements are unique. It makes use of a \u2018hash\u2019 value to determine when the element is unique or not. Since I just needed to combine the output of the algorithms, I merge them in a single hashset. I only have to make the algorithm output a hashset in order to make this work. The hashset will automatically know what floor tiles to add and what to ignore.<br><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/lh5.googleusercontent.com\/8unOIiJzHH3UeHjB8vw3rosROgX9b1lh-m0OQ2jlJcSd1N1_W_zAFiY11uLi_uIqirS9dsnGngP9V-wBF4X7wDEEZJHezc2W1qgVC5mZpF8DRBVvoyxBZqdZGcO1vuagEUHmlmF9Cs5sEs3KivTO7Q18AdJcgp-sKwy3V80qvmWXvcu9MFzRxWdxp8OLpu4z\" width=\"510\" height=\"86\"><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3.5.1 Deducting floors<\/h3>\n\n\n\n<p>One of the feedback that I have receive was that the rooms were sort of the same and suggested to use some of the algorithms to deduct the floor tiles instead. This was very interesting and creates even more interesting rooms. So to implement this, I just deducted the floor positions from the hashset instead of adding it to the hashset. Fortunately I do not have to worry about tiles being inaccessible because the flood fill algorithm will take care of that.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh6.googleusercontent.com\/6pBE4fD_w47jSZ3FYD1y9Af6SjD-lYn8CEDF4HFfdV0ETmHPD4k6EI9dvLLZUu_sj-Y_p2OgfyGCLhEB8pIPufm46PwXkqJWqXob5RLxQWp0xBgJvlJy06XcjOzbWwSKxNHlt3F7FpJqfWxDkBW5fSh_qISHAppmk75i1qM1ICoUf6AD5jdY3rzoT_5FY_Gx\" alt=\"\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/66JfAUaBybkibFBi4zgekEFqDhbCqRZocVJMEcTbIT_yaOggGj2xvjvBKKmElFi_zb9MZYwmHz4ycjV9Fc5lTxMcSffCdVB_4lbK3p-ds7HFcQpw6uCHnn5JjcG00VNul7Fi7lVzLS6yjTDBARJmfHwyFH7zz7Yyp_CHOfyaomiCMDisyj6aUB4gfOHT65cG\" alt=\"https:\/\/cdn.discordapp.com\/attachments\/1024650869200920576\/1037869022915600504\/unknown.png\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">3.6 Scriptable Objects<\/h2>\n\n\n\n<p>Since the base framework makes use of the scriptable objects to store parameters for the algorithms, I did the same with the other algorithms that I have implemented.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh5.googleusercontent.com\/1dZL6qfg0U5YMQBb-KZ9cKUuBXxxfGCicuU1aI_NZqmnksaElCi43W0A-LCTOfTXewaku2Qj2zq7iSKb8j6_qfvX5eYzDiT32zup6eDz-FzVIzecxoYeji1BNMOd6NJCArzQm8s9kkNuOy3oyKhtP-rxN5GnbeNeohojp7I9A3wzzBB75vUbgboEYnaZgQ72\" alt=\"\" \/><\/figure>\n\n\n\n<p>This is an example of how a scriptable object with parameters would look like.<\/p>\n\n\n\n<p>I went a bit further and implement a way to put these parameters in a list. This is called an algorithm set which contains a list of these scriptable objects. You can add the algorithm sets to the room level parameter scriptable object which will be used for the dungeon generator. So if you want the dungeon generator to use multiple algorithm sets for the room generation, you can.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh6.googleusercontent.com\/1OG28JFjVDICbBykkDQk2OGJWWbswkv9XY5ZaH4V62bl7Y8AzRd_hRA-VLeUznz52Uak2mZ52TvPJxJJatSqMizDfJsc_fzausmgcrF38NYq8WYihhrjJxzgqZrWWywZH2BHYZSCz06Yt6AwdFGJOM4UyTJkvLus79YuZ9jZSd3yt52_94ig0F54r-sKJ3UI\" alt=\"\" \/><\/figure>\n\n\n\n<div style=\"height:55px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">4. Conclusion<\/h2>\n\n\n\n<p>I have learned a lot during the past few weeks. I never thought there were this many algorithms in the procedural content generation topic. I kept hearing about cellular automata during my study but that\u2019s pretty much all I know about PCG before I started with this semester.<\/p>\n\n\n\n<p>Now that I have implemented some of the PCG algorithms, I have a much better understanding regarding how they work and when you should use it.<\/p>\n\n\n\n<p>Unfortunately I did not reach my goal since it\u2019s missing some of its key features. This will be explained further in the next chapter.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">5. What the future holds<\/h2>\n\n\n\n<p>There\u2019s a lot to improve on this project and there are missing features that are quite important to fix some of the problems.<\/p>\n\n\n\n<p>At this moment I haven\u2019t implemented the Minimum Spanning Tree and Delaunay triangulation, this is really unfortunate because I want to connect the rooms together by using the shortest route. Then I can use the other edges to make loops in the dungeon so it won\u2019t be linear.<\/p>\n\n\n\n<p>The room types are all the same except for the start and end rooms. There can be something added there to check whenever a room should be a different kind of room (like a treasure room).<\/p>\n\n\n\n<p>The way how the walls are placed is static; you don\u2019t really have any control over the kind of wall sprite you want to place there. So improvements can be made in that part of the algorithm.<\/p>\n\n\n\n<p>The implementation of diffusion limited aggregation is still missing some of the features such as being able to mirror the other half.&nbsp;&nbsp;<\/p>\n\n\n\n<p>Flood fill takes a long time to complete, I should see if there's a better way to detect these regions or optimize it further.<\/p>\n\n\n\n<div style=\"height:140px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h1 class=\"wp-block-heading\">Bibliography&nbsp;<\/h1>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Bracket Productions. (n.d.) <em>Diffusion-limited aggregation maps<\/em>. Retrieved October 29, 2022,<a href=\"https:\/\/bfnightly.bracketproductions.com\/chapter_30.html\">https:\/\/bfnightly.bracketproductions.com\/chapter_30.html<\/a><\/li>\n\n\n\n<li>Celebration, R. (2020, October 15). <em>Herbert Wolverson - Procedural Map Generation Techniques<\/em> [Video]. Retrieved October 4, 2022, from YouTube. <a href=\"https:\/\/youtu.be\/TlLIOgWYVpI\">https:\/\/youtu.be\/TlLIOgWYVpI<\/a><\/li>\n\n\n\n<li>Sunny Valley Studio. (2020, December 18). <em>Unity Procedural Generation of a 2D Dungeon - Introduction<\/em> [Video]. Retrieved October 5, 2022, from YouTube. <a href=\"https:\/\/www.youtube.com\/watch?v=-QOCX6SVFsk\">https:\/\/www.youtube.com\/watch?v=-QOCX6SVFsk<\/a><\/li>\n\n\n\n<li>Celusniak, M. (2019, March 19). <em>Cave-like Level Generation Using Cellular Automata<\/em>. Retrieved October 8, 2022, from <a href=\"https:\/\/www.linkedin.com\/pulse\/cave-like-level-generation-using-cellular-automata-martin-celusniak\">https:\/\/www.linkedin.com\/pulse\/cave-like-level-generation-using-cellular-automata-martin-celusniak<\/a><\/li>\n\n\n\n<li><em>OCA:Maze - LifeWiki<\/em>. (n.d.). <a href=\"https:\/\/conwaylife.com\/wiki\/OCA:Maze\">https:\/\/conwaylife.com\/wiki\/OCA:Maze<\/a><\/li>\n\n\n\n<li>Celebration, R. (2020, October 15). <em>Herbert Wolverson - Procedural Map Generation Techniques<\/em> [Video]. Retrieved October 3, 2022, from YouTube. <a href=\"https:\/\/www.youtube.com\/watch?v=TlLIOgWYVpI&amp;feature=youtu.be\">https:\/\/www.youtube.com\/watch?v=TlLIOgWYVpI&amp;feature=youtu.be<\/a><\/li>\n\n\n\n<li>Peterson, G. (2019, October 20). <em>Drunken Walk Algorithm<\/em>. Retrieved October 3, 2022, from<\/li>\n\n\n\n<li><a href=\"https:\/\/blog.bitrageous.io\/drunkenwalk\/\">https:\/\/blog.bitrageous.io\/drunkenwalk\/<\/a><\/li>\n\n\n\n<li>Robert Heaton (2018, December 17)<em> The Wavefunction Collapse Algorithm explained very clearly<\/em>. Retrieved October 24, 2022 from Robert Heaton. <a href=\"https:\/\/robertheaton.com\/2018\/12\/17\/wavefunction-collapse-algorithm\/\">https:\/\/robertheaton.com\/2018\/12\/17\/wavefunction-collapse-algorithm\/<\/a><\/li>\n\n\n\n<li>Donald, M. (n.d.) <em>Wave Function Collapse - Mixed Initiative Demo by Martin Donald<\/em>. Retrieved October 24, 2022, from itch.io. <a href=\"https:\/\/bolddunkley.itch.io\/wfc-mixed\">https:\/\/bolddunkley.itch.io\/wfc-mixed<\/a><\/li>\n\n\n\n<li>GeeksforGeeks. (2020, September 30). <em>Binary Space Partitioning<\/em>. Retrieved October 6, 2022, from <a href=\"https:\/\/www.geeksforgeeks.org\/binary-space-partitioning\/\">https:\/\/www.geeksforgeeks.org\/binary-space-partitioning\/<\/a><\/li>\n\n\n\n<li>GeeksforGeeks. (2022, August 22). <em>Prim\u2019s Minimum Spanning Tree (MST) | Greedy Algo-5<\/em>. Retrieved November 2, 2022, from <a href=\"https:\/\/www.geeksforgeeks.org\/prims-minimum-spanning-tree-mst-greedy-algo-5\/\">https:\/\/www.geeksforgeeks.org\/prims-minimum-spanning-tree-mst-greedy-algo-5\/<\/a><\/li>\n\n\n\n<li>Chothe, A. (2021, December 14). <em>Minimum Spanning Tree Algorithm - AMOGH CHOTHE<\/em>. Medium. Retrieved October 6, 2022, from <a href=\"https:\/\/amogh-chothe18.medium.com\/minimum-spanning-tree-algorithm-78fa9a7a707f\">https:\/\/amogh-chothe18.medium.com\/minimum-spanning-tree-algorithm-78fa9a7a707f<\/a><\/li>\n\n\n\n<li><em>Flood Fill \u00b7 Arcane Algorithm Archive<\/em>. (n.d.). Retrieved October 23, 2022, from <a href=\"https:\/\/www.algorithm-archive.org\/contents\/flood_fill\/flood_fill.html\">https:\/\/www.algorithm-archive.org\/contents\/flood_fill\/flood_fill.html<\/a><\/li>\n\n\n\n<li>Vazgriz. (2021, November 17). <em>Procedurally Generated 3D Dungeons<\/em> [Video]. Retrieved November 1, 2022, from YouTube. <a href=\"https:\/\/www.youtube.com\/watch?v=rBY2Dzej03A\">https:\/\/www.youtube.com\/watch?v=rBY2Dzej03A<\/a><\/li>\n\n\n\n<li>Simpson, C. (2015, February 5). <em>Delaunay Triangulation<\/em>. Delaunay Triangulation. Retrieved November 1, 2022, <a href=\"https:\/\/www.cdsimpson.net\/2015\/02\/delaunay-triangulation.html\">https:\/\/www.cdsimpson.net\/2015\/02\/delaunay-triangulation.html<\/a><\/li>\n\n\n\n<li>Sayama, H. (2011, March 7) <em>Diffusion-Limited Aggregation: A Real-Time Agent-Based Simulation - Wolfram Demonstrations Project<\/em>. Retrieved October 27, 2022, from  <a href=\"https:\/\/demonstrations.wolfram.com\/DiffusionLimitedAggregationARealTimeAgentBasedSimulation\/\">https:\/\/demonstrations.wolfram.com\/DiffusionLimitedAggregationARealTimeAgentBasedSimulation\/<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Used Assets<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/pixel-poem.itch.io\/dungeon-assetpuck\">https:\/\/pixel-poem.itch.io\/dungeon-assetpuck<\/a> (Sprite Pack)<\/li>\n\n\n\n<li><a href=\"https:\/\/opengameart.org\/content\/16x16-game-assets\">https:\/\/opengameart.org\/content\/16x16-game-assets<\/a> (Sprite Pack)<\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/nol1fe\/delaunator-sharp\">https:\/\/github.com\/nol1fe\/delaunator-sharp<\/a> (Delaunay Triangulation Library)<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>By Nicky Wu Introduction During the first four weeks of the semester, we took a look at different kinds of topics in Game Development such as shaders, performance, Machine learning and procedural generated content. At the end of the fourth week, I have decided I wanted to do something with PCG since it was the [&hellip;]<\/p>\n","protected":false},"author":26,"featured_media":2742,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9],"tags":[55,40,30,32,39],"class_list":["post-78","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-pcg","tag-2d","tag-c","tag-generation","tag-procedural","tag-unity"],"_links":{"self":[{"href":"https:\/\/summit-2223-sem1.game-lab.nl\/index.php?rest_route=\/wp\/v2\/posts\/78","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/summit-2223-sem1.game-lab.nl\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/summit-2223-sem1.game-lab.nl\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/summit-2223-sem1.game-lab.nl\/index.php?rest_route=\/wp\/v2\/users\/26"}],"replies":[{"embeddable":true,"href":"https:\/\/summit-2223-sem1.game-lab.nl\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=78"}],"version-history":[{"count":31,"href":"https:\/\/summit-2223-sem1.game-lab.nl\/index.php?rest_route=\/wp\/v2\/posts\/78\/revisions"}],"predecessor-version":[{"id":2825,"href":"https:\/\/summit-2223-sem1.game-lab.nl\/index.php?rest_route=\/wp\/v2\/posts\/78\/revisions\/2825"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/summit-2223-sem1.game-lab.nl\/index.php?rest_route=\/wp\/v2\/media\/2742"}],"wp:attachment":[{"href":"https:\/\/summit-2223-sem1.game-lab.nl\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=78"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/summit-2223-sem1.game-lab.nl\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=78"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/summit-2223-sem1.game-lab.nl\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=78"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}