Содержание урока · 10 разделов
- Игры на Go: что продаётся в Steam прямо сейчас
- Что такое Ebitengine: dead simple без кавычек
- Игровой цикл: Update, Draw и Layout за один вечер
- Платформы: одна кодовая база от Windows до Switch
- Куда собирается игра на Ebitengine
- Чего в Ebitengine нет — и почему это плюс
- Маршрут из 25 уроков крупными мазками
- Песочница урока
- Коротко: что запомнить
- Вопросы и ответы
Начнём с разговора, который был у каждого из нас. Вы пишете на Go сервисы: ручки, очереди, базы данных, деплой — и всё это по-настоящему интересно, но где-то на заднем плане сидит идея из детства: а здорово было бы сделать игру. Идея обычно умирает на первой же строчке гугла: «игры на go» — и поисковик отвечает горсткой устаревших обёрток над SDL. С 2014 года у этого вопроса есть ответ, который дожил до наших дней и стал стандартом ниши: Ebitengine, движок 2D-игр на чистом Go от Хадзиме Хоси. Не обёртка, не прототип, а зрелый проект с первым стабильным тегом v1.0.0 в январе 2015 года, второй мажорной версией в октябре 2020-го и сотнями выпущенных игр. Этот курс — 25 уроков от пустого окна до мини-аркады, и в первом уроке мы отвечаем на главный вопрос: почему вообще стоит писать игры именно здесь.
Игры на Go: что продаётся в Steam прямо сейчас#
Лучший ответ на скепсис — не аргументы, а витрина. На сайте движка есть страница Showcase, и это не набор демо: там перечислены коммерческие игры с их правообладателями. Японское издательство Odencat выпустило на Ebitengine целую линейку — приключенческие Meg's Monster и Fishing Paradiso, визуальные новеллы Mousebusters и Bear's Restaurant, сказку Snowman Story; все они продаются в Steam. Там же в витрине числится Rakuen от Morizora Studios — сюжетная ролевая игра, которую многие помнят по Steam-релизу 2017 года, и проекты студии Intrugli Games вроде Our Metal Bowl. Формулировка «игры на go» в 2020-х означает не эксперименты на GitHub, а игры с ценником, отзывами и игроками.
Что важно понимать про эти примеры: ни одна из них не пытается конкурировать с AAA по картинке. Это 2D-игры с продуманной механикой, плотным сценарием и аккуратным пиксель-артом — ровно тот жанр, где один разработчик или маленькая команда реально доходит до релиза. Если вы прошли базовый курс и умеете читать структуры и интерфейсы, вы уже знаете весь Go, который нужен для первых уроков. Остальное — рендер, ввод, звук — движок берёт на себя, и дальше по курсу мы разберём каждый слой.
Что такое Ebitengine: dead simple без кавычек#
README проекта описывает его одной строкой: «A dead simple 2D game engine for Go». Слово dead simple здесь — не маркетинг, а конструктивный принцип, который видно в API. У движка нет редактора сцен, нет системы компонентов, нет дерева объектов: игра — обычная Go-программа со структурой, реализующей три метода. Вы открываете файл main.go и видите весь каркас целиком, как в консольной утилите. Для кого-то это выглядит аскетично после Unity, но именно поэтому Ebitengine так хорошо ложится на Go: вместо обучения графическому редактору вы пишете код, который полностью понимаете.
Немного истории, чтобы понимать масштаб. Автор проекта — японский инженер Хадзиме Хоси; первый стабильный тег v1.0.0 появился в самом начале 2015 года, вторая мажорная версия — в октябре 2020-го, а весной 2022 года проект сменил имя с Ebiten на нынешнее Ebitengine. Движок пережил уже больше десятилетия развития, у него есть русско-переводимые туториалы сообщества, активный чат и подробный официальный чит-лист. Стабильность API при этом поражает: программа, написанная по туториалам десятилетней давности, после минимальных правок собирается современным компилятором. Мы в курсе используем актуальный синтаксис v2, и в следующем уроке вы запустите первый код локально.
Контракт ebiten.Game глазами языка Go
GO// Интерфейс объявлен в пакете движка github.com/hajimehoshi/ebiten/v2
type Game interface {
Update() error
Draw(screen *ebiten.Image)
Layout(outsideWidth, outsideHeight int) (int, int)
}
// Игра — обычная структура: слова implements в Go не нужно.
type MyGame struct {
steps int
}
func (g *MyGame) Update() error {
g.steps++
return nil
}Интерфейс Game объявлен в самом движке: три метода — и весь контракт. Структура MyGame удовлетворяет ему неявно, причём методы объявлены на указателе: в RunGame передают &MyGame{}. Update возвращает error, чтобы серьёзный сбой останавливал игру с сообщением. Любое состояние будущей игры живёт в полях структуры — здесь и начинается геймдей.
Минимальная игра: 20 строк, которые вы уже понимаете
GOpackage main
import (
"log"
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
)
type Game struct{}
func (g *Game) Update() error { return nil }
func (g *Game) Draw(screen *ebiten.Image) {
ebitenutil.DebugPrint(screen, "Hello, Ebitengine!")
}
func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
return 320, 240
}
func main() {
if err := ebiten.RunGame(&Game{}); err != nil {
log.Fatal(err)
}
}Это полный текст программы, а не фрагмент: структура Game реализует три метода, которые ждёт движок, а RunGame в main запускает игровой цикл. Update пока пуст — он возвращает nil, что для движка означает «игра продолжается». DebugPrint выводит отладочную строку встроенным шрифтом, который знает только латиницу — про кириллицу и свои шрифты будет отдельный урок. Пока читайте код как текст: запускать его будем локально во втором уроке.
Игровой цикл: Update, Draw и Layout за один вечер#
В сердце Ebitengine лежит одна из самых старых идей геймдева — игровой цикл. Пока окно открыто, движок по кругу делает две вещи: обновляет состояние игры (метод Update) и рисует картинку (метод Draw). Update вызывается по умолчанию 60 раз в секунду — тиками; Draw привязан к частоте монитора и обычно тоже даёт 60 кадров, но на игровом мониторе может рисоваться чаще. Третий метод, Layout, объясняет движку, какой логический размер холста рисует ваша игра: вернув из примера 320 на 240, мы попросили ретро-разрешение, которое движок растянет до размеров окна. В этом контракте нет ничего лишнего: Update меняет числа, Draw рисует числа, Layout решает, как картинка ложится на окно.
Такая схема называется fixed timestep: логика тикает с фиксированной частотой независимо от того, успевает ли рендер. Это спасает от классической болезни новичка, когда на мощном компьютере игра идёт в два раза быстрее, чем на слабом: дельта между тиками в Ebitengine константна по договорённости движка. Мы разберём цикл построчно во втором уроке, а движение и разницу TPS против FPS — в пятом; здесь важно лишь то, что весь движок стоит на трёх методах, которые вы уже видели.
Сколько раз в секунду Ebitengine по умолчанию вызывает Update?
Платформы: одна кодовая база от Windows до Switch#
Второй аргумент за игры на go — сборка. Из одной кодовой базы Ebitengine собирает игру под Windows, macOS, Linux и FreeBSD; под мобильные Android и iOS — с включённым cgo; в браузер — через WebAssembly, где игра живёт на обычной HTML-странице. Есть и экзотика, которой не может похвастаться почти никто: официальная поддержка Nintendo Switch, а также Xbox в ограниченном режиме, доступном не всем разработчикам. Практически это означает: начав с простого платформера для десктопа, вы доезжаете до телефона и браузера почти без изменений кода — логика, рисовка и ввод движка одинаковы, различается только слой платформы. Именно поэтому «сотни игр на itch.io» — не фигура речи: у движка есть своя страница Made with Ebitengine на itch.io, а витрина на официальном сайте дополняет её коммерческими релизами с ценником и отзывами.
Про браузерную сборку добавим честную деталь: WebAssembly-версия Ebitengine — один из самых приятных способов показать игру людям. Прислать другу ссылку вместо архива с бинарником — маленькая, но приятная разница, и в курсе сборке под платформы посвящён отдельный урок. Для десктопных сборок история с компилятором C за последние версии менялась: свежие релизы собираются в чистом Go без внешних зависимостей, а старые требовали gcc — как именно это выглядит на вашей системе, разберём при установке во втором уроке.
Куда собирается игра на Ebitengine#
| Платформа | Условия сборки | Кому пригодится |
|---|---|---|
| Windows, macOS, Linux, FreeBSD | обычный go build; свежим версиям C-компилятор не нужен | прототипы и релизы в Steam |
| Android и iOS | cgo включён; SDK платформы | казуальные игры и таймкиллеры |
| WebAssembly (браузер) | GOOS=js, GOARCH=wasm; страница-хост | демо, itch.io и быстрый шар с друзьями |
| Nintendo Switch | cgo, лицензирование Nintendo | инди-релизы на консоли |
| Xbox | cgo, ограниченный доступ по заявке | редкий, но существующий путь |
Какой платформы нет в официальном списке сборки Ebitengine?
Что покажет окно, если Draw пустой?
Прочитайте код и выберите, что он выведет:
func (g *Game) Update() error {
g.count++
return nil
}
func (g *Game) Draw(screen *ebiten.Image) {
// ничего не рисуем
}
func (g *Game) Layout(w, h int) (int, int) {
return 320, 240
}Чего в Ebitengine нет — и почему это плюс#
Перечислю то, чего вы не найдёте в движке: редактора сцен, встроенной физики, системы частиц из коробки, менеджера сцен, твинеров и визуальных инструментов. Есть только графика, ввод, звук и окно — а всё остальное вы собираете сами из обычного Go. У этого подхода есть сторона, о которой молчат рекламы: первые сто строк вашего платформера будут состоять из прямоугольников, скорости и проверок «стукнулся или нет». Зато каждая строка будет вашей: когда на десятой неделе игры перестанет работать столкновение со стеной, вы откроете свой код, а не чёрный ящик компонента коллайдера. Примеры в самом репозитории движка — Flappy, Blocks, 2048 — собираются из пары сотен строк и читаются как учебник: официальный сайт запускает их прямо в браузере, что удобно посмотреть ещё до установки.
У меня тут есть твёрдое мнение с оговоркой. Для обучения и для инди-игр аскетизм Ebitengine — прямой плюс: вы учитесь геймдеву, а не изучению редактора, и весь код принадлежит вам. Для большой команды, которая делает изометрическую RPG с горой контента, этот же аскетизм станет налогом: систему сцен, диалогов и анимаций придётся строить своими руками. Если ваша цель именно вторая — честнее взять полнофункциональный движок. Но тогда вы не пишете на Go, и курс, который вы читаете, вас не ждёт. Ниже — спойлер: за 25 уроков мы построим все недостающие детали руками, от коллизий до менеджера сцен.
Попытка делать в Ebitengine 3D, open world или физику мягких тел — путь к страданию: движок строго 2D, и всё, что выйдёт за плоскость, придётся эмулировать вручную. Если проект требует 3D, берите профильный инструмент. Этот курс — про 2D, и в 2D масштаб простоты движка раскрывается полностью.
Маршрут из 25 уроков крупными мазками#
- Уроки 01-05 (этот блок): движок, установка, окно, спрайты и движение
- Уроки 06-09: клавиатура, мышь и тач, прямоугольники, AABB-коллизии
- Уроки 10-13: атласы, анимация кадров, тайлмапы и камера
- Уроки 14-16: текст и шрифты, сцены, игровое состояние и счёт
- Уроки 17-19: частицы, звук через audio.Context, векторные примитивы
- Уроки 20-22: профилирование под 60 FPS, структура проекта, сборка
- Уроки 23-25: ассеты и лицензии, гейм-дизайн, итоговая мини-аркада
Графическому движку нужно окно операционной системы, поэтому примеры Ebitengine в песочнице сайта не запускаются — каждый пример рассчитан на локальный Go, который вы поставите во втором уроке. Зато игровая математика курса — тики, скорости, коллизии — считается на чистом Go: тематическая программа в песочнице сайта прокручивает игровой цикл прямо на странице.
Соберите каркас минимальной игры
Восстановите четыре пропуска в каркасе из этого урока: сигнатура Update, размер холста и запуск.
Каркас программы по строкам
Соберите минимальную Ebitengine-программу: от объявления пакета до обработки ошибки запуска.
Строки
Ваша программа
Нажимайте на строки слева, чтобы собрать программу
Итог знакомства такой: игры на go — зрелая ниша с коммерческими релизами, а Ebitengine — её главный инструмент, спроектированный вокруг трёх методов и фиксированных 60 тиков в секунду. Дальше по курсу мы двигаемся вглубь: второй урок ставит движок командой go get и запускает каркас, который вы уже видели, с разбором каждого метода (02-ustanovka-i-cikl). Третий посвящён окну и холсту — Layout, масштабированию, полноэкранному режиму и DPI (03-okno-i-holst). Четвёртый рисует первый спрайт из PNG с прозрачностью (04-sprajty), пятый заставляет его двигаться плавно и честно (05-geometriya-dvizheniya). Сосед по нише — GUI-тулкит Fyne — устроен похожим образом: тоже окно, тоже цикл событий, но вместо игры — интерфейсы; если сомневаетесь между графикой для игр и GUI-приложениями, взгляните на его первый урок для сравнения ощущений. Полная программа из 25 уроков живёт на странице курса Ebitengine — загляните, чтобы видеть, куда ведёт маршрут.
Термины урока
Песочница урока
Редактируйте код и запускайте его прямо здесь — интерпретатор работает в браузере, ничего устанавливать не нужно. За каждый запуск — +2 XP.
Запустите код, чтобы увидеть вывод.
Коротко: что запомнить
- Ebitengine — движок 2D-игр на чистом Go: первый стабильный тег v1.0.0 — январь 2015, v2.0.0 — октябрь 2020, в 2022 году Ebiten переименован в Ebitengine.
- На движке выпущены коммерческие игры — Meg's Monster, Mousebusters, Fishing Paradiso, Rakuen; официальный Showcase — витрина с правообладателями.
- Весь каркас игры — три метода: Update для логики, Draw для отрисовки, Layout для логического размера холста.
- Update тикает 60 раз в секунду по умолчанию, Draw привязан к монитору; разделение логики и рендера — главный принцип движка.
- Платформы: десктопы, Android и iOS через cgo, WebAssembly для браузера, Nintendo Switch и ограниченный Xbox.
- В движке нет редактора и встроенной физики — для обучения и инди это плюс: весь код игры принадлежит вам.
Домашнее задание
Откройте официальный Showcase на сайте Ebitengine и выберите две игры из витрины: посмотрите их страницы в Steam, трейлеры и скриншоты, выпишите, что у них общего по жанру и стилю. Для контраста прогоните взглядом любой пример из репозитория движка — Flappy или Blocks — и найдите в нём знакомые три метода: узнавание каркаса в чужом коде — лучший тест на понимание. Затем прочитайте раздел Cheat Sheet на сайте движка и найдите в нём сигнатуры Update, Draw и Layout — убедитесь, что после этого урока вы понимаете каждую строку каркаса. Запишите три идеи маленьких 2D-игр, которые вы хотели бы собрать по ходу курса: итоговый проект в уроке 25 — мини-аркада, и лучше начать думать о ней сейчас.
Личные заметкиПусто
Вопросы и ответы по уроку
Реально ли сделать игру на Go в одиночку?
Да, и витрина движка это подтверждает: многие игры в Showcase сделаны маленькими командами или одним разработчиком. Аскетичный API Ebitengine снимает налог на изучение редактора — весь объём работы сводится к коду и ассетам. Порог входа держится низким ещё и потому, что на старте не нужна линейная алгебра: три метода, прямоугольные координаты и умение читать документацию.
Ebitengine подходит только для пиксель-арта?
Нет: движок одинаково рисует и пиксель-арт, и гладкую векторную графику — фильтр масштабирования спрайтов настраивается. Но именно пиксель-арт-игры составляют большинство релизов, потому что такой стиль дешевле в производстве.
Почему не взять Unity или Godot?
Если цель — быстрая 2D-игра силами Go-разработчика, Ebitengine даёт меньше прослоек: обычная Go-программа вместо редактора и C#. Unity и Godot сильнее в 3D и огромном контенте, но цена — чужой рантайм и другой язык; для Go-программиста половина этого набора не имеет ценности.
Термины урока
Ключевые понятия из этого урока — короткие определения в глоссарии. Наведите на термин, чтобы вспомнить, откройте карточку для подробностей и ссылки на практику.
Изучайте дальше
Следующая ступень учебного пути
Chromedp в Go: автоматизация Chrome без Selenium
Курс chromedp для Go: навигация, селекторы, клики и формы, скриншоты и PDF, JS-оценка, вкладки, прокси, пул браузеров и скрапинг. 25 уроков.
- Запускать Chrome из Go и управлять страницами
- Находить элементы селекторами и ждать их появления
- Кликать, заполнять формы и извлекать данные
- Делать скриншоты, PDF и выполнять JavaScript