Java-Gaming.org Hi !
Featured games (90)
games approved by the League of Dukes
Games in Showcase (744)
Games in Android Showcase (225)
games submitted by our members
Games in WIP (825)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Trying to translate code/concept from Dart into Java for proc gen dungeon!  (Read 503 times)
0 Members and 1 Guest are viewing this topic.
Offline phunni

Senior Newbie


Exp: 17 years



« Posted 2017-11-24 17:26:21 »

I'm currently in the process of trying to create my first procedurally generated dungeon and am following this blog post in order to figure it out.

So far things have gone well and I've managed to get a dungeon created that is almost perfect for my needs - except that I wanted to be sure that I could always get from any point to any other point within the dungeon and sometimes it generates rooms that are not connected to the rest of the dungeon.

I couldn't figure out how to fix things based on my existing code and, so I went back to the blog post mentioned above and noticed that he's taking a (slightly) different approach from me when connecting his dungeon up.  I simply looped through all my rooms and made sure they had at least one door connecting them to either another room or a corridor.  The guy writing the post uses a concept of regions that, to be honest, I'm simply not getting.  He  says that he's using the connectors to separate the regions, but, as far as I can tell, that simply gives you each room as a region and then all of the corridors as one large region - but that doesn't seem to be how he's actually implementing it - which is why I'm confused.

Part of the problem is that his code is written in Dart which I'm not at all familiar with.  Much of it I can figure out, but not this section:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
void _connectRegions() {
    // Find all of the tiles that can connect two (or more) regions.
    var connectorRegions = <Vec, Set<int>>{};
    for (var pos in bounds.inflate(-1)) {
      // Can't already be part of a region.
      if (getTile(pos) != Tiles.wall) continue;

      var regions = new Set<int>();
      for (var dir in Direction.CARDINAL) {
        var region = _regions[pos + dir];
        if (region != null) regions.add(region);
      }

      if (regions.length < 2) continue;

      connectorRegions[pos] = regions;
    }

    var connectors = connectorRegions.keys.toList();

    // Keep track of which regions have been merged. This maps an original
    // region index to the one it has been merged to.
    var merged = {};
    var openRegions = new Set<int>();
    for (var i = 0; i <= _currentRegion; i++) {
      merged[i] = i;
      openRegions.add(i);
    }

    // Keep connecting regions until we're down to one.
    while (openRegions.length > 1) {
      var connector = rng.item(connectors);

      // Carve the connection.
      _addJunction(connector);

      // Merge the connected regions. We'll pick one region (arbitrarily) and
      // map all of the other regions to its index.
      var regions = connectorRegions[connector]
          .map((region) => merged[region]);
      var dest = regions.first;
      var sources = regions.skip(1).toList();

      // Merge all of the affected regions. We have to look at *all* of the
      // regions because other regions may have previously been merged with
      // some of the ones we're merging now.
      for (var i = 0; i <= _currentRegion; i++) {
        if (sources.contains(merged[i])) {
          merged[i] = dest;
        }
      }

      // The sources are no longer in use.
      openRegions.removeAll(sources);

      // Remove any connectors that aren't needed anymore.
      connectors.removeWhere((pos) {
        // Don't allow connectors right next to each other.
        if (connector - pos < 2) return true;

        // If the connector no long spans different regions, we don't need it.
        var regions = connectorRegions[pos].map((region) => merged[region])
            .toSet();

        if (regions.length > 1) return false;

        // This connecter isn't needed, but connect it occasionally so that the
        // dungeon isn't singly-connected.
        if (rng.oneIn(extraConnectorChance)) _addJunction(pos);

        return true;
      });
    }
  }


I don't get this code and I think it's partly because I'm simply not understanding the concept of a region as he uses it.  I did try and ask in the comments, but it's an old post, so I'm not expecting a reply there.

So, can anyone help me understand what he means by a region and, if so, help me understand his code?

If it's any help - here is my current attempt at this:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
private void connectRegions() {
        while (rooms.size > 0) {
            Rectangle room = rooms.peek();
            Array<Vector2> connectors = getConnectorsByRoom(room);
            carveDoors(connectors);
            rooms.removeValue(room, false);
        }
    }

    private void carveDoors(Array<Vector2> connectors) {
        int connector = MathUtils.random(connectors.size - 1);
        for (Vector2 connection : connectors) {
            if (MathUtils.random(50) != 0) {
                grid[(int) connection.x][(int) connection.y] = 0;
            } else {
                if (!isNextToDoor(connection)) {
                    grid[(int) connection.x][(int) connection.y] = DOOR;
                }
            }

        }
        Vector2 goodConnector = connectors.get(connector);
        if (!isNextToDoor(goodConnector)) {
            grid[(int) goodConnector.x][(int) goodConnector.y] = DOOR;
        }
    }

    private boolean isNextToDoor(Vector2 cell) {
        int x = (int) cell.x;
        int y = (int) cell.y;
        return grid[x - 1][y] == DOOR
                || grid[x + 1][y] == DOOR
                || grid[x][y + 1] == DOOR
                || grid[x][y - 1] == DOOR;
    }


As I say, it actually works well, but can produce unreachable sections of the dungeon.
Pages: [1]
  ignore  |  Print  
 
 

 
Ecumene (150 views)
2017-09-30 02:57:34

theagentd (225 views)
2017-09-26 18:23:31

cybrmynd (302 views)
2017-08-02 12:28:51

cybrmynd (290 views)
2017-08-02 12:19:43

cybrmynd (298 views)
2017-08-02 12:18:09

Sralse (291 views)
2017-07-25 17:13:48

Archive (979 views)
2017-04-27 17:45:51

buddyBro (1104 views)
2017-04-05 03:38:00

CopyableCougar4 (1681 views)
2017-03-24 15:39:42

theagentd (1431 views)
2017-03-24 15:32:08
Java Gaming Resources
by philfrei
2017-12-05 19:38:37

Java Gaming Resources
by philfrei
2017-12-05 19:37:39

Java Gaming Resources
by philfrei
2017-12-05 19:36:10

Java Gaming Resources
by philfrei
2017-12-05 19:33:10

List of Learning Resources
by elect
2017-03-13 14:05:44

List of Learning Resources
by elect
2017-03-13 14:04:45

SF/X Libraries
by philfrei
2017-03-02 08:45:19

SF/X Libraries
by philfrei
2017-03-02 08:44:05
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!