Как запустить динозаврика Google на тачбаре? Пишем игру на Python

Не знаете, чем заняться на новогодних праздниках? Предлагаем отложить нарезку оливье и взяться за новый проект — написать свою игру для тачбара. В тексте показываем, как это сделать на Python всего за час.

<p><i>Вот что получится, если будете следовать инструкции.</i></p>

Вот что получится, если будете следовать инструкции.

С 2016 года у некоторых моделей MacBook Pro есть сенсорная OLED-панель. Она заменяет функциональные клавиши, закладки и элементы настроек.

Для программирования тачбара не обязательно погружаться в Swift и AppKit — достаточно знания Python и библиотеки PyTouchBar. С последним познакомимся подробней: напишем игру с динозавриком и освоим встроенные инструменты модуля.

Используйте навигацию, если нужно изучить конкретные шаги, а не читать инструкцию целиком:

Делаем меню и знакомимся с элементами библиотеки

Кнопка «играть»

PyTouchBar работает в связке с Tkinter. Для начала нужно установить и первый, и второй модули. А после — подготовить GUI-окно, которое будет отображаться на тачбаре. И добавить, например, кнопку «играть».

from tkinter import * import PyTouchBar # создание окна Tkinter root = Tk() # параметризация кнопки starter = PyTouchBar.TouchBarItems.Button(title='играть', color=(PyTouchBar.Color.green)) # добавление элемента PyTouchBar.set_touchbar([starter]) # подготовка окна PyTouchBar.prepare_tk_windows(root) root.mainloop()

После запуска программы кнопка отобразится на панели.

Как запустить динозаврика Google на тачбаре? Пишем игру на Python

Для окрашивания кнопки можно использовать встроенную константу PyTouchBar.Color. Или передать в функцию кортеж (r, g, b, a), где r, g, b, a — значения от 0 до 1.

Если нажать на кнопку, ничего не произойдет. Для запуска подпрограммы нужно добавить аргумент action и сослаться на имя функции.

# PyTouchBar, добавление функции для action. ... def start(button): # здесь будет запуск игровой сцены game print('Hello world') starter = PyTouchBar.TouchBarItems.Button(title='играть', color=(PyTouchBar.Color.green), action=start) ...

Подпрограмма start нужна для запуска игровой сцены game.

Настройка скорости динозаврика

Библиотека поддерживает не только простые кнопки, но и так называемые «степперы» — с помощью них можно вводить числовые значения. В нашем случае — скорость динозаврика.

# PyTouchBar, добавление степпера. ... # минимальная скорость speed = 2 def set_speed(stepper): global speed size = int(speed.value) print ('Скорость динозавра:', speed) speed_p = PyTouchBar.TouchBarItems.Stepper(min = 2, max = 7, action = set_speed) # параметризация степпера # добавление кнопки и степпера PyTouchBar.set_touchbar([speed_p, starter]) ...

После запуска программы элементы отобразятся на панели.

Как запустить динозаврика Google на тачбаре? Пишем игру на Python

На самом деле PyTouchBar поддерживает больше элементов. Некоторые из них мы добавим в игру ниже. Полный список ищите в официальной документации.

Загружаем игровую сцену из кактусов

Представление 2D-сцены

После нажатия кнопки «играть» должна сработать специальная функция game, которая нужна для отрисовки сцены — динозаврика и кактусов. Один из вариантов — добавить их с помощью кнопок, которые мы будем называть чанками.

Каждый чанк — целочисленное значение:

  • -2 — динозавр врезался в кактус,
  • -1 — кактус,
  • 0 — плоскость,
  • 1 — динозаврик,
  • 2 — динозавр перепрыгнул через кактус.

Карту можно представить так:

map = [1, 0, 0, -1, 0, -1, 0]

Визуализация элементов

Кнопки поддерживают параметр image: на фон можно поставить любое статическое изображение.

Так, например, можно «пройтись» циклом по списку map и наполнить список buttons кнопками с изображениями, выбранными по значениям чанков.

