Практика в Jupyter Notebook — это основа нашего курса по Data Science. Но интерактивный блокнот можно использовать не только для работы. За подробностями из блога разработчиков Jupyter Notebook приглашаем под кат.


Очевидно, что в Jupyter нужны игры попроще, около 1000 строк кода, на разработку которых не уйдёт не много дней, а несколько часов: Pong, Pinball и AngryBirds. Поэтому сделаем акцент на 2D-играх с моделированием физической среды: их очень легко реализовать при помощи движков типа Box2D или Chipmunk2D.

Box2D

Box2D — это библиотека для моделирования в играх поведения твёрдых тел в двумерном пространстве. Вот её лучшая демонстрация, скомпилированная в JavaScript с помощью Emscripten. Попробуйте:

С помощью Box2D легко писать игры, моделирующие физическую среду, механику твёрдых тел и действие физических сил. Например, Angry Birds или World of Goo.

Box2D: Debug Draw

DebugDraw

В Box2D есть абстрактный класс DebugDraw с методами рисования простейших элементов. Вот его API:

DebugDraw на Box2D в действии:

Реализация этого абстрактного класса позволяет рисовать физические объекты для пользовательского интерфейса. В Box2D есть реализация DebugDraw на glfw. В Python можно сделать её на pygame или kivy. Этих отрисовок и DebugDraw более чем достаточно, чтобы быстро протестировать игровые идеи в Box2D. В готовом продукте они заменены на специальные процедуры отрисовки.

LiquidFun

LiquidFun — ещё одна библиотека 2D-моделирования поведения твёрдых тел и жидкости в играх, написанных на C++ с Box2D. Лучше всего её объясняет демо, скомпилированное в JavaScript с помощью Emscripten (запускается в браузере):

Больше, чем просто игры

Но Box2D — это не только физический движок для игр в 2D, он используется и в образовании: на YouTube-канале iforce2d в Box2D сделали двигатель внутреннего сгорания и аэродинамическую трубу.

И такая аэродинамическая труба:

Box2D на Python

В Box2D есть биндинги для многих языков, он компилируется в Wasm. Вот несколько демо:

Особенно интересно использование Box2D / LiquidFun в Python. Здесь есть такие возможности:

pybox2d

Благодаря pybox2d в Box2D есть зрелые и надёжные привязки Python с обширной документацией. И вот недостатки pybox2d, он:

  • работает только со старой версией Box2D;

  • нет поддержки LiquidFun;

  • почти нет сопровождения pybox2d;

  • привязки Python генерируются с помощью SIWG (лично я предпочитаю pybind11).

pyb2d

Сразу оговорюсь: pyb2d для Box2D на Python сделал я (хотелось написать биндинги для Box2D / LiquidFun с помощью pybind11). Хотя pyb2d работает с новой версией Box2D 2.4.1 и поддерживает LiquidFun и pybind11, кое в чём он уступает pybox2d:

  • у pyb2d меньше примеров;

  • он не такой зрелый и надёжный;

  •  пока не так хорошо документирован.

Особенно впечатляет BatchDebugDraw на pyb2d. API DebugDraw можно было сделать прямо в Python, но такая реализация имела бы ряд недостатков:

  • Когда в игре много фигур, например окружностей, приходится очень часто вызывать drawCircle и выполнять много вызовов из C++ в Python и наоборот, это приводит к определённым накладным расходам.

  • Есть бэкенды с возможностью пакетного рисования, позволяющие рисовать несколько простейших элементов одновременно. Например, 100 окружностей в разных местах всего одним вызовом функции, аргументы которой — массивы NumPy ndarray с центрами/радиусами окружностей. Использование такого API-пакета может привести к огромному ускорению.

API-пакет DebugDraw pyb2d для Python:

