Перейти к содержимому
ГоМастер

Поиск по урокам

Найдите урок, курс, термин или раздел

Урок 23 из 25 ~16 мин +50 XP

Ассеты: где брать и лицензии

Игра почти собрана, но выглядит как техническая демка: игровые ассеты — спрайты, шрифты, звуки — пока не пришли из чужих рук, а вместе с ними не пришли и чужие условия использования. Разберём, где брать ассеты бесплатно и честно, как читать CC0, CC-BY и CC-BY-SA и чем они отличаются на практике, как упаковать папку assets в бинарник через go:embed и зачем проекту файл титров CREDITS.md со строкой на каждый ресурс.

Содержание урока · 10 разделов

Ни один движок не поставляется с героем: картинки, шрифты и звуки в игру приносит разработчик, и берёт их из двух источников — рисует сам или берёт готовое. Рисовать самому долго и не обязательно, а готовое несёт с собой чужие условия: у каждого файла есть автор и лицензия, и они не отменяются копированием в проект. Отсюда три вопроса урока: где искать паки, что именно разрешает лицензия и что вы обязаны сделать в ответ — указать автора, сохранить копию лицензии или просто взять и молчать. Игровые ассеты — единственная часть курса, где главная работа происходит не в редакторе кода, а в текстовом файле LICENSE, и это тоже инженерный навык: релизная игра — это код плюс честно оформленные заимствования. Правовая часть пугает сильнее указателей, но объём у неё скромный: пять обозначений — CC0, CC-BY, CC-BY-SA, OFL и NC — покрывают почти весь рынок бесплатных ассетов, а исполняются условия одним файлом титров и дисциплиной коммитов. Остальное — организация: папка assets, директива embed и загрузчик, возвращающий понятные ошибки.

Карты источников: где живут бесплатные ассеты#

Начните с мест, где лицензии организованы честно. Kenney.nl — библиотека из тысяч паков: двухмерные спрайты, тайлсеты, UI-наборы, звуки — всё под CC0, то есть в общественном достоянии: брать можно без спроса, менять как угодно и продавать игру без отчислений и даже без упоминания автора. OpenGameArt — агрегат, где у каждого ресурса своя карточка: CC0, CC-BY или CC-BY-SA, и читать надо страницу конкретного пака, а не правила сайта. Раздел game assets на itch.io полон бесплатных материалов, но «free» говорит только о цене: лицензия у каждого пака своя, от щедрой до запретительной.

Шрифты ищите на Google Fonts: большинство семейств живут под OFL, которая прямо разрешает встраивание в приложения и игры. Звуки — Freesound, где лицензия назначается клипу отдельно, и рядом с честным CC0 соседствует неудобный CC-BY-NC. Отдельная категория — процедурные генераторы sfxr, jsfxr и Bfxr: сгенерированный звук ничей — он ваш с первой секунды. Общее правило: источник — витрина, лицензия живёт у конкретного файла. Держите карту в закладках и пополняйте по мере проектов: проверенный источник экономит час поиска в следующей игре, а привычка смотреть лицензию до скачивания превращается в рефлекс, который дальше работает сам.

Спрайт из встроенной папки

GO
package main

