Главная » Игры » Создаем 2D игру на Python с библиотекой Arcade

Создаем 2D игру на Python с библиотекой Arcade

Всем привет!

Сегодня вот решили разобраться с 2D играми. Мы продолжаем делится с вами интересными найденными вещами про питончик. Это, конечно, немного попроще, чем то, что проходят у нас на курсе «Разработчик Python», но не менее интересно это уж точно.

Поехали.

Он также идеально подходит тем, кто хочет “просто взять и сделать”, а не тратить кучу времени на шаблонный код. Python — выдающийся язык для начинающих изучать программирование. В этом статье я объясню, как начать использовать Python и Arcade для программирования игр. Arcade — библиотека Python для создания 2D игр, с низким порогом вхождения, но очень функциональная в опытных руках.

Я очно преподавал PyGames в течение почти 10 лет, а также разработал ProgramArcadeGames.com для обучения онлайн. Я начал разрабатывать на Arcade после преподавания азов библиотеки PyGame студентам. PyGames отличная, но в какой-то момент я понял, что устал тратить время на оправдание багов, которые никогда не фиксятся.

И был целый раздел, в котором я объяснял, почему y-координаты повернуты в противоположном направлении. Меня беспокоило преподавание таких вещей, как событийный цикл, которым уже почти не пользовались. На светлое будущее я не рассчитывал. PyGames обновлялась редко и базировалась на старой библиотеке SDL 1, а не чем-то более современном вроде OpenGL.

Ей оказалась Arcade. В моих мечтах была простая и мощная библиотека, которая бы использовала новые фичи Python 3, например, декораторы и тайп-хинтинг. Посмотрим, как начать ее использовать.

Установка

Arcade, как и многие другие пакеты, доступна на PyPi, а значит, можно установить Arcade при помощи команды pip (или pipenv). Если Python уже установлен, скорее всего можно просто открыть командную строку Windows и написать:

pip install arcade

А в Linux и MacOS:

pip3 install arcade

Для более детализированной инструкции по установке, почитайте документацию по установке Arcade.

Простой рисунок

Вы можете открыть окно и нарисовать простой рисунок всего несколькими строчками кода. В качестве примера, нарисуем смайлик, как на картинке ниже:

Заметьте, что вам не обязательно знать, как использовать классы или определять функции. Скрипт ниже показывает, как это сделать, используя команды рисования Arcade. Программирование с быстрым визуальным фидбеком — хороший старт для тех, кто только учится.

import arcade # Задать константы для размеров экрана
SCREEN_WIDTH = 600
SCREEN_HEIGHT = 600 # Открыть окно. Задать заголовок и размеры окна (ширина и высота)
arcade.open_window(SCREEN_WIDTH, SCREEN_HEIGHT, "Drawing Example") # Задать белый цвет фона.
# Для просмотра списка названий цветов прочитайте:
# http://arcade.academy/arcade.color.html
# Цвета также можно задавать в (красный, зеленый, синий) и
# (красный, зеленый, синий, альфа) формате.
arcade.set_background_color(arcade.color.WHITE) # Начать процесс рендера. Это нужно сделать до команд рисования
arcade.start_render() # Нарисовать лицо
x = 300
y = 300
radius = 200
arcade.draw_circle_filled(x, y, radius, arcade.color.YELLOW) # Нарисовать правый глаз
x = 370
y = 350
radius = 20
arcade.draw_circle_filled(x, y, radius, arcade.color.BLACK) # Нарисовать левый глаз
x = 230
y = 350
radius = 20
arcade.draw_circle_filled(x, y, radius, arcade.color.BLACK) # Нарисовать улыбку
x = 300
y = 280
width = 120
height = 100
start_angle = 190
end_angle = 350
arcade.draw_arc_outline(x, y, width, height, arcade.color.BLACK, start_angle, end_angle, 10) # Завершить рисование и показать результат
arcade.finish_render() # Держать окно открытым до тех пор, пока пользователь не нажмет кнопку “закрыть”
arcade.run()

Использование функций

Конечно, писать код в глобальном контексте — не лучший способ. К счастью, использование функций поможет улучшить ваш код. Ниже приведен пример того, как нарисовать елку в заданных координатах (x, y), используя функцию:

