Python Forum
How to place walls in random dungeon ?
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to place walls in random dungeon ?
#1
I have a program that will fill the window with tiles and another sprite that does a random walk, placing "floor tiles" and killing wall tiles as it goes.

How do I determine which tiles are next to floor tiles so I can put a wall graphic there?

Or just in general, what is the common approach to get a tile to search its surroundings?
Reply
#2
That's going to be highly dependent on how you store the data. For example, in the old game Wizardry, each square in the dungeon contained the wall information. That would be like having a 2D array of objects, each one containing flags for the north, south, east, and west walls. In that case, the tile contains it's surrounding, so you don't have to worry about it.

The rat in a maze simulation I did in college, on the other hand, had two types of squares: walls and passageways. So to find the adjacent squares, you would check each direction. Generally I would do something like this:

for delta_x, delta_y in ((1, 0), (0, 1), (-1, 0), (0, -1)):
    adj_x = current_x + delta_x
    adj_y = current_y + delta_y
    adj_location = locations[adj_x][adj_y]
    do_something(adj_location)
So we would need to know more about how you are storing your information before we could help you.
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#3
So far all my tiles are just sprites with a surface, a Rect, and a color. They are in 2 lists ("walls" and "floor"). By storing information do you mean which sprite knows wall locations, or storing the generated level itself.


It's my first attempt at this, but I know that I can add a player and wall-collision easy enough, and start making it a game... primitive and beginner, but a game. Currently it will look like a floor in a void. I want to replace the image of the walls with something more wall-like.

you wrote:
adj_location = locations[adj_x][adj_y]
do_something(adj_location)

simple question here: are the square brackets making this a list of all locations? And would "do_something" be "move there, collision detection, and if hit, spawn visible wall sprite"?


What I had in mind was like your rat maze program. The Wizardry method is enticing, but perhaps too complicated for my skill level. I wouldn't know were to start.
Reply
#4
Yes, I was envisioning a 2D list. Something like:

map = [[Wall(), Wall(), Wall(), Wall()],
    [Floor(), Floor(), Floor(), Wall()],
    [Wall(), Wall(), Floor(), Wall()],
    [Wall(), Wall(), Floor(), Wall()]]
But you could have both that and the walls and floors lists that you are talking about. Say you want to put a floor at a particular position. You might handle it this way:

def place_floor(x, y):
    new_floor = Floor(x, y)
    map[y][x] = new_floor
    floors.append(new_floor)
You have to make sure that when one list is updated, the other is too. However, you can use the two lists for different things. You might use the map list of lists for building the maze, but then use the floors and walls lists for collision detection.

But if you are storing a Rect with each floor/wall, you don't necessarily need that. You could use the coordinates of the Rect to calculate the appropriate coordinates of any walls, probably looping through all the possible directions in my first post. Then you could scan through the walls list to see if the appropriate squares are in there.
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#5
This is what I have so far. If you take out the # from "Build_Walls()" at the bottom, there is an error. It doesn't know that I want "wall" to be an instance in the walls list.

import pygame
import random
import time

pygame.init()


green = (4, 80, 4)
red = (250, 0, 0)
grey = (30, 30, 30)
width = 400
height = 400
tile_size = 20
window = pygame.display.set_mode((width, height))


class Floor(pygame.sprite.Sprite):
    def __init__(self, x, y):
        pygame.sprite.Sprite.__init__(self)
        
        self.image = pygame.Surface((tile_size, tile_size))
        self.image.fill(green)
        self.rect = self.image.get_rect()   
        self.rect.x = x
        self.rect.y = y
        floor_tiles.add(self)
        
        

class Wall(pygame.sprite.Sprite):
    def __init__(self, x, y):
        pygame.sprite.Sprite.__init__(self)
        self.colour = grey
        self.image = pygame.draw.rect(window, (self.colour), (x, y, tile_size, tile_size), 0)
        self.rect = pygame.Rect(x, y, tile_size, tile_size)
        self.x = x
        self.y = y
        pygame.display.flip()
        #time.sleep(.01)

class Digger(pygame.sprite.Sprite):
    def __init__(self, x, y):
        pygame.sprite.Sprite.__init__(self)
        
    
        
        self.image = pygame.Surface((tile_size, tile_size))
        self.image.fill(red)
        self.rect = self.image.get_rect()   
        self.rect.x = x
        self.rect.y = y
        
    def dig(self):
        
        
        for i in range(70): 
            
            (dx, dy) = random.choice([(0, tile_size), (0, -tile_size), (-tile_size, 0), (+tile_size, 0)])
       
            self.rect.x = self.rect.x + dx
            self.rect.y = self.rect.y + dy
            
            floor = Floor(self.rect.x, self.rect.y)
            all_sprites.add(floor)
            
            pygame.sprite.spritecollide(digger, walls, True)
            
            print(walls)
            
            
        
def Fill_Map():

    for x in range(0, width, tile_size):
       for y in range(0, height, tile_size):
            
            wall = Wall(x, y)
            walls.add(wall)

def Build_walls():
          
        for floor in floor_tiles:
            print(floor_tiles) 
            for delta_x, delta_y in ((1, 0), (0, 1), (-1, 0), (0, -1)):
          
                floor.rect.x = floor.rect.x + delta_x
                floor.rect.y = floor.rect.y + delta_y
                hits = pygame.sprite.spritecollide(floor, walls, False)
                for hit in hits:
                    wall.colour = red
                            
                    floor.rect.x = floor.rect.x - delta_x
                    floor.rect.y = floor.rect.y - delta_y
                    
    
all_sprites = pygame.sprite.Group()
walls = pygame.sprite.Group()
Fill_Map()
floor_tiles = pygame.sprite.Group()
diggers = pygame.sprite.Group()
digger = Digger((width / 2), (height / 2)) 
diggers.add(digger)
digger.dig()
#Build_walls()



all_sprites.draw(window)
pygame.display.update()
Reply
#6
Got it! I'm going to add diagonal movement to the test so that the corners close too, and a have my tunneling sprite delete floor tiles it goes over so I don't have duplicates. I'm pretty happy. This was the first thing I wanted to learn how to do. Coding is hard. lol
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  [PyGame] Starting place for Pygame Mobile app XavierPlatinum 2 2,360 Oct-15-2022, 05:51 PM
Last Post: XavierPlatinum
  [PyGame] Making Player Sprite Ricochet of walls michael1789 4 4,401 Jun-03-2019, 10:45 PM
Last Post: Windspar
  Raycasting(again) walls with different heights robie972003 0 2,434 Mar-23-2019, 01:18 AM
Last Post: robie972003
  Old School First Person Dungeon Crawler? xBlackHeartx 1 4,400 Oct-01-2017, 12:50 PM
Last Post: metulburr

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020