Предисловие
Эта статья является второй, из серии переводов документации к игровому движку Cocos2d-x. Если вы не видели первую часть перевода, то советую сначала ознакомится с ней:
Cocos2d-x — Основные понятия
А теперь продолжим!
Что такое спрайт
Спрайт — это 2D изображение, которое может быть анимировано или трансформировано, путем изменения свойств, таких как: rotation, scale, color, и так далее.
Создание спрайтов
Существуют различные способы создания спрайтов, зависящие от того что вам необходимо выполнить. Вы можете создать спрайт, используя изображения различных графических форматов, включая: PNG, JPEG, TIFF и другие. Давайте рассмотрим некоторые методы создания и поговорим о каждом из них.
Создание простого спрайта
Спрайт может быть создан путем указания файла изображения.
auto mySprite = Sprite::create("mysprite.png");
Код выше создает спрайт, используя изображение mysprite.png. В результате, созданный спрайт использует целое изображение. Он имеет те же размеры, что и mysprite.png. Если файл изображения 200 x 200 то результирующий спрайт тоже будет 200 x 200.
Создание спрайта с использованием Rect (прямоугольника)
В предыдущем примере, созданный спрайт имел тот же размер, что оригинальное изображение. Если вы хотите создать спрайт использующий только часть файла изображения, вы можете сделать это путем указания прямоугольного участка – Rect.
Rect имеет 4 значения: origin x, origin y, width и height.
auto mySprite = Sprite::create("mysprite.png", Rect(0,0,40,40));
Rect берет левый верхний угол за начало координат. Это противоположно тому принципу, что мы использовали, когда устанавливали позицию на экране, отчитывая координаты от левого нижнего угла. Таким образом, результирующий спрайт – только часть исходного файла изображения. В этом случае, размер спрайта 40 x 40 начиная от левого верхнего угла.
Если вы не зададите Rect, Cocos2d-x автоматически будет использовать полную высоту и ширину заданного изображения. Взгляните на код ниже. Если вы используете изображение с размерами 200 x 200, то следующие два выражения будут иметь одинаковые результаты.
auto mySprite = Sprite::create("mysprite.png");
auto mySprite = Sprite::create("mysprite.png", Rect(0,0,200,200));
Создание спрайта из текстурного атласа (Sprite Sheet)
Sprite sheet – это способ объединения спрайтов в один файл. Использование sprite sheet помогает добиться лучшей производительности, путем пакетной обработки вызовов рисования. Они могут также сохранить дисковую- и видео-память, если упаковать спрайты более эффективно (обычно требуются специальные инструменты). Вы прочитаете больше об этом в продвинутой главе, но это только один из многих стандартных методов повышения производительности игр.
При использовании sprite sheet, он сначала загружается в SpriteFrameCache. SpriteFrameCache – это класс кеширования, который сохраняет объекты SpriteFrame, для быстрого доступа к ним. SpriteFrame загружается один раз и сохраняется в SpriteFrameCache.
Вот пример sprite sheet:
Давайте рассмотрим подробнее, что происходит:
Как вы можете видеть, sprite sheet объединяет все спрайты в один файл и минимизирует лишнее пространство.
Загрузка Sprite Sheet
Вероятнее всего, вы будете осуществлять загрузку в AppDelegate:
// загрузка Sprite Sheet
auto spritecache = SpriteFrameCache::getInstance();
// файлы .plist могут быть сгенерированы при помощи любого из перечисленных в последнем пункте инструментов
spritecache->addSpriteFramesWithFile("sprites.plist");
Теперь, когда мы имеем текстурный атлас загруженный в SpriteFrameCache, мы можем создать спрайт.
Создание спрайта из SpriteFrameCache
Это создание спрайта, путем вытягивания его из SpriteFrameCache.
// Наш .plist содержит имена всех спрайтов, находящихся в нем.
// "mysprite" – имя спрайта из sprite sheet:
auto mysprite = Sprite::createWithSpriteFrameName("mysprite.png");
Создание спрайта из SpriteFrame
Еще один способ создать такой же спрайт – получить SpriteFrame из SpriteFrameCache, и затем создать спрайт при помощи SpriteFrame. Пример:
// это равнозначно с предыдущим примером,
// но он создается, путем извлечения SpriteFrame из кэша.
auto newspriteFrame = SpriteFrameCache::getInstance()->getSpriteFrameByName("Blue_Front1.png");
auto newSprite = Sprite::createWithSpriteFrame(newspriteFrame);
Инструменты для создания Sprite Sheets
Создание sprite sheet вручную – утомительный процесс. К счастью, есть инструменты, которые могут генерировать их автоматически. Эти инструменты предлагают множество возможностей для максимальной оптимизации ваших спрайтов!
Здесь представлено несколько инструментов:
Манипуляции со спрайтами
После создания спрайта, вы получите доступ к разнообразным его свойствам, которыми можно манипулировать.
Дано:
auto mySprite = Sprite::create("mysprite.png");
Опорная точка и позиция
Опорная точка (Anchor Point) – это точка, которую вы задаете, чтобы указать, какая часть спрайта будет использоваться, при установке его координат. Опорная точка влияет только на свойства связанные с трансформацией. Они включают: scale, rotation, skew. И не включают: color и opacity. Опорная точка использует систему координат от нижнего левого угла. Учитывайте это, при выполнении своих расчетов. По умолчанию, все Node объекты имеют стандартную опорную точку (0.5, 0.5).
Задать опорную точку просто:
// DEFAULT
mySprite->setAnchorPoint(0.5, 0.5);
// нижний левый угол
mySprite->setAnchorPoint(0, 0);
// верхний левый угол
mySprite->setAnchorPoint(0, 1);
// нижний правый угол
mySprite->setAnchorPoint(1, 0);
// верхний правый угол
mySprite->setAnchorPoint(1, 1);
Чтобы представить это визуально:
Свойства спрайтов, на которые влияет опорная точка
Использование опорной точки влияет только на свойства связанные с трансформированием. Такие как: scale, rotation, skew.
Position
Опорная точка влияет на позицию спрайта, поскольку именно эта точка используется в качестве основной при позиционировании. Давайте посмотрим, как это происходит. Обратите внимание на цветную линию, и то где находятся спрайты относительно ее. Важно отметить, что такой эффект был получен, лишь путем изменения опорной точки. Мы не использовали setPosition() для достижения этого:
Позицию спрайта можно также задать методом setPosition().
// установка новой позиции спрайта x = 100, y = 200.
mySprite->setPosition(Vec2(100, 200));
Rotation
Изменяет вращение спрайта, на положительное или отрицательное число градусов. Положительные значения поворачивают спрайт по часовой стрелке, в то время как отрицательные поворачивают против часовой стрелки. Стандартное значение – 0.0
// поворот спрайта на +20 градусов
mySprite->setRotation(20.0f);
// поворот спрайта на -20 градусов
mySprite->setRotation(-20.0f);
// поворот спрайта на +60 градусов
mySprite->setRotation(60.0f);
// поворот спрайта на -60 градусов
mySprite->setRotation(-60.0f);
Scale
Изменяет масштаб спрайта, либо по каждой оси отдельно, либо равномерно по обеим. Стандартное значение – 1.0
// увеличивает спрайт в 2 раза
mySprite->setScale(2.0);
// масштабирует спрайт по координате x
mySprite->setScaleX(2.0);
// масштабирует спрайт по координате y
mySprite->setScaleY(2.0);
Skew
Изменяет наклон спрайта, либо отдельно по осям x и y, либо равномерно для всех. Стандартное значение – 0.0
// устанавливает наклон X на 20.0
mySprite->setSkewX(20.0f);
// устанавливает наклон Y на 20.0
mySprite->setSkewY(20.0f);
Свойства спрайта, на которые не влияет опорная точка
Существует несколько свойств объекта Sprite, на которые не влияет опорная точка. Почему? Потому что они изменяют только внешний вид, подобно свойствам color и opacity.
Color
Изменяет цвет спрайта. Это делается при помощи Color3B. Мы еще не сталкивались с Color3B, но это просто объект, представляющий собой RGB цвет. RGB цвет включает в себя 3 значения (Red, Green, Blue), от 0 до 255. Cocos2d-x также предоставляет предопределенные цвета, из которых вы можете выбрать. Использование их будет немного быстрее, поскольку они уже определены заранее. Вот некоторые примеры:
// установка цвета при помощи предопределенного объекта Color3B.
mySprite->setColor(Color3B::WHITE);
// установка цвета с помощью Color3B.
mySprite->setColor(Color3B(255, 255, 255));
// Тоже что Color3B::WHITE
Opacity
Изменяет непрозрачность спрайта на заданное значение. Это свойство принимает значения от 0 до 255, где 255 – полная не прозрачность, а 0 – абсолютная невидимость. Стандартное значение 255 (полная видимость).
// Установим opacity на 30, что сделает этот спрайт непрозрачным на 11.7%.
// (30 / 256 = 0.1171875...)
mySprite->setOpacity(30);
Полигональные спрайты
Полигональный спрайт это тоже спрайт, который используется для вывода 2d изображения. Однако, в отличие от нормального спрайта, который является прямоугольником, состоящим из двух треугольников, полигональный спрайт состоит из серии треугольников.
Зачем использовать полигональный спрайт?
Ответ прост — производительность!
Существует много технических терминов о скорости пиксельного заполнения, которые мы могли сюда вывалить, но вам просто нужно понять, что PolygonSprite рисуется на основе формы вашего спрайта, а не прямоугольника с избыточной площадью. Этот способ прорисовки, позволяет сэкономить на ненужной работе. Рассмотрим пример:
Заметили различия между левой и правой версиями?
Слева, типичный Sprite, который прорисовывается, с использованием двух треугольников.
Справа, PolygonSprite, рисующийся большим количеством маленьких треугольников.
Стоит ли идти на такой компромисс, чисто по соображениям производительности, зависит от ряда факторов (форма/детализация спрайта, размер, количество нарисованного на экране, и так далее), но в основном, вершины дешевле пикселей на современных графических процессорах.
AutoPolygon
AutoPolygon – это вспомогательный класс. Его цель – создавать 2d полигональную сетку на основе изображения.
Существуют функции для каждого шага обработки этого процесса, от определения всех точек, до триангуляции. Результат может быть передан в функцию create объекта sprite, для создания PolygonSprite. Пример:
// Автоматическая генерация polygon info.
auto pinfo = AutoPolygon::generatePolygon("filename.png");
// Создание спрайта при помощи polygon info.
auto sprite = Sprite::create(pinfo);
domix32
Для опроных точек также существуют предопределенные точки для каждой из девяти основных вариантов расположения