def draw_pine_tree(x, y): """ Эта функция рисует елку в указанном месте""" # Нарисовать треугольник поверх ствола. # Необходимы три x, y точки для рисования треугольника. arcade.draw_triangle_filled(x + 40, y, # Point 1 x, y - 100, # Point 2 x + 80, y - 100, # Point 3 arcade.color.DARK_GREEN) # Нарисовать ствол arcade.draw_lrtb_rectangle_filled(x + 30, x + 50, y - 100, y - 140, arcade.color.DARK_BROWN)

Для полного примера, посмотрите рисунок с функциями.

Arcade это поддерживает. Более опытные программисты знают, что современные программы сначала загружают графическую информацию на видеокарту, а затем просят ее отрисовать batch-файлом. 8 секунды. Индивидуальная отрисовка 10000 прямоугольников занимает 0. 001 секунды. Отрисовка того же количества батником займет менее 0.

Класс Window

Большие программы обычно базируются на классе Window или используют декораторы. Это позволяет программисту писать код, контролирующий отрисовку, обновление и обработку входных данных пользователя. Ниже приведен шаблон для программы с Window-основой.

import arcade SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600 class MyGame(arcade.Window): """ Главный класс приложения. """ def __init__(self, width, height): super().__init__(width, height) arcade.set_background_color(arcade.color.AMAZON) def setup(self): # Настроить игру здесь pass def on_draw(self): """ Отрендерить этот экран. """ arcade.start_render() # Здесь код рисунка def update(self, delta_time): """ Здесь вся игровая логика и логика перемещения.""" pass def main(): game = MyGame(SCREEN_WIDTH, SCREEN_HEIGHT) game.setup() arcade.run() if __name__ == "__main__": main()

В классе Window есть несколько методов, которые ваши программы могут переопределять для обеспечения функциональности. Вот список тех, что используются чаще всего:

  • on_draw: Весь код для отрисовки экрана находится здесь.
  • update: Весь код для перемещения объектов и отработки игровой логики находится здесь. Вызывается примерно 60 раз в секунду.
  • on_key_press: Обрабатывает события при нажатии кнопки, например, движение персонажа.
  • on_key_release: Обрабатывает события при отпускании кнопки, например, остановка персонажа.
  • on_mouse_motion: Вызывается каждый раз при движении мышки.
  • on_mouse_press: Вызывается при нажатии кнопки мыши.
  • set_viewport: Эта функция используется в скроллерах, когда мир значительно больше, чем то что видно на одном экране. Вызов set_viewport позволяет программисту задать ту часть экрана, которая будет видна.

Спрайты

Спрайты — простой способ создания 2D bitmap объектов в Arcade. В нем есть методы, позволяющие с легкостью рисовать, перемещать и анимировать спрайты. Также можно использовать спрайты для отслеживания коллизий между объектами.

Создание спрайта

Создать инстанс Sprite класса Arcade очень легко. Программисту необходимо только название файла изображения, на котором будет основываться спрайт, и, опционально, число раз для увеличения или уменьшения изображения. Например:

SPRITE_SCALING_COIN = 0.2 coin = arcade.Sprite("coin_01.png", SPRITE_SCALING_COIN)

Этот код создает спрайт, используя изображение coin_01.png. Картинка уменьшится до 20% от исходной.

Список спрайтов

Спрайты обычно организуются в списки. Они помогают упростить их управление. Спрайты в списке будут использовать OpenGl для групповой batch-отрисовки. Нижеприведенный код настраивает игру, где есть игрок и множество монет, которые игрок должен собрать. Мы используем два списка — один для игрока и один для монеток.

def setup(self): """ Настроить игру и инициализировать переменные. """ # Создать список спрайтов self.player_list = arcade.SpriteList() self.coin_list = arcade.SpriteList() # Счет self.score = 0 # Задать игрока и # Его изображение из kenney.nl self.player_sprite = arcade.Sprite("images/character.png", SPRITE_SCALING_PLAYER) self.player_sprite.center_x = 50 # Стартовая позиция self.player_sprite.center_y = 50 self.player_list.append(self.player_sprite) # Создать монетки for i in range(COIN_COUNT): # Создать инстанс монеток # и их изображение из kenney.nl coin = arcade.Sprite("images/coin_01.png", SPRITE_SCALING_COIN) # Задать положение монеток coin.center_x = random.randrange(SCREEN_WIDTH) coin.center_y = random.randrange(SCREEN_HEIGHT) # Добавить монетку к списку self.coin_list.append(coin)

