From: Stan_Lewry Date: Tue, 20 Jul 2021 12:28:22 +0000 (+0100) Subject: Continuted world gen work. Can now correctly fill the map with rooms that don't overlap. X-Git-Url: https://stanlewry.com/index.cgi?a=commitdiff_plain;h=9cc3973ba5f9bae757ca9d6dc3e7ac104bdef59c;p=pyroguelike.git Continuted world gen work. Can now correctly fill the map with rooms that don't overlap. --- diff --git a/Main.py b/Main.py index 90d02f2..9eaf236 100644 --- 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() diff --git a/WorldGen.py b/WorldGen.py index 7615d88..d685d52 100644 --- a/WorldGen.py +++ b/WorldGen.py @@ -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 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 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 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 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 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 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 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