Kivy — мобильные приложения и игры на Python
Что такое Kivy
Kivy — open-source фреймворк для кроссплатформенных приложений с сенсорным вводом. Интерфейс рисуется через OpenGL ES 2, поэтому один и тот же код можно запускать на Windows, macOS, Linux, Android и (с ограничениями) iOS. Для учебных мобильных игр и прототипов на Python Kivy — практичная альтернатива тяжёлым движкам вроде Unity.
Виджет в Kivy — узел дерева UI с координатами, размером и обработчиками событий. Главный цикл Kivy не пишут вручную: его запускает App.run(), а кадры и таймеры планируют через Clock. Это отличает Kivy от Pygame, где цикл while running — центр программы (см. Разработка игр на Python).
Краткий обзор в экосистеме Python — в справочнике библиотек. В этой статье — архитектура, отличия от Pygame/Tkinter/Flutter и маршрут к практикумам (2048, Pong, Snake).
Мобильный контекст — ограничения платформы, магазины, сенсорный UI — раздел "Мобильные приложения", Мобильные игры.
Игры на десктопе — Pygame и учебный практикум — Разработка игр на Python, Практикум разработки игр.
Окна с формами — встроенный Tkinter — Tkinter и GUI, галерея виджетов в Lab.
Сравнение Kivy, Pygame, Tkinter и Flutter
| Критерий | Kivy | Pygame | Tkinter | Flutter |
|---|---|---|---|---|
| Цель | Мультитач UI, мобильные игры | 2D-игры на десктопе | Десктопные формы | Нативный мобильный UI |
| Графика | OpenGL, canvas | SDL, blit на Surface | Системные виджеты Tcl/Tk | Skia, Material/Cupertino |
| Сенсор | on_touch_*, свайпы | Мышь, джойстик | Мышь | Жесты из коробки |
| Сборка APK | Buildozer, python-for-android | Нет | Нет | flutter build apk |
| Кривая обучения | Средняя | Ниже для игр | Ниже для форм | Выше (Dart + экосистема) |
Правило выбора
- Уже знаете Python и нужна простая мобильная игра с тачем — Kivy.
- Игра только для ПК — Pygame и мини-игры в Lab.
- Нужен продуктовый мобильный UI с нативным видом — Flutter или Kotlin/Swift из мобильного раздела.
- Окно с кнопками и полями без OpenGL — Tkinter.
Установка и первый запуск
Перед Kivy полезно настроить окружение по Зависимости Python — venv и requirements.txt избавят от конфликтов пакетов.
python -m venv .venv
# Windows: .venv\Scripts\activate
# Linux/macOS: source .venv/bin/activate
pip install "kivy>=2.3.0"
Минимальное приложение:
from kivy.app import App
from kivy.uix.button import Button
class HelloApp(App):
def build(self):
return Button(text="Привет, Kivy!", on_press=lambda *_: print("tap"))
if __name__ == "__main__":
HelloApp().run()
Разбор.
App— точка входа: методbuild()возвращает корневой виджет,run()запускает цикл событий.on_press— обработчик нажатия; на мобильном это сработает и от тапа.if __name__ == "__main__"— тот же приём, что в первой программе на Python и точке входа__main__.
Запуск — python main.py. Окно появится на десктопе — это нормально: Kivy сначала отлаживают на ПК, затем упаковывают в APK (сборка APK).
Архитектура Kivy
App и жизненный цикл
Жизненный цикл мобильного экрана в общих чертах описан в Мобильных приложениях. В Kivy на практике важны три шага:
- Наследуем
kivy.app.App, реализуемbuild()— возвращаем корневой виджет. App.run()запускает главный цикл — обработка событий, отрисовка, таймеры.- Точка входа —
if __name__ == "__main__": ...App().run(), как в обычных Python-скриптах.
Виджеты и компоновка
Виджет (Widget и наследники) — прямоугольная область с pos, size и дочерними элементами. Layout раскладывает детей по правилам.
| Класс | Назначение |
|---|---|
BoxLayout | Вертикальный или горизонтальный стек |
GridLayout | Сетка с фиксированным числом столбцов (cols) |
FloatLayout | Абсолютное позиционирование дочерних элементов |
Widget | Пустая область — база для кастомной отрисовки на canvas |
Размеры задают двумя способами:
- Доля родителя —
size_hint=(1, 0.3)(ширина 100%, высота 30%). - Фиксированный размер —
size_hint_y=Noneиheight=dp(48)(см. ниже проdp).
Аналог компоновки в других стеках — Flutter Layout, Tkinter pack/grid.
Единицы dp и sp
dp (density-independent pixel) — логический пиксель, не зависящий от плотности экрана. kivy.metrics.dp(48) даёт одинаково "щёлкаемую" кнопку на телефоне и на мониторе с высоким DPI.
sp (scale-independent pixel) — для шрифтов; в Kivy пишут "22sp" в font_size.
На мобильных важен адаптивный дизайн — см. Мобильные игры (раздел про экраны и safe areas). В Kivy доли size_hint и dp — основной инструмент.
Отрисовка через canvas
Canvas — слой OpenGL-примитивов (Rectangle, Ellipse, Line, RoundedRectangle), привязанный к виджету. canvas.before рисует под дочерними виджетами (фон), canvas — поверх фона, но логика та же.
from kivy.graphics import Color, Rectangle
with self.canvas:
Color(0.2, 0.8, 1, 1)
self.rect = Rectangle(pos=self.pos, size=self.size)
self.bind(pos=self._sync, size=self._sync)
Разбор.
with self.canvas— контекстный менеджер добавляет примитивы на слой виджета.Color(r, g, b, a)— компоненты 0..1, не 0..255.bind(pos=..., size=...)обязателен: без него при ресайзе окна прямоугольник "отстанет" от виджета.
В практикуме Pong ракетка и мяч — виджеты с Rectangle/Ellipse; в 2048 — RoundedRectangle у плиток.
Игровой цикл и Clock
В Pygame игровой цикл — явный while running с clock.tick(60) (теория в 312). В Kivy кадры планируют через Clock:
from kivy.clock import Clock
Clock.schedule_interval(self.update, 1.0 / 60.0) # ~60 FPS
def update(self, dt):
self.ball.x += self.ball.velocity_x * dt
Разбор.
dt— секунды с прошлого вызова; умножение скорости наdtдаёт движение, не зависящее от частоты кадров (как в физике Pong на Pygame).schedule_once— один отложенный вызов (подача мяча через 0.8 с после гола).- Отмена —
event.cancel(); в Snake интервал пересоздают при ускорении.
Сенсорный ввод
Touch в Kivy — объект с координатами touch.x, touch.y. Цепочка событий:
on_touch_down— палец коснулся экрана;on_touch_move— палец движется;on_touch_up— палец оторван.
Свайп — разность координат между down и up. Сохраняют _touch_start, сравнивают dx/dy с порогом dp(30) — так сделано в Kivy — 2048 и Kivy — Snake. Теория жестов — Мобильные игры (тап, свайп, виртуальные кнопки).
Перетаскивание — обновление позиции в on_touch_move, пока player_touch_active — Kivy — Pong.
Клавиатура на десктопе — Window.bind(on_key_down=handler); удобно при отладке на ПК без телефона.
Возврат True из обработчика означает "событие обработано" и останавливает всплытие к родителю.
Properties и привязки
Property в Kivy — объявленный атрибут с уведомлением при изменении. Пример:
from kivy.properties import NumericProperty
class Paddle(Widget):
score = NumericProperty(0)
# где-то в App:
self.field.player.bind(score=self._update_score_labels)
При player.score += 1 Kivy сам вызовет _update_score_labels — не нужно вручную обновлять Label после каждого гола. Подробнее в практикуме Pong, этап 8.
Разделение логики и UI
Модель хранит состояние и правила; представление рисует и принимает ввод. Связь — тонкий слой: game.move("left") → board.refresh().
В учебных проектах Kivy:
- 2048 —
game_logic.py(Game2048) не импортирует Kivy;main.pyтолько рисует сетку. - Pong / Snake — логика в
GameField/SnakeBoard, корневой layout — вApp.build().
Тот же приём — в SmallPong на Pharo (PongGame + PongGameMorph) и Pygame-практикуме Pong (пакет game/).
Плюсы разделения:
- логику можно проверить без GUI (тесты, REPL);
- проще перенести UI на другой фреймворк;
- меньше смешивания математики и отрисовки в одном файле.
Сборка APK
Для Android обычно используют Buildozer — обёртку над python-for-android, которая собирает Python, Kivy и зависимости в APK.
Типичные шаги:
- Установите зависимости Buildozer (Linux или WSL; на Windows нативная сборка часто проблемна — см. сравнение стеков).
- Создайте
buildozer.specсrequirements = python3,kivy. - Выполните
buildozer android debug— получите APK для установки по USB (установка на телефон).
Подпись, keystore и публикация — Сборка мобильных приложений и Публикация Android.
Сначала доведите игру до рабочего состояния на десктопе (python main.py), затем переходите к Buildozer. Отладка графики и тача в эмуляторе Android сложнее, чем в окне Kivy на ПК.
Практикумы — три мобильные игры
Пошаговые реализации с самопроверкой на каждом этапе:
| Игра | Фокус | Статья |
|---|---|---|
| 2048 | Свайпы, сетка, JsonStore, логика без UI | Kivy — 2048 |
| Pong | Clock, физика мяча, тач, ИИ | Kivy — Pong |
| Snake | Тик змейки, еда, D-pad + свайп | Kivy — Snake |
Обзор маршрута и порядок прохождения — Практикум Kivy — о разделе.
Частые ошибки
| Симптом | Причина | Что сделать |
|---|---|---|
| Чёрный экран | Не вызван App.run() или build() вернул None | Проверьте точку входа и return в build() |
| Графика "плывёт" при ресайзе | Не обновляются Rectangle.pos / size | bind(pos=..., size=...) на виджете |
| Свайп не срабатывает | Порог слишком большой или touch уходит в дочерний виджет | Уменьшите порог dp(20–30), перехватите touch на поле |
| Игра "тормозит" на телефоне | Тяжёлая логика в on_touch_move | Перенесите физику в Clock, touch только меняет состояние |
pip install kivy падает | Нет SDL2 / зависимостей ОС | Документация Kivy — Installation |
Официальные материалы
- Kivy Documentation
- Kivy Garden — дополнительные виджеты
- Buildozer — сборка APK