# Отрисовка карты map с помощью кнопок. ... for chunk in range(len(map)): if map[chink] == 1: buttons[chunk] = PyTouchBar.TouchBarItems.Button(image='assets/trex.png', color=(PyTouchBar.Color.black), action=jumping) elif map[chunk]== 0: buttons[chunk] = PyTouchBar.TouchBarItems.Button(image='assets/platform.png', color=(PyTouchBar.Color.black)) else: buttons[chunk] = PyTouchBar.TouchBarItems.Button(image='assets/cactus.png', color=(PyTouchBar.Color.black)) ...

В результате схема карты преобразится в игровую сцену.

Как запустить динозаврика Google на тачбаре? Пишем игру на Python

Что нужно учитывать

Для запуска сцены нужно закрыть root-окно и запустить новое. PyTouchBar не поддерживает обновление Tkinter-программ.

def game(map): # отрисовка карты map ... def prepare(): root = Tk() def start(button): # запускается по клику кнопки «играть» root.destroy() ... # генерируем карту и передаем в функцию игровой сцены game(map) ... PyTouchBar.set_touchbar([starter]) PyTouchBar.prepare_tk_windows(root) root.mainloop() prepare()

Но как тогда заставить динозаврика бежать?

Заставляем динозаврика бежать

Чтобы динозаврик побежал, нужно как-то обновлять сцену без root.update(). То есть уничтожать настоящую сцену с помощью root.destroy() и запускать новую с обновленными параметрами map. Получается некое обновление кадров.

Удаление старых кадров

Автоматизировать удаление старых кадров с помощью root.destroy() можно с помощью встроенного метода root.after(). Он умеет запускать отложенные функции.

# root.after(), пример вызова метода destroy. ... # после запуска Tkinter удалит кадр через 1 секунду root.after(1000, start.destroy) root.mainloop() ...

1000 — время, спустя которое удалится root-окно. Чем меньше значение, тем быстрее бежит динозаврик.

Создание новых кадров

Сам динозаврик не двигается. Обновляется только задний план — ландшафт сцены.

По сути, генерировать новые кадры можно разными способами. Выберем один из самых простых: будем делать срез списка на один элемент и добавлять рандомный чанк в конец. А после — запускать на новой карте игровую сцену game.

# Генерация новых кадров. Одна итерация — один новый кадр и чанк. ... # бесконечная генерация новых чанков и кадров while True: new_map = map[1:] # первый чанк — всегда динозавр (1) new_map[0] = 1 # условие, чтобы не генерировать два кактуса подряд if map[-1] == 0: new_map.append(random.choice([0, -1])) else: new_map.append(0) game(new_map) ...

На тачбаре это выглядит вот так:

Покадровое обновление игровой сцены.

Для большей плавности нужно создать ассеты для промежуточных кадров. И добавить в игровую сцену дополнительный цикл при отрисовке чанков.

Как запустить динозаврика Google на тачбаре? Пишем игру на Python

Добавление событий

Предпоследний этап — то, ради чего играют в Google-динозаврика, — «паркур по кактусам».

Чтобы добавить прыжок, нужно завести переменную jump — к ней мы будем прибавлять единицу при нажатии на кнопку с динозавром. И модифицировать список map таким образом, чтобы в первом чанке кактус и динозавр могли встретиться несколькими способами.

Динозаврик врезался в кактус — чанк -2. Комбинация [1, -1], jump = 0.

Как запустить динозаврика Google на тачбаре? Пишем игру на Python

Динозаврик перепрыгнул кактус — чанк 2. Комбинация [1, -1], jump = 1.

Как запустить динозаврика Google на тачбаре? Пишем игру на Python

Вот как «сценарии» записаны в программе:

