По сути, вы на правильном пути - вам нужно знать, как долго длится анимация, чтобы делать подобные вещи. Анимации - это больше, чем просто набор кадров, вокруг них есть всякая другая информация, которая вам нужна. Например, сколько кадров, цикл анимации, как быстро он воспроизводится (например, 10 кадров анимации в секунду, или 25, или 60?). Каждая анимация может быть определена в виде нескольких фрагментов данных, которые некоторый обобщенный код анимации может просматривать и воспроизводить. Вы должны инкапсулировать часть анимации в свой собственный фрагмент кода, который ничего не знает, кроме этих определений анимации и способов отображения отдельных кадров изображения. Это значит, что у вас есть анимационный объект, который вы можете загрузить, начать воспроизведение, остановить воспроизведение и указать рендеринг в определенном месте на экране.
Гибкий подход заключается в использовании своего рода определения анимации для инкапсуляции информации такого рода. Поэтому вместо того, чтобы просто сказать «анимация Х - это все эти кадры, просто играть через них», вы получите что-то более сложное.
Например, с каким-то смоделированным форматом данных
анимации =
{
{name = "walk", files = "walk * .png", frameCount = "12", loop = "true"},
{name = "fire" files = "fire * .png" frameCount = "6",
события = {
{name = "bulletLeavesGun", frame = "4", param1 = "43", param2 = "30"}
}
}
}
Итак, ваш код говорит что-то вроде:
currentAnimation = animations.Get("fire");
currentAnimation.Play();
То, как вы обнаруживаете события, может быть либо с помощью кода анимации, который вам перезванивает (т. Е. Когда он обнаруживает новое событие, потому что анимация воспроизводится в определенном кадре, он вызывает код вашей игры, чтобы сообщить ему о новом событии), или путем анимация вроде так:
List<Event> events = currentAnimation.EventsSinceLastCheck();
foreach (AnimationEvent event in events)
{
if (event.name == "bulletLeavesGun")
{
Vector2 bulletPosition = new Vector2(event.param1, event.param2);
Vector2 actualBulletPosition = new Vector2(
character.x + bulletPosition.x,
character.y + bulletPosition.y);
CreateBulletAt(actualBulletPosition);
}
}
Примечания к сведению:
- Код анимации должен существовать отдельно от кода игры. Вы действительно не хотите, чтобы ваш игровой код был слишком тесно связан с болтами при воспроизведении анимации.
- Код анимации знает, следует ли выполнять цикл на основе определения анимации
- Код анимации знает, когда анимация завершена, и может перезвонить другому коду, чтобы сказать: «Эй, анимация под названием« огонь »только что закончилась, что вы хотите сделать сейчас?»
- Код анимации ничего не знает о событиях, кроме того, что у них есть имя и некоторые произвольные данные, связанные с ними (param1 и param2)
- Код анимации знает, в каком кадре он находится в данный момент, и когда он меняется на новый, он может проверить и сказать: «О, я сейчас на 4 кадре, это означает, что это событие под названием« огонь »только что произошло, добавьте это к мой список недавних событий, чтобы я мог рассказать любому, кто спрашивает об этом ».
Если вам не нужно, чтобы выстрелы происходили внутри анимации, но только после того, как она закончилась, вы можете обойтись без гораздо более сложной системы без понятия событий. Но вам все еще нужна система, в которой анимации воспроизводятся сами по себе, знают, как долго они работают, и могут вызывать код игры после завершения анимации.