Continuted world gen work. Can now correctly fill the map with rooms that don't overlap.
authorStan_Lewry <stanley.jml@gmail.com>
Tue, 20 Jul 2021 12:28:22 +0000 (13:28 +0100)
committerStan_Lewry <stanley.jml@gmail.com>
Tue, 20 Jul 2021 12:28:22 +0000 (13:28 +0100)
Main.py
WorldGen.py
Writeup/worldgen.png [new file with mode: 0644]
Writeup/worldgen2.png [new file with mode: 0644]
Writeup/worldgen_example.png [new file with mode: 0644]
Writeup/worldgen_example2.png [new file with mode: 0644]
Writeup/worldgen_example3.png [new file with mode: 0644]
Writeup/worldgen_example4.png [new file with mode: 0644]
test.py [new file with mode: 0644]

diff --git a/Main.py b/Main.py
index 90d02f2..9eaf236 100644 (file)
--- a/Main.py
+++ b/Main.py
@@ -14,7 +14,7 @@ def main():
     random.seed(None)
     renderer = Renderer.Renderer(1920, 1080)
     
-    World.world = WorldGen.generateWorldGrowingRectangles()
+    World.world = WorldGen.generateWorldGrowingRectangles((40, 60), 40)
 
     player = Player.Player(World.worldWidth / 2, World.worldHeight / 2)
 
@@ -46,7 +46,7 @@ def main():
         
         if InputHandler.globalInputState.debugRegenWorld:
             Debug.worldGenDebugRects.clear()
-            World.world = WorldGen.generateWorldGrowingRectangles()
+            World.world = WorldGen.generateWorldGrowingRectangles((40, 60), 40)
         
         pygame.display.flip()
     pygame.quit()
index 7615d88..d685d52 100644 (file)
@@ -1,9 +1,16 @@
+import collections
+from dataclasses import dataclass
+import itertools
+from os import error
 import random
+from itertools import product
+
 import WorldTemplates
 import World
 import GameObject
 import Debug
 
+
 def generateWorld():
     template = WorldTemplates.worldTemplate6
     output = [[]]
@@ -21,10 +28,8 @@ def generateWorld():
         output.insert(y, row)
     return output
 
-def generateWorldGrowingRectangles():
+def generateWorldGrowingRectangles(minMaxRooms, iterations):
     outputWorld = [[]]
-    # generate default
-    # TODO do this with a comprehension or something nice :)
     for y in range(World.worldHeight):
         row = []
         for x in range(World.worldWidth):
@@ -33,8 +38,6 @@ def generateWorldGrowingRectangles():
             row.append(cell)
         outputWorld.insert(y, row)
 
-
-
     class Room:
         def __init__(self, point):
             self.cells = [[]]
@@ -43,8 +46,6 @@ def generateWorldGrowingRectangles():
             self.cells[0].append(point)
 
         def growNorth(self):
-            #newRow = [(tup[0], tup[1] - 1) for _, tup in enumerate(self.cells[0])]
-            # I want to create a new row, that is equal to the first row, but the y coord of each cell is -1
             newRow = []
             for tup in self.cells[0]:
                 newRow.append((tup[0], tup[1] - 1))
@@ -62,7 +63,6 @@ def generateWorldGrowingRectangles():
             self.minX -= 1
         
         def growSouth(self):
-            #newRow = [(tup[0], tup[1] + 1) for _, tup in enumerate(self.cells[-1])]
             newRow = []
             for tup in self.cells[-1]:
                 newRow.append((tup[0], tup[1] + 1))
@@ -71,57 +71,94 @@ def generateWorldGrowingRectangles():
 
     # choose starting points
     # TODO make this controllable
-    points = random.randint(10, 12)
-    #points = 1
-
+    points = random.randint(*minMaxRooms)
     rooms = []
-    for _ in range(points):
-        #maybe limit how close these can be?
-        y = random.randint(1, World.worldHeight - 2)
-        x = random.randint(1, World.worldWidth - 2)
-        #cell = GameObject.WorldCell()
-        #cell.objects.append(GameObject.GameObject(x, y, "floor_tile", False))
-        #outputWorld[y][x] = cell
-        rooms.append(Room((x, y)))
-        Debug.worldGenDebugRects.append((x, y, (0, 255, 0)))
+    excludeList = []
+    possible = True
+    count = 0
+
+    while count != points and possible:
+        possible = len([t for t in list(itertools.product(range(1, World.worldWidth - 2), range(1, World.worldWidth - 2))) if t not in excludeList]) > 0
+        coord = (random.randint(1, World.worldWidth - 2), random.randint(1, World.worldHeight - 2))
+        if coord not in excludeList:
+            excludeList.append(coord)
+            excludeList.append((coord[0] + 1, coord[1]))
+            excludeList.append((coord[0] - 1, coord[1]))
+            excludeList.append((coord[0], coord[1] + 1))
+            excludeList.append((coord[0], coord[1] - 1))
+            excludeList.append((coord[0] + 1, coord[1] - 1))
+            excludeList.append((coord[0] + 1, coord[1] + 1))
+            excludeList.append((coord[0] - 1, coord[1] - 1))
+            excludeList.append((coord[0] - 1, coord[1] + 1))
+            rooms.append(Room(coord))
+            Debug.worldGenDebugRects.append((coord[0], coord[1], (255, 155, 0)))
+            count += 1
+        else: continue
     
