I am developing a simple platformer game using the arcade game library of Python. I am still new to this, but I have tried to use as much object oriented programming as I could. I have successfully setup two “rooms” or levels of the game. However, I cannot figure out how to move to the second room after finishing the first room. Here is my code:
import arcade import os import random SPRITE_SCALING = 0.5 SPRITE_SCALING_COIN = 0.3 SPRITE_NATIVE_SIZE = 128 SPRITE_SIZE = int(SPRITE_NATIVE_SIZE * SPRITE_SCALING) SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600 SCREEN_TITLE = "Help Nick Adams!" # Physics MOVEMENT_SPEED = 5 JUMP_SPEED = 12 GRAVITY = 0.5 class Room: # Class to hold info about rooms/levels def __init__(self): self.wall_list = self.goal_list = self.enemy_list = self.victory_sprite = None self.collectedCoins = 0 self.numCoins = 0 def setup_room_1(): room = Room() room.wall_list = arcade.SpriteList(use_spatial_hash=True) room.enemy_list = arcade.SpriteList() room.goal_list = arcade.SpriteList(use_spatial_hash=True) room.victory_sprite = arcade.SpriteList(use_spatial_hash=True) # Draw platforms and ground for x in range(0, SCREEN_WIDTH, SPRITE_SIZE): wall = arcade.Sprite(":resources:images/tiles/grassMid.png", SPRITE_SCALING) wall.bottom = 0 wall.left = x room.wall_list.append(wall) for x in range(SPRITE_SIZE * 3, SPRITE_SIZE * 8, SPRITE_SIZE): wall = arcade.Sprite(":resources:images/tiles/grassMid.png", SPRITE_SCALING) wall.bottom = SPRITE_SIZE * 3 wall.left = x room.wall_list.append(wall) # Draw the crates for x in range(0, SCREEN_WIDTH, SPRITE_SIZE * 5): wall = arcade.Sprite(":resources:images/tiles/boxCrate_double.png", SPRITE_SCALING) wall.bottom = SPRITE_SIZE wall.left = x room.wall_list.append(wall) # Draw an enemy 1 enemy = arcade.Sprite(":resources:images/enemies/wormGreen.png", SPRITE_SCALING) enemy.bottom = SPRITE_SIZE enemy.left = SPRITE_SIZE * 2 enemy.change_x = 2 room.enemy_list.append(enemy) # -- Draw enemy2 on the platform enemy = arcade.Sprite(":resources:images/enemies/wormGreen.png", SPRITE_SCALING) enemy.bottom = SPRITE_SIZE * 4 enemy.left = SPRITE_SIZE * 4 # Set boundaries for enemy enemy.boundary_right = SPRITE_SIZE * 8 enemy.boundary_left = SPRITE_SIZE * 3 enemy.change_x = 2 room.enemy_list.append(enemy) # Set up coins for pos in [[128, 96], [418, 300], [670, 150]]: goal = arcade.Sprite(":resources:images/items/coinGold.png", SPRITE_SCALING) goal.center_x = pos[0] goal.center_y = pos[1] room.goal_list.append(goal) room.numCoins += 1 # Set up checkpoint/level clear flag = arcade.Sprite(":resources:images/tiles/signExit.png", SPRITE_SCALING) flag.center_x = 770 flag.center_y = 96 room.victory_sprite.append(flag) # Load the background image for this level. room.background = arcade.load_texture(":resources:images/backgrounds/abstract_1.jpg") return room def setup_room_2(): room = Room() room.wall_list = arcade.SpriteList(use_spatial_hash=True) room.enemy_list = arcade.SpriteList() room.goal_list = arcade.SpriteList(use_spatial_hash=True) room.victory_sprite = arcade.SpriteList(use_spatial_hash=True) # Set up walls for y in range(0, 800, 200): for x in range(100, 700, 64): wall = arcade.Sprite(":resources:images/tiles/boxCrate_double.png", SPRITE_SCALING) wall.center_x = x wall.center_y = y room.wall_list.append(wall) for pos in [[35, 40], [765, 80], [35, 280], [765, 480]]: wall = arcade.Sprite(":resources:images/tiles/grassHalf.png", SPRITE_SCALING) wall.center_x = pos[0] wall.center_y = pos[1] room.wall_list.append(wall) # Create the coins for i in range(50): # Create the coin instance # Coin image from kenney.nl goal = arcade.Sprite(":resources:images/items/coinGold.png", SPRITE_SCALING_COIN) # Boolean variable if we successfully placed the coin coin_placed_successfully = False # Keep trying until success while not coin_placed_successfully: # Position the coin goal.center_x = random.randrange(100, 700) goal.center_y = random.randrange(SCREEN_HEIGHT) # See if the coin is hitting a wall wall_hit_list = arcade.check_for_collision_with_list(goal, room.wall_list) # See if the coin is hitting another coin coin_hit_list = arcade.check_for_collision_with_list(goal, room.goal_list) if len(wall_hit_list) == 0 and len(coin_hit_list) == 0: coin_placed_successfully = True # Add the coin to the lists room.goal_list.append(goal) room.numCoins += 1 # Draw an enemy1 enemy = arcade.Sprite(":resources:images/enemies/fly.png", SPRITE_SCALING_COIN) enemy.bottom = SPRITE_SIZE enemy.left = SPRITE_SIZE * 2 enemy.boundary_right = SPRITE_SIZE * 8 + 60 enemy.boundary_left = SPRITE_SIZE * 1 + 60 enemy.change_x = 3 room.enemy_list.append(enemy) # Draw a enemy2 enemy = arcade.Sprite(":resources:images/enemies/fly.png", SPRITE_SCALING_COIN) enemy.bottom = SPRITE_SIZE * 4 enemy.left = SPRITE_SIZE * 4 enemy.boundary_right = SPRITE_SIZE * 8 enemy.boundary_left = SPRITE_SIZE * 3 enemy.change_x = 4 room.enemy_list.append(enemy) # Draw a enemy3 enemy = arcade.Sprite(":resources:images/enemies/fly.png", SPRITE_SCALING_COIN) enemy.bottom = SPRITE_SIZE * 7.2 enemy.left = SPRITE_SIZE * 4 enemy.boundary_right = SPRITE_SIZE * 8 + 80 enemy.boundary_left = SPRITE_SIZE * 3 enemy.change_x = 4.8 room.enemy_list.append(enemy) # Draw victory point flag = arcade.Sprite(":resources:images/tiles/signExit.png", SPRITE_SCALING) flag.center_x = 765 flag.center_y = 545 room.victory_sprite.append(flag) # Load the background image for this level. room.background = arcade.load_texture(":resources:images/backgrounds/abstract_1.jpg") return room class MainGame(arcade.Window): def __init__(self): super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE) file_path = os.path.dirname(os.path.abspath(__file__)) os.chdir(file_path) # Sprites and set up player self.player_list = self.rooms = self.player_sprite = self.physics_engine = None self.current_room = self.view_left = self.view_bottom = self.collectedCoins = 0 self.game_over = False # Load sounds self.collect_goal_sound = arcade.load_sound(":resources:sounds/coin1.wav") self.jump_sound = arcade.load_sound(":resources:sounds/jump1.wav") def setup(self): """ Set up the game and initialize the variables. """ # -- Set up the player self.player_sprite = arcade.Sprite(":resources:images/animated_characters/female_person/femalePerson_idle.png", SPRITE_SCALING) # list of rooms self.rooms = [] # Create the rooms room = setup_room_1() self.rooms.append(room) room = setup_room_2() self.rooms.append(room) # Starting room number self.current_room = 0 # Player start position according to room number if self.current_room == 0: self.player_sprite.center_x = 64 self.player_sprite.center_y = 270 elif self.current_room == 1: self.player_sprite.center_x = 35 self.player_sprite.center_y = 55 self.player_list = arcade.SpriteList() self.player_list.append(self.player_sprite) # Create a physics engine self.physics_engine = arcade.PhysicsEnginePlatformer(self.player_sprite, self.rooms[self.current_room].wall_list ) # Set the background color arcade.set_background_color(arcade.color.AMAZON) def on_draw(self): arcade.start_render() self.rooms[self.current_room].wall_list.draw() self.rooms[self.current_room].goal_list.draw() self.rooms[self.current_room].enemy_list.draw() self.rooms[self.current_room].victory_sprite.draw() # Draw all the sprites. self.player_list.draw() def on_key_press(self, key, modifiers): if key == arcade.key.UP: if self.physics_engine.can_jump(): self.player_sprite.change_y = JUMP_SPEED elif key == arcade.key.LEFT: self.player_sprite.change_x = -MOVEMENT_SPEED elif key == arcade.key.RIGHT: self.player_sprite.change_x = MOVEMENT_SPEED def on_key_release(self, key, modifiers): if key == arcade.key.LEFT or key == arcade.key.RIGHT: self.player_sprite.change_x = 0 def on_update(self, delta_time): if not self.game_over: # Move the enemies self.rooms[self.current_room].enemy_list.update() # Check each enemy for enemy in self.rooms[self.current_room].enemy_list: # If the enemy hit a wall, reverse if len(arcade.check_for_collision_with_list(enemy, self.rooms[self.current_room].wall_list)) > 0: enemy.change_x *= -1 # If the enemy hit the left boundary, reverse elif enemy.boundary_left is not None and enemy.left < enemy.boundary_left: enemy.change_x *= -1 # If the enemy hit the right boundary, reverse elif enemy.boundary_right is not None and enemy.right > enemy.boundary_right: enemy.change_x *= -1 # Update the player using the physics engine self.physics_engine.update() # See if we hit any coins goal_hit_list = arcade.check_for_collision_with_list(self.player_sprite, self.rooms[self.current_room].goal_list) # Loop through each coin we hit (if any) and remove it for goal in goal_hit_list: # Remove the coin goal.remove_from_sprite_lists() # Play a sound arcade.play_sound(self.collect_goal_sound) # Count number of coins collected self.collectedCoins += 1 if self.player_sprite.center_x <= -10 or self.player_sprite.center_x >= 800: self.player_sprite.change_x = 0 self.player_sprite.change_y = 0 self.player_sprite.center_x = 64 self.player_sprite.center_y = 270 # See if the player hit a worm if len(arcade.check_for_collision_with_list(self.player_sprite, self.rooms[self.current_room].enemy_list)) > 0: self.game_over = True # See if the player hit the flag. If so, progress to round 2 ?????? if arcade.check_for_collision_with_list(self.player_sprite, self.rooms[ self.current_room].victory_sprite) and self.collectedCoins == self.rooms[self.current_room].numCoins: self.game_over = True self.current_room += 1 def main(): window = MainGame() window.setup() arcade.run() if __name__ == "__main__": main()
If I delete self.gameover= True from the def update, the program transitions into room 2 but the sprites aren’t loaded properly and player position is not reset.
Advertisement
Answer
- replace
self.game_over = True
withself.setup()
- Move creation of rooms from
setup
to__init__
Updated script:
import arcade import os import random SPRITE_SCALING = 0.5 SPRITE_SCALING_COIN = 0.3 SPRITE_NATIVE_SIZE = 128 SPRITE_SIZE = int(SPRITE_NATIVE_SIZE * SPRITE_SCALING) SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600 SCREEN_TITLE = "Help Nick Adams!" # Physics MOVEMENT_SPEED = 5 JUMP_SPEED = 12 GRAVITY = 0.5 class Room: # Class to hold info about rooms/levels def __init__(self): self.wall_list = self.goal_list = self.enemy_list = self.victory_sprite = None self.collectedCoins = 0 self.numCoins = 0 def setup_room_1(): room = Room() room.wall_list = arcade.SpriteList(use_spatial_hash=True) room.enemy_list = arcade.SpriteList() room.goal_list = arcade.SpriteList(use_spatial_hash=True) room.victory_sprite = arcade.SpriteList(use_spatial_hash=True) # Draw platforms and ground for x in range(0, SCREEN_WIDTH, SPRITE_SIZE): wall = arcade.Sprite(":resources:images/tiles/grassMid.png", SPRITE_SCALING) wall.bottom = 0 wall.left = x room.wall_list.append(wall) for x in range(SPRITE_SIZE * 3, SPRITE_SIZE * 8, SPRITE_SIZE): wall = arcade.Sprite(":resources:images/tiles/grassMid.png", SPRITE_SCALING) wall.bottom = SPRITE_SIZE * 3 wall.left = x room.wall_list.append(wall) # Draw the crates for x in range(0, SCREEN_WIDTH, SPRITE_SIZE * 5): wall = arcade.Sprite(":resources:images/tiles/boxCrate_double.png", SPRITE_SCALING) wall.bottom = SPRITE_SIZE wall.left = x room.wall_list.append(wall) # Draw an enemy 1 enemy = arcade.Sprite(":resources:images/enemies/wormGreen.png", SPRITE_SCALING) enemy.bottom = SPRITE_SIZE enemy.left = SPRITE_SIZE * 2 enemy.change_x = 2 room.enemy_list.append(enemy) # -- Draw enemy2 on the platform enemy = arcade.Sprite(":resources:images/enemies/wormGreen.png", SPRITE_SCALING) enemy.bottom = SPRITE_SIZE * 4 enemy.left = SPRITE_SIZE * 4 # Set boundaries for enemy enemy.boundary_right = SPRITE_SIZE * 8 enemy.boundary_left = SPRITE_SIZE * 3 enemy.change_x = 2 room.enemy_list.append(enemy) # Set up coins for pos in [[128, 96], [418, 300], [670, 150]]: goal = arcade.Sprite(":resources:images/items/coinGold.png", SPRITE_SCALING) goal.center_x = pos[0] goal.center_y = pos[1] room.goal_list.append(goal) room.numCoins += 1 # Set up checkpoint/level clear flag = arcade.Sprite(":resources:images/tiles/signExit.png", SPRITE_SCALING) flag.center_x = 770 flag.center_y = 96 room.victory_sprite.append(flag) # Load the background image for this level. room.background = arcade.load_texture(":resources:images/backgrounds/abstract_1.jpg") return room def setup_room_2(): room = Room() room.wall_list = arcade.SpriteList(use_spatial_hash=True) room.enemy_list = arcade.SpriteList() room.goal_list = arcade.SpriteList(use_spatial_hash=True) room.victory_sprite = arcade.SpriteList(use_spatial_hash=True) # Set up walls for y in range(0, 800, 200): for x in range(100, 700, 64): wall = arcade.Sprite(":resources:images/tiles/boxCrate_double.png", SPRITE_SCALING) wall.center_x = x wall.center_y = y room.wall_list.append(wall) for pos in [[35, 40], [765, 80], [35, 280], [765, 480]]: wall = arcade.Sprite(":resources:images/tiles/grassHalf.png", SPRITE_SCALING) wall.center_x = pos[0] wall.center_y = pos[1] room.wall_list.append(wall) # Create the coins for i in range(50): # Create the coin instance # Coin image from kenney.nl goal = arcade.Sprite(":resources:images/items/coinGold.png", SPRITE_SCALING_COIN) # Boolean variable if we successfully placed the coin coin_placed_successfully = False # Keep trying until success while not coin_placed_successfully: # Position the coin goal.center_x = random.randrange(100, 700) goal.center_y = random.randrange(SCREEN_HEIGHT) # See if the coin is hitting a wall wall_hit_list = arcade.check_for_collision_with_list(goal, room.wall_list) # See if the coin is hitting another coin coin_hit_list = arcade.check_for_collision_with_list(goal, room.goal_list) if len(wall_hit_list) == 0 and len(coin_hit_list) == 0: coin_placed_successfully = True # Add the coin to the lists room.goal_list.append(goal) room.numCoins += 1 # Draw an enemy1 enemy = arcade.Sprite(":resources:images/enemies/fly.png", SPRITE_SCALING_COIN) enemy.bottom = SPRITE_SIZE enemy.left = SPRITE_SIZE * 2 enemy.boundary_right = SPRITE_SIZE * 8 + 60 enemy.boundary_left = SPRITE_SIZE * 1 + 60 enemy.change_x = 3 room.enemy_list.append(enemy) # Draw a enemy2 enemy = arcade.Sprite(":resources:images/enemies/fly.png", SPRITE_SCALING_COIN) enemy.bottom = SPRITE_SIZE * 4 enemy.left = SPRITE_SIZE * 4 enemy.boundary_right = SPRITE_SIZE * 8 enemy.boundary_left = SPRITE_SIZE * 3 enemy.change_x = 4 room.enemy_list.append(enemy) # Draw a enemy3 enemy = arcade.Sprite(":resources:images/enemies/fly.png", SPRITE_SCALING_COIN) enemy.bottom = SPRITE_SIZE * 7.2 enemy.left = SPRITE_SIZE * 4 enemy.boundary_right = SPRITE_SIZE * 8 + 80 enemy.boundary_left = SPRITE_SIZE * 3 enemy.change_x = 4.8 room.enemy_list.append(enemy) # Draw victory point flag = arcade.Sprite(":resources:images/tiles/signExit.png", SPRITE_SCALING) flag.center_x = 765 flag.center_y = 545 room.victory_sprite.append(flag) # Load the background image for this level. room.background = arcade.load_texture(":resources:images/backgrounds/abstract_1.jpg") return room class MainGame(arcade.Window): def __init__(self): super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE) file_path = os.path.dirname(os.path.abspath(__file__)) os.chdir(file_path) # Sprites and set up player self.player_list = self.rooms = self.player_sprite = self.physics_engine = None self.current_room = self.view_left = self.view_bottom = self.collectedCoins = 0 self.game_over = False # Load sounds self.collect_goal_sound = arcade.load_sound(":resources:sounds/coin1.wav") self.jump_sound = arcade.load_sound(":resources:sounds/jump1.wav") # Starting room number self.current_room = 0 # list of rooms self.rooms = [] # Create the rooms room = setup_room_1() self.rooms.append(room) room = setup_room_2() self.rooms.append(room) def setup(self): """ Set up the game and initialize the variables. """ # -- Set up the player self.player_sprite = arcade.Sprite(":resources:images/animated_characters/female_person/femalePerson_idle.png", SPRITE_SCALING) # Player start position according to room number if self.current_room == 0: self.player_sprite.center_x = 64 self.player_sprite.center_y = 270 elif self.current_room == 1: self.player_sprite.center_x = 35 self.player_sprite.center_y = 55 self.player_list = arcade.SpriteList() self.player_list.append(self.player_sprite) # Create a physics engine self.physics_engine = arcade.PhysicsEnginePlatformer(self.player_sprite, self.rooms[self.current_room].wall_list) # Set the background color arcade.set_background_color(arcade.color.AMAZON) def on_draw(self): arcade.start_render() self.rooms[self.current_room].wall_list.draw() self.rooms[self.current_room].goal_list.draw() self.rooms[self.current_room].enemy_list.draw() self.rooms[self.current_room].victory_sprite.draw() # Draw all the sprites. self.player_list.draw() def on_key_press(self, key, modifiers): if key == arcade.key.UP: if self.physics_engine.can_jump(): self.player_sprite.change_y = JUMP_SPEED elif key == arcade.key.LEFT: self.player_sprite.change_x = -MOVEMENT_SPEED elif key == arcade.key.RIGHT: self.player_sprite.change_x = MOVEMENT_SPEED def on_key_release(self, key, modifiers): if key == arcade.key.LEFT or key == arcade.key.RIGHT: self.player_sprite.change_x = 0 def on_update(self, delta_time): if not self.game_over: # Move the enemies self.rooms[self.current_room].enemy_list.update() # Check each enemy for enemy in self.rooms[self.current_room].enemy_list: # If the enemy hit a wall, reverse if len(arcade.check_for_collision_with_list(enemy, self.rooms[self.current_room].wall_list)) > 0: enemy.change_x *= -1 # If the enemy hit the left boundary, reverse elif enemy.boundary_left is not None and enemy.left < enemy.boundary_left: enemy.change_x *= -1 # If the enemy hit the right boundary, reverse elif enemy.boundary_right is not None and enemy.right > enemy.boundary_right: enemy.change_x *= -1 # Update the player using the physics engine self.physics_engine.update() # See if we hit any coins goal_hit_list = arcade.check_for_collision_with_list(self.player_sprite, self.rooms[self.current_room].goal_list) # Loop through each coin we hit (if any) and remove it for goal in goal_hit_list: # Remove the coin goal.remove_from_sprite_lists() # Play a sound arcade.play_sound(self.collect_goal_sound) # Count number of coins collected self.collectedCoins += 1 if self.player_sprite.center_x <= -10 or self.player_sprite.center_x >= 800: self.player_sprite.change_x = 0 self.player_sprite.change_y = 0 self.player_sprite.center_x = 64 self.player_sprite.center_y = 270 # See if the player hit a worm if len(arcade.check_for_collision_with_list(self.player_sprite, self.rooms[self.current_room].enemy_list)) > 0: self.game_over = True # See if the player hit the flag. If so, progress to round 2 ?????? if arcade.check_for_collision_with_list(self.player_sprite, self.rooms[self.current_room].victory_sprite) and self.collectedCoins == self.rooms[self.current_room].numCoins: # self.game_over = True self.current_room += 1 self.setup() def main(): window = MainGame() window.setup() arcade.run() if __name__ == "__main__": main()