Pull to refresh

Разработка игр с использованием Cocos2d на Python

Reading time 5 min
Views 31K
image

Введение


Имплементация Cocos2d на Objective-C используется для разработки игр для iPhone весьма широко. По данным официального сайта число игр на этом движке уже превышает 1800. Не раз упоминался он и на Хабре. Другие порты (cocos2d-x на C++ и cocos2d-android на Java) также известны и набирают популярность. Однако прародитель этих движков, оригинальный Cocos2d оказался незаслуженно обойден вниманием. Попробую восполнить этот пробел.

Cocos2d написан на языке Python с использованием библиотеки pyglet. В силу использования Python и простой архитектуры он кросплатформенный и хорошо подходит для быстрого прототипирования и тестирования концепций игр. Движок несколько отстает от своих потомков в части реализации некоторых возможностей, однако на практике это не вызывает сложностей. Проблемой движка является низкое качество документации: официальный гайд описывает самые базовые концепции, а затем пестрит перманентными заглушками TODO. API также содержит мало комментариев. Тем не менее, в комплекте идут примеры и тесты, которые позволяют ознакомиться с основными приемами программирования.

Итак, устанавливаем Cocos2d и приступаем.

Сцены и поток управления


Сцена (класс cocos.scene.Scene) — это один уровень или экран вашей игры. Все игровые объекты, принадлежащие конкретному уровню, размещаются на соответствующей сцене. Для управления сценами используется синглтон director (cocos.director.director).

# задействуем cocos2d
import cocos

# инициализируем director; аргументами можно передать размер окна, заголовок и пр.
cocos.director.director.init()

# создаем новую пустую сцену и передаем ее директору, запуская таким образом основной цикл
cocos.director.director.run(cocos.scene.Scene())

В процессе игры director контролирует стэк сцен. Стэк сцен — очень удобная концепция. Когда новая сцена помещается на стэк, директор приступает к ее исполнению, а предыдущая сцена приостанавливается. Когда верхняя сцена снимается со стэка, директор возобновляет исполнение предыдущей сцены. Таким образом, например, можно реализовать вложенные уровни или внутриигровые меню. Для операций со стэком сцен используются методы директора push(), pop() и replace(). Вызов replace() эквивалентен последовательному вызову pop() и push().

Структура сцены


Сцена (scene) представляет собой набор объектов (узлов), организованных в виде дерева. Корнем дерева является сама сцена. Трансформации родителя (положение, угол наклона, масштаб) в такой модели влияют на трансформации детей. Таким образом можно строить сложные составные объекты и легко управлять их отображением. В движке представлен широкий спектр готовых примитивов узлов (например, слой (cocos.layer.Layer), спрайт (cocos.sprite.Sprite), текст (cocos.text.Label), система частиц (cocos.particle.ParticleSystem) и многие другие). Можно писать свои узлы, наследуя от cocos.cocosnode.CocosNode или производных классов.

import cocos
cocos.director.director.init()

# создаем новую пустую сцену
scene = cocos.scene.Scene()

# добавляем узел с текстом
scene.add(cocos.text.Label("Hello world!", position = (100, 200))

# исполняем сцену
cocos.director.director.run(scene)

Структура сцены формируется с использованием методов узлов add(), remove() и kill().

Объекты могут контролировать свое (и не только свое) состояние при помощи функций обратного вызова, создавать которые довольно просто. Для иллюстрации создадим производный узел с вращающимся текстом:

import cocos

class RotatingText(cocos.text.Label):
&nbsp&nbsp# инициализируем базовый класс и настраиваем обратный вызов
&nbsp&nbspdef __init__(self, text = "", position = (0, 0)):
&nbsp&nbsp&nbsp&nbspsuper(RotatingText, self).__init__(text, position)
&nbsp&nbsp&nbsp&nbspself.schedule(self.update)

&nbsp&nbsp# функция обратного вызова, модифицируем угол поворота в зависимости от прошедшего времени
&nbsp&nbspdef update(self, dt):
&nbsp&nbsp&nbsp&nbspself.rotation += dt * 20

cocos.director.director.init()
scene = cocos.scene.Scene()
scene.add(RotatingText("Hello world!", (100, 200)))
cocos.director.director.run(scene)

Действия


Описанного выше уже достаточно для того, чтобы написать простую демку, создав объекты и задав их поведение. Однако то, что делает Cocos2d таким гибким и мощным — это система действий (actions), и сейчас мы в ней разберемся.

Действие — это указание объекту изменить свое состояние.

import cocos
cocos.director.director.init()
scene = cocos.scene.Scene()
label = cocos.text.Label("Hello world!", position = (100, 200))
scene.add(label)
# текстовая метка будет перемещаться вправо на 200 пикселей в течение 5 секунд
label.do(cocos.actions.MoveBy((200, 0), duration = 5))
cocos.director.director.run(scene)

Действия бывают мгновенными и интервальными. Кроме того, действия бывают абсолютными и относительными. Список стандартных действий включает:
  • перемещение (мгновенное — Place, интервальные — MoveTo, MoveBy, JumpTo, JumpBy)
  • масштабирование (ScaleTo, ScaleBy)
  • поворот (RotateTo, RotateBy)
  • управление видимостью объекта (Show, Hide, Blink, ToggleVisibility)
  • управление прозрачностью (FadeIn, FadeOut, FadeTo)
Благодаря переопределенным операторам + и | действия можно комбинировать. Действия, скомбинированные с помощью суммирования, исполняются последовательно друг за другом.

# метка переместится вверх на 100 пикселей за 5 секунд и затем растворится за 3 секунды
label.do(cocos.actions.MoveBy((0, 100), 5) + cocos.actions.FadeOut(3))

Действия, скомбинированные с помощью дизъюнкции, исполняются параллельно.

# метка переместится вверх на 100 пикселей, одновременно поворачиваясь на 90 градусов, за 5 секунд
label.do(cocos.actions.MoveBy((0, 100), 5) | cocos.actions.RotateBy(90, 5))

Кроме того, есть действия-модификаторы, воздействующие на способ применения действий. Стандартные действия-модификаторы:
  • повтор (Repeat) — повторяет заданное действие бесконечно
  • ускорение (Accelerate, AccelDeccel) — изменяют ускорение действия в его процессе
  • изменение скорости (Speed) — изменяет время исполнения действия
  • обратное действие (Reverse) — данное действие будет исполнено в обратном направлении, если это возможно
  • и другие
# метка будет бесконечно перемещаться влево-вправо на 200 пикселей с периодом в 3 секунды
action = cocos.actions.MoveBy((200, 0), 3)
label.do(cocos.actions.Repeat(action + cocos.actions.Reverse(action)))

Отладка


Cocos2d содержит встроенный интерпретатор Python, который вызывается по умолчанию нажатием Ctrl-I. С помощью интерпретатора можно получить полную интроспекцию игры и вести разработку интерактивно. Исполнение при этом не останавливается.

Заключение


К сожалению, многие вопросы (такие как взаимодействие с пользователем, обработка событий, переходы между сценами и эффекты) остались за рамками данной статьи. Если хабровчанам интересны эти темы, попробую изложить их в следующей статье.

Официальный сайт Cocos2d
Tags:
Hubs:
+78
Comments 23
Comments Comments 23

Articles