+    @dataclass
+    class Rect: 
+        x1 : int = 0 
+        y1 : int = 0 
+        x2 : int = 0
+        y2 : int = 0
+
+    def testCollisions(rA, dir):
+        for rB in [item for item in rooms if not item == rA]:
+            if collide(Rect(rA.minX, rA.minY, rA.maxX, rA.maxY),
+                            Rect(rB.minX, rB.minY, rB.maxX, rB.maxY),
+                            dir):
+                return True
+        return False
+  
+    def collide (a, b, dir):
+        #inflate b to account for 1 block border, idk why this needs to be 2 and not 1 /shrug
+        b = Rect(b.x1 - 2, b.y1 - 2, b.x2 + 2, b.y2 + 2)
+        if dir == (-1, 0):
+            a.x1 -= 1
+        elif dir == (1, 0):
+            a.x2 += 1
+        elif dir == (0, -1):
+            a.y1 -= 1
+        elif dir == (0, 1):
+            a.y2 += 1
+        
+        return (a.x1 < b.x2 and
+            a.x2 > b.x1 and
+            a.y1 < b.y2 and
+            a.y2 > b.y1)
+
+
     # Generate rooms
     # TODO experiment with this
     # TODO make controllable
-    iterations = 12
     for _ in range(iterations):
         for r in rooms:
             direction = random.randint(0, 3)
-            # OPTIONAL EXTRA: CHECK IT WONT INTERESCT WITH OTHER ONE
             if direction == 0:
                 if r.minY > 1:
-                    r.growNorth()
+                    if not testCollisions(r, (0, -1)):
+                        r.growNorth()
             elif direction == 1:
                 if r.maxX < World.worldWidth - 2:
-                    r.growEast()
+                    if not testCollisions(r, (1, 0)):
+                        r.growEast()
             elif direction == 2:
                 if r.maxY < World.worldHeight - 2:
-                    r.growSouth()
+                    if not testCollisions(r, (0, 1)):
+                        r.growSouth()
             elif direction == 3:
                 if r.minX > 1:
-                    r.growWest()
+                    if not testCollisions(r, (-1, 0)):
+                        r.growWest()
 
     # paint generated rooms to output
     for r in rooms:
-        #print ("\n====================================\n")
-        #print(f'minX {r.minX} maxX {r.maxX} minY {r.minY} maxY {r.maxY}')
+        debugCol = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
         for y in range(len(r.cells)):
-            #print (r.cells[y])
             for _, x in enumerate(r.cells[y]):
                 cell = GameObject.WorldCell()
                 cell.objects.append(GameObject.GameObject(x[0], x[1], "floor_tile", False))
                 outputWorld[x[1]][x[0]] = cell
-                Debug.worldGenDebugRects.append((x[0], x[1], (0, 255, 255)))
+                Debug.worldGenDebugRects.append((x[0], x[1], debugCol))
 
     return outputWorld
-
-# So to grow north we need to prepend a new list of the same "width"
-#       the coords are the first lists coords -1
-# to grow east we need to append 1 to each list
-# to grow south we need to APPEND a new list of same width
-# to grow west we PREPEND one to each
diff --git a/Writeup/worldgen.png b/Writeup/worldgen.png
new file mode 100644 (file)
index 0000000..2df41f8
Binary files /dev/null and b/Writeup/worldgen.png differ
diff --git a/Writeup/worldgen2.png b/Writeup/worldgen2.png
new file mode 100644 (file)
index 0000000..64203e9
Binary files /dev/null and b/Writeup/worldgen2.png differ
diff --git a/Writeup/worldgen_example.png b/Writeup/worldgen_example.png
new file mode 100644 (file)
index 0000000..590e265
Binary files /dev/null and b/Writeup/worldgen_example.png differ
diff --git a/Writeup/worldgen_example2.png b/Writeup/worldgen_example2.png
new file mode 100644 (file)
index 0000000..c747cef
Binary files /dev/null and b/Writeup/worldgen_example2.png differ
diff --git a/Writeup/worldgen_example3.png b/Writeup/worldgen_example3.png
new file mode 100644 (file)
index 0000000..3828e3d
Binary files /dev/null and b/Writeup/worldgen_example3.png differ
diff --git a/Writeup/worldgen_example4.png b/Writeup/worldgen_example4.png
new file mode 100644 (file)
index 0000000..29f084c
Binary files /dev/null and b/Writeup/worldgen_example4.png differ
diff --git a/test.py b/test.py
new file mode 100644 (file)
index 0000000..83b8efb
--- /dev/null
+++ b/test.py
@@ -0,0 +1,32 @@
+from dataclasses import dataclass
+
+@dataclass
+class Rect:
+    x1 : int = 0
+    y1 : int = 0
+    x2 : int = 0
+    y2 : int = 0
+
+def collide(rA, rB, dir):
+    # inflate other box by 1 to account for border
+    rB = Rect(rB.x1 - 1, rB.y1 - 1, rB.x2 + 1, rB.y2 + 1)
+    # grow our box in the desired direction is there a way to do this without the if?
+    if dir == (-1, 0):
+        rA = Rect(rA.x1 - 1, rA.y1, rA.x2, rA.y2)
+    
+    if (rA.x1 < rB.x2 and 
+        rA.x2 > rB.x1 and 
+        rA.y1 < rB.y2 and 
+        rA.y2 > rB.y1):
+        return True
+    else: return False
+
+
+#x, y, w, h
+rB = Rect(3, 3, 7, 7)
+rA = Rect(8, 2, 10, 4)
+dir = (-1, 0)
+
+print("collision test begin:")
+print(rB.x1)
+print(collide(rA, rB, dir))
\ No newline at end of file