В этой статье мы рассмотрим код, который служит шаблоном для создания платформерной игры с использованием библиотеки Arcade в Python. Библиотека Arcade упрощает разработку игр, предоставляя удобные инструменты для работы с графикой, анимацией, физикой и другими игровыми элементами.
Импорт необходимых модулей
import arcade
Мы импортируем модуль arcade
, который содержит все необходимые классы и функции для разработки игры.
Определение констант
# --- Constants
SCREEN_TITLE = "Platformer"
SCREEN_WIDTH = 1000
SCREEN_HEIGHT = 650
# Constants used to scale our sprites from their original size
CHARACTER_SCALING = 1
TILE_SCALING = 0.5
COIN_SCALING = 0.5
SPRITE_PIXEL_SIZE = 128
GRID_PIXEL_SIZE = SPRITE_PIXEL_SIZE * TILE_SCALING
Здесь определяются константы, которые используются в игре. SCREEN_TITLE
– это название окна игры, SCREEN_WIDTH
и SCREEN_HEIGHT
– ширина и высота экрана. Другие константы используются для масштабирования спрайтов и настройки размеров пикселей.
Класс MyGame
class MyGame(arcade.Window):
"""
Основной класс приложения.
"""
def __init__(self):
# Вызываем конструктор родительского класса и настраиваем окно
super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT,
SCREEN_TITLE, resizable=True)
# ... (другие атрибуты и методы)
Класс MyGame
наследует от класса arcade.Window
, который отвечает за окно игры. В конструкторе __init__
мы устанавливаем размер и название окна.
Настройка игры
def setup(self):
"""Настройка игры. Вызовите эту функцию для перезапуска игры."""
# Настройка камер
self.camera_sprites = arcade.Camera(self.width, self.height)
self.camera_gui = arcade.Camera(self.width, self.height)
# ... (загрузка карты, создание игрока и т.д.)
Метод setup
используется для настройки игры. Здесь создаются камеры для игры: camera_sprites
для игровых объектов и camera_gui
для интерфейса пользователя. Затем загружается карта игры, создается игрок и другие игровые элементы.
Рендеринг игры
def on_draw(self):
"""Отрисовка экрана."""
# Очищаем экран под цвет фона
self.clear()
# Активируем игровую камеру
self.camera_sprites.use()
# Рисуем игровую сцену
self.scene.draw()
# Активируем камеру интерфейса перед отрисовкой GUI элементов
self.camera_gui.use()
# Выводим текст с счетом игрока, прокручивая его вместе с видом
score_text = f"Счет: {self.score}"
arcade.draw_text(score_text,
start_x=10,
start_y=10,
color=arcade.csscolor.WHITE,
font_size=18)
Метод on_draw
отвечает за рендеринг игры. Сначала очищается экран, затем активируется игровая камера camera_sprites
. Далее рисуется игровая сцена (self.scene.draw()
), активируется камера интерфейса (camera_gui
) и выводится текст с счетом игрока.
Обработка событий клавиатуры
def on_key_press(self, key, modifiers):
"""Вызывается при нажатии любой клавиши."""
# Прыжок
if key == arcade.key.UP or key == arcade.key.W:
if self.physics_engine.can_jump():
self.player_sprite.change_y = PLAYER_JUMP_SPEED
# Влево
elif key == arcade.key.LEFT or key == arcade.key.A:
self.left_key_down = True
self.update_player_speed()
# Вправо
elif key == arcade.key.RIGHT or key == arcade.key.D:
self.right_key_down = True
self.update_player_speed()
def on_key_release(self, key, modifiers):
"""Вызывается при отпускании клавиши."""
if key == arcade.key.LEFT or key == arcade.key.A:
self.left_key_down = False
self.update_player_speed()
elif key == arcade.key.RIGHT or key == arcade.key.D:
self.right_key_down = False
self.update_player_speed()
Методы on_key_press
и on_key_release
обрабатывают события нажатия и отпускания клавиш. Здесь определяется поведение игрока при нажатии клавиш движения и прыжка.
Обновление игры
def center_camera_to_player(self):
# ... (код для центрирования камеры на игроке)
def on_update(self, delta_time):
"""Движение и игровая логика"""
# Перемещаем игрока с помощью физического движка
self.physics_engine.update()
# Проверяем столкновения с монетами
coin_hit_list = arcade.check_for_collision_with_list(
self.player_sprite, self.scene["Coins"]
)
# Цикл по монетам, с которыми произошло столкновение (если таковые есть)
for coin in coin_hit_list:
# Удалить монету
coin.remove_from_sprite_lists()
# Увеличить счет
self.score += 1
# Установка позиции камеры
self.center_camera_to_player()
Метод on_update
отвечает за обновление игры. Здесь обновляется физика игрока, проверяются столкновения с монетами, и если столкновение произошло, монеты удаляются, а счет игрока увеличивается. Также обновляется позиция камеры, чтобы игрок оставался в центре экрана.
Обработка изменения размера окна
def on_resize(self, width, height):
""" Изменение размера окна """
self.camera_sprites.resize(int(width), int(height))
self.camera_gui.resize(int(width), int(height))
Метод on_resize
обрабатывает изменение размера окна игры, обновляя размеры игровых камер.
Главная функция
def main():
"""Основная функция"""
window = MyGame()
window.setup()
arcade.run()
if __name__ == "__main__":
main()
Главная функция main
создает экземпляр класса MyGame
, настраивает игру и запускает игровой цикл с помощью arcade.run()
.
Этот код является шаблоном для создания платформерной игры с использованием библиотеки Arcade. Он включает в себя настройку окна, загрузку карты, создание игрока, обработку событий клавиатуры, рендеринг игры и игровую логику. Вы можете использовать этот шаблон как основу для создания собственных платформерных игр, добавляя больше функциональности и элементов дизайна.
полный листинг игры
"""
Platformer Template
"""
import arcade
# --- Constants
SCREEN_TITLE = "Platformer"
SCREEN_WIDTH = 1000
SCREEN_HEIGHT = 650
# Constants used to scale our sprites from their original size
CHARACTER_SCALING = 1
TILE_SCALING = 0.5
COIN_SCALING = 0.5
SPRITE_PIXEL_SIZE = 128
GRID_PIXEL_SIZE = SPRITE_PIXEL_SIZE * TILE_SCALING
# Movement speed of player, in pixels per frame
PLAYER_MOVEMENT_SPEED = 10
GRAVITY = 1
PLAYER_JUMP_SPEED = 20
class MyGame(arcade.Window):
"""
Main application class.
"""
def __init__(self):
# Call the parent class and set up the window
super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT,
SCREEN_TITLE, resizable=True)
# Our TileMap Object
self.tile_map = None
# Our Scene Object
self.scene = None
# Separate variable that holds the player sprite
self.player_sprite = None
# Our physics engine
self.physics_engine = None
# A Camera that can be used for scrolling the screen
self.camera_sprites = None
# A non-scrolling camera that can be used to draw GUI elements
self.camera_gui = None
# Keep track of the score
self.score = 0
# What key is pressed down?
self.left_key_down = False
self.right_key_down = False
def setup(self):
"""Set up the game here. Call this function to restart the game."""
# Setup the Cameras
self.camera_sprites = arcade.Camera(self.width, self.height)
self.camera_gui = arcade.Camera(self.width, self.height)
# Name of map file to load
map_name = ":resources:tiled_maps/map.json"
# Layer specific options are defined based on Layer names in a dictionary
# Doing this will make the SpriteList for the platforms layer
# use spatial hashing for detection.
layer_options = {
"Platforms": {
"use_spatial_hash": True,
},
}
# Read in the tiled map
self.tile_map = arcade.load_tilemap(map_name, TILE_SCALING, layer_options)
# Initialize Scene with our TileMap, this will automatically add all layers
# from the map as SpriteLists in the scene in the proper order.
self.scene = arcade.Scene.from_tilemap(self.tile_map)
# Set the background color
if self.tile_map.background_color:
arcade.set_background_color(self.tile_map.background_color)
# Keep track of the score
self.score = 0
# Set up the player, specifically placing it at these coordinates.
src = ":resources:images/animated_characters/female_adventurer/femaleAdventurer_idle.png"
self.player_sprite = arcade.Sprite(src, CHARACTER_SCALING)
self.player_sprite.center_x = 128
self.player_sprite.center_y = 128
self.scene.add_sprite("Player", self.player_sprite)
# --- Other stuff
# Create the 'physics engine'
self.physics_engine = arcade.PhysicsEnginePlatformer(
self.player_sprite, gravity_constant=GRAVITY, walls=self.scene["Platforms"]
)
def on_draw(self):
"""Render the screen."""
# Clear the screen to the background color
self.clear()
# Activate the game camera
self.camera_sprites.use()
# Draw our Scene
# Note, if you a want pixelated look, add pixelated=True to the parameters
self.scene.draw()
# Activate the GUI camera before drawing GUI elements
self.camera_gui.use()
# Draw our score on the screen, scrolling it with the viewport
score_text = f"Score: {self.score}"
arcade.draw_text(score_text,
start_x=10,
start_y=10,
color=arcade.csscolor.WHITE,
font_size=18)
def update_player_speed(self):
# Calculate speed based on the keys pressed
self.player_sprite.change_x = 0
if self.left_key_down and not self.right_key_down:
self.player_sprite.change_x = -PLAYER_MOVEMENT_SPEED
elif self.right_key_down and not self.left_key_down:
self.player_sprite.change_x = PLAYER_MOVEMENT_SPEED
def on_key_press(self, key, modifiers):
"""Called whenever a key is pressed."""
# Jump
if key == arcade.key.UP or key == arcade.key.W:
if self.physics_engine.can_jump():
self.player_sprite.change_y = PLAYER_JUMP_SPEED
# Left
elif key == arcade.key.LEFT or key == arcade.key.A:
self.left_key_down = True
self.update_player_speed()
# Right
elif key == arcade.key.RIGHT or key == arcade.key.D:
self.right_key_down = True
self.update_player_speed()
def on_key_release(self, key, modifiers):
"""Called when the user releases a key."""
if key == arcade.key.LEFT or key == arcade.key.A:
self.left_key_down = False
self.update_player_speed()
elif key == arcade.key.RIGHT or key == arcade.key.D:
self.right_key_down = False
self.update_player_speed()
def center_camera_to_player(self):
# Find where player is, then calculate lower left corner from that
screen_center_x = self.player_sprite.center_x - (self.camera_sprites.viewport_width / 2)
screen_center_y = self.player_sprite.center_y - (self.camera_sprites.viewport_height / 2)
# Set some limits on how far we scroll
if screen_center_x < 0:
screen_center_x = 0
if screen_center_y < 0:
screen_center_y = 0
# Here's our center, move to it
player_centered = screen_center_x, screen_center_y
self.camera_sprites.move_to(player_centered)
def on_update(self, delta_time):
"""Movement and game logic"""
# Move the player with the physics engine
self.physics_engine.update()
# See if we hit any coins
coin_hit_list = arcade.check_for_collision_with_list(
self.player_sprite, self.scene["Coins"]
)
# Loop through each coin we hit (if any) and remove it
for coin in coin_hit_list:
# Remove the coin
coin.remove_from_sprite_lists()
# Add one to the score
self.score += 1
# Position the camera
self.center_camera_to_player()
def on_resize(self, width, height):
""" Resize window """
self.camera_sprites.resize(int(width), int(height))
self.camera_gui.resize(int(width), int(height))
def main():
"""Main function"""
window = MyGame()
window.setup()
arcade.run()
if __name__ == "__main__":
main()