---
title: "Знакомство: игры на Go существуют"
description: "Ebitengine знакомство: движок 2D-игр на чистом Go — игры на Go существуют и продаются в Steam. Dead simple-философия, игровой цикл Update и Draw, план курса из 25 уроков. 2D-графика на Go без обёрток над SDL."
course: "Ebitengine: 2D-игры на Go"
url: "https://golangmaster.ru/courses/ebitengine/lessons/01-znakomstvo-ebitengine/"
published: "2026-09-19"
updated: "2026-09-21"
minutes: 16
---

# Знакомство: игры на Go существуют

*Курс «Ebitengine: 2D-игры на Go», урок 1 из 25. ~16 минут. Обновлено 21.09.2026. Источник: https://golangmaster.ru/courses/ebitengine/lessons/01-znakomstvo-ebitengine/*

Ebitengine знакомит нас с идеей, которую десять лет назад никто бы не принял всерьёз: игры на go — это нормальный, рабочий жанр, а не курьёз для хакатона. На этом движке написаны игры, которые продаются в Steam, — и в этом уроке мы посмотрим на них, разберём философию проекта и соберём мысленный портрет вашей первой игры.

Начнём с разговора, который был у каждого из нас. Вы пишете на 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-игры с продуманной механикой, плотным сценарием и аккуратным пиксель-артом — ровно тот жанр, где один разработчик или маленькая команда реально доходит до релиза. Если вы прошли [базовый курс](/courses/go-basics/) и умеете читать структуры и интерфейсы, вы уже знаете весь 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 строк, которые вы уже понимаете

```go
package 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?

- Столько же, сколько кадров рисует монитор
- ✅ 60 раз — это тики, частота фиксирована
- 30 раз, чтобы экономить процессор
- Столько раз, сколько успеет за кадр

Update вызывается по умолчанию 60 раз в секунду, и это фиксированная частота (TPS), не зависящая от монитора. Draw привязан к частоте кадров монитора и может быть другим. Мы разложим TPS против FPS по полочкам в пятом уроке.

### Платформы: одна кодовая база от 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?

- Nintendo Switch
- WebAssembly в браузере
- ✅ PlayStation
- FreeBSD

PlayStation в списке платформ README нет — есть Windows, macOS, Linux, FreeBSD, Android, iOS, WebAssembly, Switch и ограниченный Xbox. Даже если консольная разработка вам не светит, сам список показывает, насколько далеко от «скриптового языка для утилит» уехал Go.

### Что покажет окно, если Draw пустой?

```go
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
}
```

**Что выведет программа?**

- Программа не скомпилируется: пустой Draw недопустим
- ✅ Откроется чёрное окно, но игра работает — тики идут
- Движок сам напечатает значение счётчика в консоль
- Окно закроется сразу, потому что рисовать нечего

Update и Draw независимы: логика работает и без отрисовки, а пустой Draw означает «рисовать нечего», и экран остаётся чёрным. Игра при этом живёт: счётчик растёт 60 раз в секунду. Это хорошее упражнение на понимание разделения логики и рендера, к которому мы возвращаемся в каждом уроке курса.

### Чего в 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, размер холста и запуск.

```go
package main

import (
        "log"

        "github.com/hajimehoshi/ebiten/v2"
)

type Game struct{}

func (g *Game) Update() ___ { return nil }

func (g *Game) Draw(screen *ebiten.Image) {}

func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
        return ___, ___
}

func main() {
        if err := ebiten.___(&Game{}); err != nil {
                log.Fatal(err)
        }
}
```

Подсказка: Update возвращает ошибку, Layout из примера вернул 320 и 240, а стартует игра функцией RunGame.

Правильные ответы в пропусках: `error`, `320`, `240`, `RunGame`

### Каркас программы по строкам

Соберите минимальную Ebitengine-программу: от объявления пакета до обработки ошибки запуска.

Правильный порядок строк:

1. `package main`
2. `import "github.com/hajimehoshi/ebiten/v2"`
3. `type Game struct{}`
4. `func (g *Game) Update() error { return nil }`
5. `func (g *Game) Draw(screen *ebiten.Image) {}`
6. `func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) { return 320, 240 }`
7. `func main() {`
8. `if err := ebiten.RunGame(&Game{}); err != nil { log.Fatal(err) }`
9. `}`

Итог знакомства такой: игры на go — зрелая ниша с коммерческими релизами, а Ebitengine — её главный инструмент, спроектированный вокруг трёх методов и фиксированных 60 тиков в секунду. Дальше по курсу мы двигаемся вглубь: второй урок ставит движок командой go get и запускает каркас, который вы уже видели, с разбором каждого метода (02-ustanovka-i-cikl). Третий посвящён окну и холсту — Layout, масштабированию, полноэкранному режиму и DPI (03-okno-i-holst). Четвёртый рисует первый спрайт из PNG с прозрачностью (04-sprajty), пятый заставляет его двигаться плавно и честно (05-geometriya-dvizheniya). Сосед по нише — GUI-тулкит [Fyne](/courses/fyne/) — устроен похожим образом: тоже окно, тоже цикл событий, но вместо игры — интерфейсы; если сомневаетесь между графикой для игр и GUI-приложениями, взгляните на его первый урок для сравнения ощущений. Полная программа из 25 уроков живёт на странице [курса Ebitengine](/courses/ebitengine/) — загляните, чтобы видеть, куда ведёт маршрут.

### Термины урока

- **Ebitengine** — 2D-игровой движок для Go авторства Хадзиме Хоси. До 2022 года назывался Ebiten; первый стабильный тег v1.0.0 — начало 2015 года, v2.0.0 — октябрь 2020.
- **Игровой цикл** — Повторяющийся каркас игры: Update обновляет состояние, Draw рисует кадр. В Ebitengine это два из трёх методов интерфейса ebiten.Game.
- **Тик** — Один вызов Update. По умолчанию движок делает 60 тиков в секунду, и эта частота фиксирована независимо от монитора.
- **Layout** — Третий метод ebiten.Game: получает размер окна и возвращает логический размер холста игры, который движок масштабирует до окна.
- **Showcase** — Официальная витрина игр на движке: коммерческие проекты вроде Meg's Monster, Mousebusters и Rakuen, многие продаются в Steam.
- **Fixed timestep** — Схема, при которой логика шагает с постоянной дельтой времени. Спасает игру от «ускорения» на мощных компьютерах.

## Коротко: что запомнить

- 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-программиста половина этого набора не имеет ценности.