import (
        "embed"

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

//go:embed assets/*
var assetsFS embed.FS

func loadPlayer() (*ebiten.Image, error) {
        img, _, err := ebitenutil.NewImageFromFileSystem(assetsFS, "assets/player.png")
        if err != nil {
                return nil, err
        }
        return img, nil
}

Директива go:embed над переменной embed.FS пакует папку assets внутрь бинарника при компиляции: файловая система перестаёт быть внешним миром и едет вместе с игрой. assetsFS реализует стандартный интерфейс fs.FS, а NewImageFromFileSystem открывает путь и декодирует PNG в ebiten.Image — тот же тип, что рисовал спрайты раньше, только источник теперь встроенный и одинаковый на всех платформах. Ошибка возвращается наверх без проглатывания: вызывающий код решает сам, падать целиком или рисовать заглушку.

В проект попал спрайт-пак под CC-BY. Что лицензия обязывает сделать?

Читать лицензию: CC0, CC-BY и CC-BY-SA#

Creative Commons выглядит как один значок, а требует разного. CC0 — автор отказался от прав целиком: условий нет, атрибуция не нужна, менять и продавать можно; единственная лицензия, которая не создаёт обязательств. CC-BY добавляет одно условие — атрибуцию: доступное место — обычно титры игры — должно назвать автора, источник и лицензию. Обязанность не истекает с релизом: она живёт столько, сколько живёт игра.

CC-BY-SA добавляет пункт ShareAlike: производные работы обязаны распространяться под той же лицензией. Для открытого проекта это естественно, для закрытой игры — риск: в спорных трактовках производной оказывается вся игра целиком. Отдельно запомните NC: «некоммерческое использование» разом отсекает платный магазин, рекламу и платные версии; формулировка «free for non-commercial» — та же ловушка другими словами. Рабочее правило: лицензия не прочиталась за минуту — файл не берётся, а поиск продолжается с фильтром CC0; во всех источниках выше такой фильтр есть. Ещё одна деталь, о которую спотыкаются: у пака и у отдельного файла из него условия бывают разными, как и у ремикса чужого ресурса — читается не «что написал сайт», а что написано рядом с конкретным файлом.

Загрузчик: один вход для всех картинок

GO
type Assets struct {
        Player  *ebiten.Image
        Enemy   *ebiten.Image
        Tileset *ebiten.Image
}

func LoadAssets() (Assets, error) {
        var a Assets
        var err error

        a.Player, _, err = ebitenutil.NewImageFromFileSystem(assetsFS, "assets/player.png")
        if err != nil {
                return a, fmt.Errorf("player: %w", err)
        }
        a.Enemy, _, err = ebitenutil.NewImageFromFileSystem(assetsFS, "assets/enemy.png")
        if err != nil {
                return a, fmt.Errorf("enemy: %w", err)
        }
        a.Tileset, _, err = ebitenutil.NewImageFromFileSystem(assetsFS, "assets/tileset.png")
        if err != nil {
                return a, fmt.Errorf("tileset: %w", err)
        }
        return a, nil
}

Один вход для всех картинок: структура Assets хранит готовые ebiten.Image, а LoadAssets возвращает ошибку с именем ресурса — при опечатке в пути вы сразу увидите, какой файл не встроился. Game получает весь набор один раз на старте, и ни одна сцена не ходит к файлам сама. Порядок загрузки фиксирован, и игра до завершения LoadAssets просто не начинается. Шрифты и звуки подключаются тем же способом: из того же embed.FS, через текстовый и аудио-механизмы курса.

Ресурс, лицензия и обязанность разработчика#

РесурсЛицензияЧто обязан сделать разработчик
Паки Kenney.nlCC0ничего: атрибуция не требуется, продажа разрешена
Пак с OpenGameArtCC-BYтитры: автор, источник, название лицензии
Тайлсет CC-BY-SACC-BY-SAтитры плюс производное под той же лицензией — риск для закрытой игры
Пак «free» с itch.ioу каждого свояпрочитать LICENSE до скачивания и действовать по нему
Шрифт с Google FontsOFLкопия лицензии рядом с файлом; сам шрифт не продавать
Клип Freesound с пометкой NCCC-BY-NCтитры и никакого платного использования — не для коммерции

Что вернёт путь без префикса assets?

Прочитайте код и выберите, что он выведет:

//go:embed assets/*
var assetsFS embed.FS

img, _, err := ebitenutil.NewImageFromFileSystem(
        assetsFS, "player.png",
)

Папка assets и go:embed: от файла к бинарнику#

Папка assets — единственный источник ассетов, который вы контролируете целиком: скачанные PNG, шрифты и звуки складываются туда, и дальше с ними работает только компилятор. Директива go:embed встраивает файлы в бинарник на этапе сборки, и это не стилистическое предпочтение: после урока про сборку на платформы вы знаете, что у WASM и мобильных версий нет доступа к вашей локальной файловой системе — относительный путь через обычный os.Open там не найдёт ничего. Встроенный FS ведёт себя одинаково на всех платформах.

Нюанса два. Первый: файлы, чьи имена начинаются с точки или подчёркивания, в бинарник не попадают — держите имена чистыми. Второй: пути внутри embed.FS сохраняют префикс assets, и запрос без него не найдёт файл — ошибка новичка номер один. Третий практический пункт — размер: встроенные файлы увеличивают бинарь на свой вес, поэтому тяжёлые видео и сотни мегабайт аудио туда не кладут; для игр курса паков хватает с запасом. Структуру папки ведите плоско или с понятными подпапками: это продолжение структуры проекта, а не свалка для скачанного.

Чем CC0 отличается от CC-BY с точки зрения разработчика игры?

Титры: CREDITS.md как часть проекта#

Атрибуция исполняется не намерением, а файлом. Заведите CREDITS.md в корне рядом с assets и добавляйте строку в тот же коммит, что и сам ассет: название ресурса, автор, источник, лицензия, дата. Строка выглядит так: «Ninja Sprite Pack — Kenney, kenney.nl, CC0, 2024». Для CC0 это вежливость и аудит — при обновлении пака вы вспомните, откуда файл; для CC-BY — прямое исполнение лицензии, записанное до того, как память подвела.

Титры дублируются в саму игру: пункт «Credits» в сцене меню — такой же элемент интерфейса, как пауза, потому что игрок должен иметь возможность увидеть имена. Данные читаются из того же списка: CREDITS.md служит и игроку, и разработчику одновременно. Перед релизом сверьте направления: каждый файл из assets/ упомянут, у каждой строки есть живой файл; расхождение в любую сторону — либо неоплаченный долг лицензии, либо мусор в репозитории. Имя файла не случайно: markdown читается в diff, на хостинге репозитория и в телефоне, а простой текст переживёт любой рефакторинг — таблица в редакторе документов таких гарантий не даёт.

Чек-лист принятия ассета в проект#

  • Лицензия прочитана у конкретного пака, а не на главной странице источника
  • Тип лицензии назван словами: CC0, CC-BY, CC-BY-SA, OFL или своё условие
  • Для CC-BY записаны автор, источник и версия лицензии
  • NC-варианты отсеяны, если игра когда-нибудь будет продаваться
  • Файл лёг в assets/ без точки или подчёркивания в начале имени
  • Строка в CREDITS.md добавлена тем же коммитом, что и файл
  • Пункт титров в игре обновлён вместе с ассетом
  • Непонятная лицензия означает поиск замены, а не обещание разобраться потом

Соберите объявление встроенных файлов

Восстановите два пропуска: имя пакета и тип встроенной файловой системы.

import ( "" ) //go:embed assets/* var assetsFS embed.

Путь ассета: от скачивания до экрана

Расставьте шаги от пакета до работающего спрайта.

Строки

Ваша программа

Нажимайте на строки слева, чтобы собрать программу

Шрифты и звуки: отдельные правила#

Шрифты живут по своим законам: Google Fonts раздаёт большинство семейств под OFL — встраивать в игру можно и нужно, копию лицензии держите рядом с файлом шрифта, а продавать сам шрифт нельзя. Механика отрисовки текста уже готова из урока про шрифты — меняется только источник, а текстовый рисующий код не замечает подмены.

Звуки дисциплинируют сильнее графики: на Freesound лицензия назначается клипу, поэтому фильтр CC0 ставьте до прослушивания — иначе через час поиска никто не вспомнит, какой клип был под каким условием. NC-варианты отметайте сразу, если игра когда-нибудь окажется платной. Альтернатива без правовых вопросов — генераторы sfxr и Bfxr: ползунки, кнопка экспорта, и результат полностью ваш; выстрелы, прыжки и подбор монет генерируются за минуты и встают в аудио-систему как обычные файлы, встроенные тем же go:embed. Отдельный совет про музыку: треки ищите по тем же правилам, что и эффекты, только цена ошибки выше — фоновый трек слышен весь сеанс и именно его чаще всего забывают в титрах.

К концу урока у проекта появляется материальная часть: папка assets с честными лицензиями, встроенная в бинарник директивой go:embed, загрузчик, возвращающий готовые спрайты, и CREDITS.md, где у каждого ресурса есть строка. Это закрывает последний инфраструктурный вопрос перед содержательным: впереди гейм-дизайн с балансом и итоговый проект, где всё соберётся в одну аркаду. Домашнее задание проводит первый ассет по полному пути — от страницы источника до экрана и титров. И держите рядом правило проверки: непонятная лицензия — это не обещание разобраться потом, а немедленный поиск замены под CC0; в релизной сборке репутация живёт в тех же файлах, что и игра. Дисциплина переносится и вне игр: любой проект с чужими зависимостями — от иконок до библиотек — живёт по тем же правилам чтения лицензий.

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

Термин

CC0

нажмите, чтобы перевернуть
Определение

Автор отказался от авторских прав полностью: условий нет, атрибуция не требуется, коммерческое использование разрешено.

1 / 6

Песочница урока

Редактируйте код и запускайте его прямо здесь — интерпретатор работает в браузере, ничего устанавливать не нужно. За каждый запуск — +2 XP.

Вывод

Запустите код, чтобы увидеть вывод.

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

  • Источник — витрина; лицензия живёт у конкретного пака: CC0, CC-BY, CC-BY-SA, OFL или своё условие.
  • CC0 не требует ничего; CC-BY требует атрибуции; SA и NC опасны для закрытых коммерческих игр.
  • Папка assets плюс go:embed пакует ассеты в бинарник и одинаково работает на всех платформах сборки.
  • Пути внутри embed.FS сохраняют префикс assets; файлы с точкой или подчёркиванием в имени не встраиваются.
  • Один загрузчик возвращает готовые ebiten.Image и честную ошибку с именем файла.
  • CREDITS.md в корне и пункт титров в меню — исполнение атрибуции и часть релиза.
  • Непонятная лицензия означает немедленный поиск замены под CC0, а не обещание разобраться потом.

Домашнее задание

Соберите первую партию ассетов по чек-листу урока. Скачайте два пака Kenney и один CC-BY-пак с OpenGameArt; создайте папку assets и CREDITS.md, внеся строку для каждого ресурса в момент скачивания. Подключите go:embed и замените прямоугольник героя на спрайт из урока про спрайты — загрузку оформите через LoadAssets с проверкой ошибок и понятными сообщениями. Добавьте в меню пункт «Credits» и выведите титры на экран в сцене из урока про сцены. Соберите бинарь и WASM-версию из урока про сборку: на встроенных ассетах обе должны запуститься одинаково. Найдите на Freesound один CC0-звук и один NC — второй не подключайте, а запишите в заметку, почему нельзя. В конце проверьте, что файлы с точкой или подчёркиванием в начале имени не попали в assets: embed их молча пропустит. Финальная проверка — запустить бинарь из другой папки: встроенные ассеты обязаны загрузиться без зависимости от текущей директории, потому что едут внутри бинарника.

Личные заметкиПусто
Хранятся только в вашем браузере (Ebitengine · Ассеты: где брать и лицензии)

Вопросы и ответы по уроку

Можно ли брать ассеты из Unity Asset Store или Figma Community в игру на Ebitengine?

Каждый магазин пишет свои условия, и они не привязаны к движку напрямую, но часто ограничивают рантайм или требуют упоминания магазина. Правило то же: читать лицензию конкретного пака до скачивания. Универсальные CC0-источники дешевле по вниманию: условия знакомые и короткие, а если сомнение осталось — пишите автору: молчаливое «наверное можно» в релизе хуже отказа.

Kenney просит указывать себя? Пак ведь CC0.

Не просит: CC0 снимает обязанность атрибуции. Строка в CREDITS.md остаётся хорошей практикой — при обновлении пака вы вспомните, откуда взяли файл, а не будете искать источник по названию спрайта через полгода. Та же строка — публичное уважение к чужому труду: авторы видят использование и продолжают делиться.

Ассет уже в игре, а лицензия нашлась позже — что делать?

Прочитать её спокойно. Если условия исполняются — дописать CREDITS.md и жить дальше. Если нет — NC в платной игре или SA в закрытом проекте — заменить ассет и вычистить файл из релиза; замена через загрузчик урока — правка одной строки пути, остальной код подмену не замечает.

Термины курса

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

Следующая ступень учебного пути

Chromedp25 уроков~11 чпрактика25 уроков уже доступны

Chromedp в Go: автоматизация Chrome без Selenium

Курс chromedp для Go: навигация, селекторы, клики и формы, скриншоты и PDF, JS-оценка, вкладки, прокси, пул браузеров и скрапинг. 25 уроков.

  • Запускать Chrome из Go и управлять страницами
  • Находить элементы селекторами и ждать их появления
  • Кликать, заполнять формы и извлекать данные
  • Делать скриншоты, PDF и выполнять JavaScript