'Pygame change level - level made of list
Hello i am new in pygame. And i have used this example: http://pygame.org/project/1061/ The example shows how to chack for collision, make a level from a list and movement. A great beginner example. I have modified it so it should be able to change level. I have tried deleting the rects once drawn but i can't figure that out. I have the problem that i can't change the level in my code:
import os
import random
import pygame
# Class for the orange dude
class Player(object):
def __init__(self, pos):
players.append(self)
self.rect = pygame.Rect(pos[0], pos[1], 16, 16)
def move(self, dx, dy):
# Move each axis separately. Note that this checks for collisions both times.
if dx != 0:
self.move_single_axis(dx, 0)
if dy != 0:
self.move_single_axis(0, dy)
def move_single_axis(self, dx, dy):
# Move the rect
self.rect.x += dx
self.rect.y += dy
# If you collide with a wall, move out based on velocity
for wall in walls:
if self.rect.colliderect(wall.rect):
if dx > 0: # Moving right; Hit the left side of the wall
self.rect.right = wall.rect.left
if dx < 0: # Moving left; Hit the right side of the wall
self.rect.left = wall.rect.right
if dy > 0: # Moving down; Hit the top side of the wall
self.rect.bottom = wall.rect.top
if dy < 0: # Moving up; Hit the bottom side of the wall
self.rect.top = wall.rect.bottom
# Nice class to hold a wall rect
class Wall(object):
def __init__(self, pos):
walls.append(self)
self.rect = pygame.Rect(pos[0], pos[1], 16, 16)
class Finish(object):
def __init__(self, pos):
finishes.append(self)
self.rect = pygame.Rect(pos[0], pos[1], 16, 16)
# Variables
currentLevel = 1
# Initialise pygame
pygame.init()
# Set up the display
pygame.display.set_caption("Change level")
screen = pygame.display.set_mode((320, 240))
clock = pygame.time.Clock()
walls = [] # List to hold the walls
players = []
finishes = []
# Holds the level layout in a list of strings.
if currentLevel == 1:
level = [
"WWWWWWWWWWWWWWWWWWWW",
"W W",
"W P WWWWWW W",
"W WWWW W W",
"W W WWWW W",
"W WWW WWWW W",
"W W W W W",
"W W W WWW WW",
"W WWW WWW W W W",
"W W W W W W",
"WWW W WWWWW W W",
"W W WW W",
"W W WWWW WWW W",
"W W F W W",
"WWWWWWWWWWWWWWWWWWWW",
]
# Parse the level string above
x = y = 0
for row in level:
for col in row:
if col == "W":
Wall((x, y))
if col == "P":
Player((x, y))
if col == "F":
Finish((x, y))
x += 16
y += 16
x = 0
if currentLevel == 2:
level = [
"WWWWWWWWWWWWWWWWWWWW",
"W W",
"W W",
"W WWWWWWWWWWWWW W",
"W W",
"W P W",
"W W",
"W WWWWWWWWWWWWW W",
"W W",
"W WWWWWWWWWWWWW W",
"W W",
"W F W",
"W W",
"W W",
"WWWWWWWWWWWWWWWWWWWW",
]
# Parse the level string above
x = y = 0
for row in level:
for col in row:
if col == "W":
Wall((x, y))
if col == "P":
Player((x, y))
if col == "F":
Finish((x, y))
x += 16
y += 16
x = 0
running = True
while running:
clock.tick(60)
for e in pygame.event.get():
if e.type == pygame.QUIT:
running = False
if e.type == pygame.KEYDOWN and e.key == pygame.K_ESCAPE:
running = False
# Move the player if an arrow key is pressed
key = pygame.key.get_pressed()
if key[pygame.K_LEFT]:
player.move(-2, 0)
if key[pygame.K_RIGHT]:
player.move(2, 0)
if key[pygame.K_UP]:
player.move(0, -2)
if key[pygame.K_DOWN]:
player.move(0, 2)
# Just added this to make it slightly fun ;)
for player in players:
for finish in finishes:
if player.rect.colliderect(finish.rect):
currentLevel = 2 # Doesn't work
# Draw the scene
screen.fill((0, 0, 0))
for wall in walls:
pygame.draw.rect(screen, (255, 255, 255), wall.rect)
for player in players:
pygame.draw.rect(screen, (255, 200, 0), player.rect)
for finish in finishes:
pygame.draw.rect(screen, (0, 200, 0), finish.rect)
pygame.display.flip()
Solution 1:[1]
You just change the currentLevel
variable, but you never actually change the walls
, players
and finishes
lists (only the code inside the while
loop is executed at this time).
A very simple way to solve this issue is to put the code that "loads" the level into a function and call it when the player reaches the end of the level, e.g.:
import os
import random
import pygame
# Class for the orange dude
class Player(object):
def __init__(self, pos):
self.rect = pygame.Rect(pos[0], pos[1], 16, 16)
def move(self, dx, dy):
# Move each axis separately. Note that this checks for collisions both times.
if dx != 0:
self.move_single_axis(dx, 0)
if dy != 0:
self.move_single_axis(0, dy)
def move_single_axis(self, dx, dy):
# Move the rect
self.rect.x += dx
self.rect.y += dy
# If you collide with a wall, move out based on velocity
for wall in walls:
if self.rect.colliderect(wall.rect):
if dx > 0: # Moving right; Hit the left side of the wall
self.rect.right = wall.rect.left
if dx < 0: # Moving left; Hit the right side of the wall
self.rect.left = wall.rect.right
if dy > 0: # Moving down; Hit the top side of the wall
self.rect.bottom = wall.rect.top
if dy < 0: # Moving up; Hit the bottom side of the wall
self.rect.top = wall.rect.bottom
# Nice class to hold a wall rect
class Wall(object):
def __init__(self, pos):
self.rect = pygame.Rect(pos[0], pos[1], 16, 16)
class Finish(object):
def __init__(self, pos):
self.rect = pygame.Rect(pos[0], pos[1], 16, 16)
# Variables
currentLevel = 0
# Initialise pygame
pygame.init()
# Set up the display
pygame.display.set_caption("Change level")
screen = pygame.display.set_mode((320, 240))
clock = pygame.time.Clock()
levels = [[
"WWWWWWWWWWWWWWWWWWWW",
"W W",
"W P WWWWWW W",
"W WWWW W W",
"W W WWWW W",
"W WWW WWWW W",
"W W W W W",
"W W W WWW WW",
"W WWW WWW W W W",
"W W W W W W",
"WWW W WWWWW W W",
"W W WW W",
"W W WWWW WWW W",
"W W F W W",
"WWWWWWWWWWWWWWWWWWWW",
],
[
"WWWWWWWWWWWWWWWWWWWW",
"W W",
"W W",
"W WWWWWWWWWWWWW W",
"W W",
"W P W",
"W W",
"W WWWWWWWWWWWWW W",
"W W",
"W WWWWWWWWWWWWW W",
"W W",
"W F W",
"W W",
"W W",
"WWWWWWWWWWWWWWWWWWWW",
]]
def load_level(level):
walls = []
players = []
finishes = []
# Parse the level string above
x = y = 0
for row in levels[level]:
for col in row:
if col == "W":
walls.append(Wall((x, y)))
if col == "P":
players.append(Player((x, y)))
if col == "F":
finishes.append(Finish((x, y)))
x += 16
y += 16
x = 0
return walls, players, finishes
walls, players, finishes = load_level(currentLevel)
running = True
while running:
clock.tick(60)
for e in pygame.event.get():
if e.type == pygame.QUIT:
running = False
if e.type == pygame.KEYDOWN and e.key == pygame.K_ESCAPE:
running = False
# Move the player if an arrow key is pressed
key = pygame.key.get_pressed()
if key[pygame.K_LEFT]:
player.move(-2, 0)
if key[pygame.K_RIGHT]:
player.move(2, 0)
if key[pygame.K_UP]:
player.move(0, -2)
if key[pygame.K_DOWN]:
player.move(0, 2)
# Just added this to make it slightly fun ;)
for player in players:
for finish in finishes:
if player.rect.colliderect(finish.rect):
currentLevel += 1
walls, players, finishes = load_level(currentLevel)
# Draw the scene
screen.fill((0, 0, 0))
for wall in walls:
pygame.draw.rect(screen, (255, 255, 255), wall.rect)
for player in players:
pygame.draw.rect(screen, (255, 200, 0), player.rect)
for finish in finishes:
pygame.draw.rect(screen, (0, 200, 0), finish.rect)
pygame.display.flip()
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | sloth |