Основи Cocos2d-x

Статті про розробку ігор за допомогою Cocos2d-x

Анімація

Posted at — Apr 14, 2020

Виділяють два способи створення анімації:

Ручний перелік файлів

Для прикладу візьмемо анімацію свічки з безкоштовного паку. Там всього лише три кадри, їх дуже просто завантажити і використати ось таким чином:

Vector<SpriteFrame*> animFrames;
animFrames.reserve(3);
animFrames.pushBack(SpriteFrame::create("candle/SC300-1.png", Rect(0,0,64,64)));
animFrames.pushBack(SpriteFrame::create("candle/SC300-2.png", Rect(0,0,64,64)));
animFrames.pushBack(SpriteFrame::create("candle/SC300-3.png", Rect(0,0,64,64)));

// create the animation out of the frames
Animation* animation = Animation::createWithSpriteFrames(animFrames, 0.4f);
Animate* animate = Animate::create(animation);

// run it and repeat it forever
Sprite* candleSprite = Sprite::create();
candleSprite->runAction(RepeatForever::create(animate));

Тут цифри у Rect(0,0,64,64) такі, тому що файли розміром 64х64 пікселі.

Проблема в тому, що практика прямого завантаження файлів, яку ми досі використовували у всіх прикладах, насправді є досить поганою. Вона підходить для навчання, але краще буде використовувати списки файлів (sprite sheet).

Файли зі списком файлів

У цьому місці я б дуже радив прочитати ось цю довгу, але дуже корисну статтю про анімацію. Якщо коротко, то є такий собі клас SpriteFrameCache, що може завантажувати зображення, описані у файлах *.plist. Такі файли можна створювати у різних програмах: непоганим варіантом є TexturePacker, також можна використовувати Shoebox, SpriteSheet Packer та Zwoptex. Результатом пакування є два файли:

Наприклад, можна взяти чотири зображення створіння у капюшоні, створити на його основі plist та ресурс і використати ось так:

SpriteFrameCache* sfc = SpriteFrameCache::getInstance();

const string violetMonsterFN = "littleCandleMonster/littleCandleMonster_violet.plist";
sfc->addSpriteFramesWithFile(violetMonsterFN);

Vector<SpriteFrame*> animFrames;
Animation *monsterAnimation = Animation::create();
char tmps[256];
for (int i = 1; i<=4; i++) {
  sprintf(tmps, "lm-1-%i.png", i);
  SpriteFrame * sf = sfc->getSpriteFrameByName(tmps);
  monsterAnimation->addSpriteFrame(sf);
}

monsterAnimation->setDelayPerUnit(0.1);

Animate* animate = Animate::create(monsterAnimation);

Можна позбавитись від переліку імен файлів у коді, якщо використати метод addAnimationsWithFile класу AnimationCache. Тоді завантаження анімацій виглядатиме так:

const string plistFilename = "skeleton/skeleton_images.plist";
SpriteFrameCache::getInstance()->addSpriteFramesWithFile(plistFilename);

const string animationsPlistFN = "skeleton/skeleton_animations.plist";
AnimationCache::getInstance()->addAnimationsWithFile(animationsPlistFN);

А використання так:

Animation* animation = AnimationCache::getInstance()->getAnimation(idleAnimationName);
Animate* animate = Animate::create(animation);
skeletonSprite->runAction(animate);

Недоліком такого способу є те, що він вимагає якогось особливого plist-файлу. Цей файл відрізняється від тих, що створює Texture Packer (не зважаючи на однакове розширення) і його доводиться виписувати вручну. Для даного прикладу цей файл виглядатиме так.

У будь-якому разі, отримана в результаті акція animate може використовуватись так само, як і будь-яка інша акція. Ось, наприклад, фіолетове створіння пересувається подібно до зеленого НЛО з попередньої статті