Python Forum
Adding persistent multiple levels to game - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: Game Development (https://python-forum.io/forum-11.html)
+--- Thread: Adding persistent multiple levels to game (/thread-22490.html)



Adding persistent multiple levels to game - michael1789 - Nov-15-2019

Where would anyone suggest I start with adding persistent, multiple levels to my random dungeon game?

I can generate a level to a rudimentary degree: floors, walls, player, entrance, exit, and a key that the exit requires. But so far it just makes one level and when you get the key to the exit, it only prints "Win!!". That's all.

The obvious next step is to add multiple levels and be able to go in between them, but I draw a blank as to where to start.

How would I produce a number of levels and have the exit of one level enter the next and visa versa? I know that the NES Legend of Zelda's dungeons are all actually one large map but you can't tell because of how it is displayed. Is this a strategy? I fear massive lag.

How had this been done traditionally?


RE: Adding persistent multiple levels to game - micseydel - Nov-15-2019

You may find use in the games tutorials. Perhaps this one most specifically.


RE: Adding persistent multiple levels to game - michael1789 - Nov-16-2019

Thank you. Here is the complete code so far. I changed out my graphics for simple squares, and it will run as-is. Find the red key and take it to the white exit.

import pygame
import random
import time
import sys


pygame.init()

blue = (5, 5, 200)
green = (4, 80, 4)
red = (250, 0, 0)
grey = (30, 30, 30)
lightgrey = (150, 150, 150)
black = (0, 0, 0)
brown = (100, 100, 5)
white = (255, 255, 255)
width = 600
height = 600
tile_size = 30
mapheight = 2400
mapwidth = 2400

floor_locations = []

#wallimage = pygame.image.load("C:/Users/owner/Desktop/python3/dungeongraphics/wall1.png")
#heroimage = pygame.image.load("C:/Users/owner/Desktop/python3/dungeongraphics/hero_1.png")
#upstair = pygame.image.load("C:/Users/owner/Desktop/python3/dungeongraphics/upstairs.png")
#keyimage = pygame.image.load("C:/Users/owner/Desktop/python3/dungeongraphics/key.png")
#downstair = pygame.image.load("C:/Users/owner/Desktop/python3/dungeongraphics/downstairs.png")



diggers = pygame.sprite.Group()
players = pygame.sprite.Group()
all_sprites = pygame.sprite.Group()
base_tiles = pygame.sprite.Group()
floor_tiles = pygame.sprite.Group()        
walls = pygame.sprite.Group()
keys = pygame.sprite.Group()
exits = pygame.sprite.Group()

key_collected = False

class Player(pygame.sprite.Sprite):
    def __init__(self, game, x, y):
        
        pygame.sprite.Sprite.__init__(self)
        self.game = game
        self.image = pygame.Surface((tile_size, tile_size))
        self.image.fill(blue)
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y

    def move(self, dx=0, dy=0):
        global key_collected
        if not self.collide_with_walls(dx, dy):
            self.rect.x += dx 
            self.rect.y += dy
        
        collect = pygame.sprite.spritecollide(game.player, keys, True)
        if collect:
            key_collected = True
        
        exiting = pygame.sprite.spritecollide(game.player, exits, False)
        if exiting and key_collected == True:
            print("win!!")
        
    def collide_with_walls(self, dx=0, dy=0):
        
        for wall in walls:
            
            if wall.rect.x==self.rect.x + dx and wall.rect.y == self.rect.y + dy:
                
                return True
        return False
    
   
    
    def update(self):
        
        self.rect.x = self.x 
        self.rect.y = self.y 



class Floor(pygame.sprite.Sprite):
    def __init__(self, x, y):
        pygame.sprite.Sprite.__init__(self)
        self.game = game
        self.image = pygame.Surface((tile_size, tile_size))
        self.image.fill(brown)
        self.rect = self.image.get_rect()   
        self.rect.x = x
        self.rect.y = y
        
class Key(pygame.sprite.Sprite):
    def __init__(self, x, y):
        pygame.sprite.Sprite.__init__(self)
        self.game = game
        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
        
class Entrance(pygame.sprite.Sprite):
    def __init__(self, x, y):
        pygame.sprite.Sprite.__init__(self)
        self.game = game
        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
        
class Exit(pygame.sprite.Sprite):
    def __init__(self, x, y):
        pygame.sprite.Sprite.__init__(self)
        self.game = game
        self.image = pygame.Surface((tile_size, tile_size))
        self.image.fill(white)
        self.rect = self.image.get_rect()    
        self.rect.x = x
        self.rect.y = y
              
class Base(pygame.sprite.Sprite):
    def __init__(self, x, y):
        pygame.sprite.Sprite.__init__(self)
        self.game = game
        self.colour = grey
        self.image = pygame.draw.rect(game.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()
        
class Wall(pygame.sprite.Sprite):
    def __init__(self, x, y):
        pygame.sprite.Sprite.__init__(self)
        self.game = game
        self.image = pygame.Surface((tile_size, tile_size))
        self.image.fill(lightgrey)
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y
        pygame.display.flip()

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()   #pygame.Rect(self.rect.x, self.recty, tile_size, tile_size)
        self.rect.x = x
        self.rect.y = y
        
def Make_map():
    
    for x in range(0, mapwidth, tile_size):
        for y in range(0, mapheight, tile_size):
            
            base = Base(x, y)
            base_tiles.add(base)
     
    
    digger = Digger((mapwidth / 2), (mapheight / 2))
    diggers.add(digger)
    all_sprites.add(digger)
    
    for i in range(2400): 
        
        (dx, dy) = random.choice([(0, tile_size), (0, -tile_size), (-tile_size, 0), (tile_size, 0)])
   
   
        if digger.rect.x + dx <= tile_size:
            dx = 0
        if digger.rect.x + dx >= mapwidth  - (2 * tile_size):
            dx = 0
        if digger.rect.y + dy <= tile_size:
            dy = 0
        if digger.rect.y + dy >= mapheight - (2 * tile_size):
            dy = 0
            
        digger.rect.x = digger.rect.x + dx
        digger.rect.y = digger.rect.y + dy
        floor_locations.append((digger.rect.x, digger.rect.y))
        pygame.sprite.spritecollide(digger, floor_tiles, True)
        floor = Floor(digger.rect.x, digger.rect.y)
        all_sprites.add(floor)
        floor_tiles.add(floor)
        pygame.sprite.spritecollide(digger, base_tiles, True)
    
    key_location = random.choice(floor_locations)
    x, y = key_location
    key1 = Key(x, y)
    all_sprites.add(key1)
    keys.add(key1)
    
    for floor in floor_tiles:
         
        for delta_x, delta_y in ((tile_size, 0), (0, tile_size), (-tile_size, 0), (0, -tile_size), (-tile_size, tile_size), (tile_size, -tile_size), (-tile_size, -tile_size), (tile_size, tile_size)):
      
            floor.rect.x = floor.rect.x + delta_x
            floor.rect.y = floor.rect.y + delta_y
            hits = pygame.sprite.spritecollide(floor, base_tiles, False)
            
            floor.rect.x = floor.rect.x - delta_x
            floor.rect.y = floor.rect.y - delta_y
            
            for hit in hits:
               
                wall = Wall(hit.rect.x, hit.rect.y)       
                all_sprites.add(wall)
                walls.add(wall)
                   
    entrance = Entrance((mapwidth / 2), (mapheight / 2))
    eXit = Exit(digger.rect.x, digger.rect.y)
    all_sprites.add(floor, entrance, eXit)
    floor_tiles.add(floor)
    exits.add(eXit)
                
class Game():
    def __init__(self):
        pygame.init()
        self.window = pygame.display.set_mode((width, height))
        pygame.display.set_caption("Dungeon")
        self.clock = pygame.time.Clock()
        pygame.key.set_repeat(500, 100)
        
    def New(self):
        
        Make_map()
       
        self.player = Player(game, (mapwidth / 2), (mapheight / 2))
        all_sprites.add(self.player)
        players.add(self.player)
        self.camera = Camera(mapwidth, mapheight)
        self.run()
        all_sprites.draw(window)
        pygame.display.flip()
            
        
    def run(self):
        playing = True
        while playing:
               
            self.update()
            self.draw()
            self.events()
            

    def quit(self):
        pygame.quit()
        sys.exit()

    def update(self):
        
        self.camera.update(self.player)
        all_sprites.draw(game.window)    

    def draw(self):
       
        self.window.fill(black)
        for sprite in all_sprites:
            self.window.blit(sprite.image, self.camera.apply(sprite))
        pygame.display.flip()
  

    def events(self):
        # catch all events here
        
        check = True
        while check:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    self.quit()
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_ESCAPE:
                        self.quit()
                    if event.key == pygame.K_LEFT:
                        self.player.move(dx=-tile_size)
                        check = False
                    if event.key == pygame.K_RIGHT:
                        self.player.move(dx=tile_size)
                        check = False
                    if event.key == pygame.K_UP:
                        self.player.move(dy=-tile_size)
                        check = False
                    if event.key == pygame.K_DOWN:
                        self.player.move(dy=tile_size)
                        check = False

class Camera:
    def __init__(self, width, height):
        self.camera = pygame.Rect(0, 0, width, height)
        self.width = width
        self.height = height
        
    def apply(self, entity):
        return entity.rect.move(self.camera.topleft)
    
    def update(self, target):
        x = -target.rect.x + int(width / 2)
        y = -target.rect.y + int(height / 2)
        
        x = min(0, x)
        y = min(0, y)
        x = max(-(mapwidth - width), x)
        y = max(-(mapheight - height), y)
        
        self.camera = pygame.Rect(x, y, self.width, self.height)

game = Game()
game.New()
I was really just looking for some general guidance on how it is normally done (eg. make 10 of these levels and link the entrances and exits). Then I would at least have a starting point.