Dungeon Generation algorithm

Source: Internet
Author: User

http://www.gamasutra.com/blogs/AAdonaac/20150903/252889/Procedural_Dungeon_Generation_Algorithm.php

This post explains a technique for generating randomized dungeons the was first described by Tinykeepdev here. I ' ll go over it in a little more detail than the steps in the original post. The general and the algorithm works are this:generate roomsfirst you wanna Generate some rooms with some width and height That is placed randomly inside a circle. Tkdev ' s algorithm used the normal distribution for generating class sizes and I think that's generally a good idea as It gives parameters to play with. Picking different ratios between width/height mean and standard deviation would generally result in different looking dunge Ons. One function you might need getrandompointincircle:
functionGetrandompointincircle (RadiusLocal T=2*math.pi* Math.random () local u = math.random ()  +math.random () local R = nil if u > 1 then R = 2-u else R = u end return radius*r*math.cos (t), Radius*r*math.sin (t) end     
You can get more info about how that works exactly here. And after this you should is able to does something like this:  one very important thing so you had to consider is, since you ' re (at least conceptually), dealing with a grid of the tiles you had to snap everything to that same grid. The gif above the tile size is 4 pixels, meaning this all-positions and sizes is multiples of 4. To does this I wrap position and width/height assignments in a function so rounds the number to the tile size:
  function roundm (n, m)  return math.floor (((n + m -1) /m)) *m end             --now we can change the returned value from Getrandompointincircle to:function getrandompointincircle (  radius)   ... return roundm (Radius*r* math.cos (t), tile_size), roundm (Radius*r *math.sin (t), tile_size) end      

Separate Roomsnow we can move on to the separation part. There's a lot of rooms mashed together in one place and they should isn't be overlapping somehow. Tkdev used the separation steering behavior to does this but I found that it's much easier to just use a physics engine. After your ' ve added all rooms, simply add solid physics bodies to match each of the "s" position and then just run the Simulati On until all bodies go to sleep. In the GIF I ' m running the simulation normally if you're doing this between levels you can advance the physics Simul  ation faster. The physics bodies themselves is not a tied to the tile grid in any-to-do, but when setting the "s position you wrap it W ITH the ROUNDM Call and then you get rooms that is not overlapping with each other and that also respect the tile grid. The GIF below shows this in action as the blue outlines is the physics bodies and there ' s always a slight mismatch betwee n them and the rooms since their position is all being rounded:  one issue that might come T to has rooms that is skewed horizontally or vertically. For instance, consider the game I ' m working on:  combat are very horizontally oriented and so I probably want to The rooms being bigger in width than they is in height. The problem with this lies on how the physics engine decides to resolve its collisions whenever long rooms is near each O Ther:  as you can see, the dungeon becomes very tall, which are not ideal. To fix the We can spawn rooms initially inside a thin strip instead of on a circle. This ensures the dungeon itself would have a decent width to height ratio:  to spawn randomly insidE This strip we can just change the ' getrandompointincircle ' function to spawn points inside a ellipse instead (in the GI F above I used ellipse_width =and ellipse_height =):
functionGetrandompointinellipse (Ellipse_width, Ellipse_height)Local T=2*Math.PI*Math.random ()Local U=math.random () +math.random () local R = nil if u > 1 then R = 2-u else R = u end return roundm (ellipse_width< Span class= "pl-k" >*r*math.cos (t) / 2, Tile_size), roundm (Ellipse_height*r* math.sin (t) /2, tile_size) end  

Main Roomsthe Next step simply determines which rooms are main/hub rooms and which ones aren ' t. Tkdev ' approach ' s p Retty Solid:just pick rooms that's above some width/height threshold. For the GIF below the threshold I used was 1.25*mean, meaning, if Width_meanand Height_mean is, then rooms with width and height bigger than-be is Selected.   delaunay triangulation + GRAPHN ow we take all the midpoints of the selected rooms and feeds that into the Delaunay procedure. You either implement this procedure yourself or find someone else who's done it and shared the source. In my case I got lucky And yonaba already implemented it. As you can see from this interface, it takes in points and spits out triangles:  after we have the triangles yo U can then generate a graph. This procedure should is fairly simple provided you has a graph data structure/library at hand. In the case of you weren ' t doing this already, it's useful that your the hostel objects/structures has a unique IDs to them so which you Can add those IDs to the graph instead of have to copy them Around.  minimum Spanning Treeafter this we genera Te a minimum spanning tree from the graph. Again, either implement this yourself or find someone who's done it in your LANGUAGE of choice.  the minimum spanning tree would ensure that all main rooms in the dungeon is reachable but also WI ll make it so, they ' re not all connected as before. This was useful because by default we usually don't want a super connected dungeon but we also don ' t want unreachable Islan Ds. However, we also usually don ' t want a dungeon that's only have one linear path, so why we do now are add a few edges back fro M the Delaunay Graph:  this would add a few more paths and loops and would make the dungeon more interesting. Tkdev arrived at 15% of edges being added back and I found that around 8-10% was a better value. This could vary depending on what connected you want the dungeon to being in the End.  hallwaysfor the final part we W Ant to add hallways to the dungeon. To does this we go through each node in the graph and then for each of the other node connects to it we create lines between t Hem. If the nodes is horizontally close enough (their yPosition is similar) and we create a horizontal line. If the nodes is vertically close enough then we create a vertical line.  If the nodes is not close together either horizontally or vertically then we create 2 lines forming an L shape. The test that I used for what ~close enough~ means calculates the midpoint between both nodes ' positions and checks to see If that midpoint ' s x or YAttributes is inside the node ' s boundaries. If They is then I create the line from that midpoint ' s position. If they aren ' t then I create both lines, both going from the source's midpoint to the target's midpoint but only in one Axi S. in the picture above you can see examples of all cases. Nodes-horizontal line between them, Nodes a vertical one and Nodes 118 and 119 has an L Shape. It's also important to note this those aren ' t the only lines I ' m creating. They is the only ones I ' m drawing but I ' m also creating 2 additional lines to the side of each one spaced by tile_size, since I want my corridors to is at least 3 tiles wide in either width or height. anyway, after this we check to see Which rooms that aren ' t main/hub rooms this collide with each of the lines. Colliding rooms is then added-whatever structure you ' re using-to-hold all this by now and they would serve as the Skele ton for the hallways:  depending on the uniformity and a size of the rooms that's initially set you ' ll get Diffe Rent looking dungeons here. If you want your hallways to being more uniform and less weird looking then you should aim for low standard deviation and you Should put some checks in place to keep rooms from being too skinny one-or the other. for the last step we Simpl Y add 1 tile sized grid cells to make up the missing parts. Note that you don ' t actually need a grid data structure or anything too fancy, you can just go through all line according To the tile size and add grid rounded positions (that would correspond to a 1 tile sized cell) to someList. This is where have the have 3 (or more) lines happening instead of the only 1 Matters.   and so after the this we ' re don E!  endthe data Structures I returned from the entire procedure were:a list of rooms (each hostel is just a stru Cture with a unique ID, x/Y positions and width/height); The graph, where each node is points to a, and the edges has the distance between rooms in tiles; Actual 2D grid, where each cell can is nothing (meaning it empty), can point to a main/hub A hallway or can be hallway cell. With these 3 structures I think it's possible to get all type of data you could want out of the layout and then you can fi Gure out where to place doors, enemies, items, which rooms should has bosses, and so on. 

Dungeon Generation algorithm

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.