Эти недостатки устранены в реализации BatchDebugDraw на pyb2d. Здесь сначала собираются все отдельные вызовы, такие как drawCircle, drawSegment, drawPolygon и т. д. Их аргументы сохраняются в массивах NumPy. После того как все фигуры собраны, с помощью функций draw_circles, draw_segments, draw_polygons и т. д. вызывается Python API. Все фигуры передаются в Python в одном вызове функции. На стороне Python эти инструкции пакетного рисования передаются в batch-drawing API поддерживаемого пользовательского интерфейса (будем использовать API пакетного рисования ipycanvas для интеграции pyb2d с Jupyter).

Требования интеграции Box2D в Jupyter

Чтобы сделать из Jupyter платформу для разработки игр, требуется:

  • поверхность/холст для рисования контента игр;

  • доступ к устройствам ввода (мышь, клавиатура или даже геймпады). Без взаимодействия с пользователем игры были бы скучными.

Ipycanvas, Ipywidgets, Ipyevents

В Jupyter огромная экосистема расширений. Для интеграции с Box2D нужно лишь выбрать из них нужные: Ipycanvas даёт доступ к HTML Canvas из ядер Python в Jupyter (это поверхность/холст для рисования элементов игр), а Ipywidets и Ipyevents — доступ к устройствам ввода (геймпадам, клавиатуре и мыши).

Ipycanvas

Ipycanvas — это легковесная библиотека, разработанная Мартином Рену и предоставляющая браузерный Canvas API для Jupyter. Она позволяет рисовать простейшие элементы (текст, линии, многоугольники, дуги, изображения и т. д.) прямо из Python. Освоив пару трюков, на ipycanvas достаточно быстро можно делать отличную анимацию, даже когда сервер и клиент на разных компьютерах (например, при запуске ipycanvas на Mybinder).

Попробуйте игру «Жизнь» на Ipycanvas:

DebugDraw на Ipycanvas

Первый этап интеграции pyb2d в Jupyter Notebook — реализация DebugDraw на Ipycanvas. Недавно мы выпустили новую версию Ipycanvas с расширенным API: рисовать теперь можно очень быстро. Используем её при реализации API DebugDraw.

Обработка событий в Jupyter

Здесь применяем Ipyevents. Очевидно, что при запуске игры надо управлять событиями. Для этого в Jupyter-notebook в выделенном потоке запускается цикл игры, а в основном потоке прослушиваются события.

Добавление кнопок

Кнопки для запуска, паузы и сброса игры на Box2D добавляются с помощью ipywidgets.

Что в итоге?

Мы интегрируем Box2D и pyb2d в Jupyter. Чтобы проверить интеграцию в деле, мы реализовали несколько игр:

Бильярд

Очень простая бильярдная игра, попробуйте её в модуле привязки:

Angry Shapes

Эта похожая на Angry Birds игра реализована с помощью pyb2d, попробуйте поиграть:

World of Goo homage

Тоже реализована с pyb2d, попробуйте:

Rocket

Управляйте ракетой с клавиатуры, только не попадите в чёрную дыру:

Совместимость

Все эти примеры pyb2d также запускаются в окне pygame или kivy — для них есть бэкенды. Хотите протестировать на pygame? В этом поможет бэкенд Jupyter: примеры можно разместить на MyBinder (здесь ими удобно пользоваться).

Нюансы

Хотя интеграция pyb2d с Jupyter даёт приличную частоту кадров даже при запуске через Mybinder, в бэкенде на pygame она обычно ещё выше, а игровой процесс более плавный.

Забегаем вперёд

Сейчас мы работаем над:

  • добавлением примеров и улучшением документации в pyb2d;

  • повышением производительности интеграции с Jupyter;

  • добавлением pyb2d в JupyterLite;

  • реализацией удалённого многопользовательского игрового процесса через режим совместной работы JupyterLab.

В этом режиме можно подключаться к Notebook с двух компьютеров и играть на бильярде друг против друга:

Научиться решать сложные задачи с помощью Jupyter Notebook вы сможете на наших курсах:

Узнайте подробности здесь.

Профессии и курсы

Комментарии (1)


  1. telpos
    13.01.2022 16:22

    Есть что-то подобное для геометрической оптики?