# Ситуативная генерация новых кадров. ... jump = 0 # первый элемент — комбинация значений, где второе значение — следующий чанк map = [[1,0], 0, 0, -1, 0, -1, 0] ... while True: # итоговое значение для комбинации: # [1,0] → 1 кактуса нет, динозаврик бежит # [1,-1] → кактус есть: если jump = 1, все хорошо zero_chunk = 1 # записываем комбинацию map[0] = [1,map[1]] # динозаврик не прыгнул на прошлом чанке и врезался if jump == 0 and map[0] == [1, -1]: zero_chunk = -2 # на чанке без кактуса jump обнуляется elif jump >= 1 and map[0] == [1, 0]: jump = 0 zero_chunk = 1 # динозаврик прыгнул на прошлом чанке, все хорошо elif jump == 1 and map[0] == [1,-1]: zero_chunk = 2 points += 1 # настраиваем формат карты для передачи в функцию new_map = map[1:] new_map[0] = zero_chunk if map[-1] == 0: new_map.append(random.choice([0, -1])) else: new_map.append(0) map = new_map game(new_map)

В коде отрисовки сцены также нужно добавить новые события:

# Отрисовка игровой сцены. def game(buttons) ... for b in range(len(map)): # если динозаврик не перепрыгнул, загружаем ассет со столкновением if map[b] == -2: buttons[b] = PyTouchBar.TouchBarItems.Button(image='assets/loss.png', color=(PyTouchBar.Color.black)) # если динозаврик перепрыгнул, загружаем ассет с прыжком elif map[b] == 2: buttons[b] = PyTouchBar.TouchBarItems.Button(image='assets/lucky.png', color=(PyTouchBar.Color.black)) ...

На тачбаре это выглядит вот так:

Итоговый результат.

Выводим количество очков

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

Подсчет очков

Для подсчета очков нужно завести переменную points и прибавлять к ней единицу каждый раз, когда динозаврик перепрыгивает через кактус. Но с выводом сообщения немного сложней.

Вывод сообщения

Чтобы вывести сообщение, нужно создать новое окно Tkinter, подготовить его и добавить текстовое поле.

# PyTouchBar, добавление элемента Label. def finish(points): ... # объявление элемента label label = PyTouchBar.TouchBarItems.Label(text = f'Упс:( Вы набрали: {points}') ...

Элемент Label поддерживает разные шрифты, цвета и масштабы. Полный список параметров есть в официальной документации.

Притом вызвать функцию finish нужно после отрисовки сцены.

# Обработка окончания игры. while True: points = 0 ... # динозаврик не прыгнул на прошлом чанке и врезался if jump == 0 and map[0] == [1, -1]: zero_chunk = -2 elif jump == 1 and map[0] == [1, -1]: zero_chunk = 2 points += 1 ... game(new_map) # если динозаврик врезался — вызвать finish() if zero_chunk == -2: finish(points)

Как закрыть сообщение и программу?

У PyTouchBar есть особенность: с помощью библиотеки можно модифицировать встроенную кнопку escape. Например, сделать ее кнопкой для закрытия программы.

... def exit_f(button): exit() esc = PyTouchBar.TouchBarItems.Button(title = "exit", action = exit_f) PyTouchBar.set_touchbar(… , esc_key = esc) ...

Полная версия кода доступна на GitHub. Подключайтесь и предлагайте свои улучшения.

На что еще способна библиотека?

Даже с ограничениями библиотека кажется интересной. С помощью нее можно написать софт для решения повседневных задач. Например, сделать дополнительный ряд кнопок для всяких спецсимволов, если надоела раскладка Бирмана.

Но Doom с помощью PyTouchBar запустить будет сложно: не понятно, как «вытягивать» отдельные кадры и управлять игрой через панель. Для более сложных проектов лучше «прыгнуть в нору за кроликом» и программировать тачбар с помощью Objective-C.

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

Читайте также:

4444
13 комментариев

Вы молодец но опоздали на 5 лет )

6

нууу, как говорится
лучше поздно чем никогда))

2

Мде, игра для тачбара на макбуке... Звучит как интересный опыт, но охват аудитории у такого проекта будет околонулевой

4

А какая программа для тачбара могла бы найти своего пользователя? Поделитесь идеями — необязательно, чтобы это была игра)

1

Что можно вывести на полоску 0,5 см? ряд кастомных кнопок, больше ничего, для игр нормальный экран же есть, зачем извращаться...

суть-то в опыте. я не делал такого, мне интересно, и сделаю)

4

Можно, например, вывести Doom, если правильно сделать раскадровку и с высокой частотой обновлять бэкграунд кнопок)