我正在使用 Python 的街机游戏库开发一个简单的平台游戏。我对此仍然很陌生,但我已尝试尽可能多地使用面向对象的编程。我已经成功设置了两个“房间”或游戏关卡。但是,我不知道在完成第一个房间后如何搬到第二个房间。这是我的代码:
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()
如果我从 def 更新中删除 self.gameover=True ,程序将转换到房间 2 但精灵没有正确加载并且玩家位置没有重置。