Мы с легкостью можем отрисовать все монетки в списке монеток:

def on_draw(self): """ Нарисовать все """ arcade.start_render() self.coin_list.draw() self.player_list.draw()

Отслеживание коллизий спрайтов

Функция check_for_collision_with_list позволяет увидеть, если спрайт наталкивается на другой спрайт из списка. Используем ее, чтобы увидеть все монетки, с которыми пересекается спрайт игрока. Применив простой for- цикл, можно избавиться от монетки в игре и увеличить счет.

def update(self, delta_time): # Сгенерировать список всех спрайтов монеток, которые пересекаются с игроком. coins_hit_list = arcade.check_for_collision_with_list(self.player_sprite, self.coin_list) # Пройтись циклом через все пересекаемые спрайты, удаляя их и увеличивая счет. for coin in coins_hit_list: coin.kill() self.score += 1

С полным примером можно ознакомиться в collect_coins.py.

Игровая физика

Во многих играх есть физика в том или ином виде. Самые простое, например, что top-down игры не позволяют игроку проходить сквозь стены. Платформеры добавляют сложности с гравитацией и движущимися платформами. Некоторые игры используют полноценные физические 2D движки с массами, трением, пружинами и тд.

Top-down игры

Обычно я называю это wall_list. Для простых игр с видом сверху программе на Arcade необходим список стен (или чего-то подобного), через которые игрок не сможет проходить. Затем создается физический движок в установочном коде класса Window:

self.physics_engine = arcade.PhysicsEngineSimple(self.player_sprite, self.wall_list)

player_sprite получает вектор движения с двумя атрибутами change_x и change_y. Просто пример использования — перемещение игрока с помощью клавиатуры.

MOVEMENT_SPEED = 5 def on_key_press(self, key, modifiers): """Вызывается при нажатии пользователем клавиши""" if key == arcade.key.UP: self.player_sprite.change_y = MOVEMENT_SPEED elif key == arcade.key.DOWN: self.player_sprite.change_y = -MOVEMENT_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.UP or key == arcade.key.DOWN: self.player_sprite.change_y = 0 elif key == arcade.key.LEFT or key == arcade.key.RIGHT: self.player_sprite.change_x = 0

Несмотря на то что этот код задает скорость игрока, он его не перемещает. Метод update в классе Window вызывает physics_engine.update(), что заставит игрока двигаться, но не через стены.

def update(self, delta_time): """ Передвижение и игровая логика """ self.physics_engine.update()

Пример полностью можно посмотреть в sprite_move_walls.py.

Платформеры

Программисту необходимо переключить физический движок на PhysicsEnginePlatformer и добавить гравитационную константу. Переход к платформеру с видом сбоку достаточно прост.

self.physics_engine = arcade.PhysicsEnginePlatformer(self.player_sprite, self.wall_list, gravity_constant=GRAVITY)

Для добавления тайлов и блоков, из которых будет состоять уровень, можно использовать программу вроде Tiled.

Пример доступен в sprite_tiled_map.py.

Учитесь на примере

Учиться на примере — один из лучших методов. В библиотеке Arcade есть большой список образцов программ, на которые можно ориентироваться при создании игры. Эти примеры раскрывают концепты игр, о которых спрашивали мои онлайн и оффлайн студенты в течение нескольких лет.

В начале программы каждого примера есть комментарий с командой, которую нужно ввести в командную строку для запуска этого примера. Запускать демки при установленной Arcade совсем не сложно. Например:

python -m arcade.examples.sprite_moving_platforms

THE END

Как всегда ждём ваши комментарии и вопросы, которые можно оставить тут или зайти к Стасу на день открытых дверей.


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

Trekz Air — как на самом деле звучат наушники с костной проводимостью

Осенний привет хабровчанам! Большая аудиотека пополняется благодаря стриминговым сервисам. По жизни я — меломан, и провожу с музыкой непростительно много времени — по 8-12 часов в день. Всё сокровенное храню на плеере, используя наушники с большим количеством излучателей: TBA04, NuForce ...

[Перевод] Делаем проект по машинному обучению на Python. Часть 3

Перевод A Complete Machine Learning Walk-Through in Python: Part Three В этой статье мы постараемся разобраться, как созданная нами модель делает прогнозы и что она может рассказать о решаемой нами задаче. Многим не нравится, что модели машинного обучения представляют собой ...