01 октября 2013

Flash, ответы на вопросы - 4

Продолжаем тему Flash разработки. Сегодня на очереди три маленькие хитрости, которыми я поделюсь. Если кто не знает, то мы решили стартовать серию сообщений вопрос-ответ по флеш... у нас полная демократия - кто угодно может спросить что-то интересующее его из мира флеш, а я постараюсь ответить :)
Сегодня в номере:
  • BlendMode - будьте аккуратны с этим зверем...
  • как я храню несколько анимаций в одном MovieClip'е
  • всякие полезные параметры stage'а
А теперь подробнее...
BlendMode - будьте аккуратны с этим зверем
Начну с того, что расскажу, что графические объекты могут по-разному накладываться и смешиваться на экране. Режимов много: Add, Alpha, Darken, Difference, Erase, Hardlight, Invert, Layer, Lighten, Multiply, Normal, Overlay, Screen, Shader, Subtract. И каждый служит для своих целей.
Особенно этими штуками часто пользуются художники, добиваясь потрясающих цветов и переходов.
Но я из этих всех способов наложения объектов при программировании использую лишь Normal и Layer. Выставляется это дело просто:

MyDisplayObject.blendMode = BlendMode.LAYER;

Название "нормальный" говорит само за себя, и я в основном этим режимом и пользуюсь, однако есть у него один недостаток. Накладываем несколько объектов, а затем изменяем прозрачность у их родителя... ба-бах, и вылезают артефакты, которые совсем не хотелось бы, чтобы они вылезали. Выглядит это так:


Видите? На средней картинке объекты стали прозрачными "по отдельности" и выглядит это надо сказать ужасно. Перехлест тайлов травы стал очень темным, а через голову девочки можно увидеть травинки, да и вообще цвет лица теперь с зеленцой! А вот режим Layer (справа) лишен вышеописанного недостатка, все выглядит как надо, зато у него есть другой недостаток :)
Итак, плавное появление диалогов и элементов уровня я делал через Layer, а затем обнаружил катастрофическое падение производительности при таком режиме. Я показывал целый уровень, со всякими объектами, анимациями, кнопками и прочим. И обнаружил слайдшоу, всего 5-7 фпс. На самом деле я довольно долго ломал голову, что же я такое натворил, а потом отключил Layer и обнаружил, что этот зверь оказался прожорливее, чем я мог себе представить. В итоге - оставил везде режим Normal, и просто увеличил скорость перехода от одного экрана к другому, чтобы игрок не успел заметить артефакты прозрачного наложения.


Как я храню несколько анимаций в одном мувике 
Совсем недавно в своих играх мы начали применять покадровую анимацию. Зверушка моргает глазами, прыгает, кушает и так далее - все это рисуется по кадрам, и при воспроизведении зверек оживает.
Так вот при создании анимации всяких игровых элементов возникает вопрос о том, как всем этим барахлом манипулировать. Сейчас я расскажу о способе, которым пользуюсь на данный момент, затрону плюсы и минусы.

Итак, анимация одного персонажа полностью лежит в одном мувике. Первые десять кадров - прыжок, следующие пятнадцать кадров бег, затем карабкается, еще двадцать кадров стреляет и так далее. Ставим текстовые метки на кадрах и вуаля - теперь мы можем легко найти первый кадр нужной анимации! В итоге остается один вопрос - как осуществлять навигацию по кадрам? Да все просто:

var fSuperMan = new mcSuperMan;
fSuperMan.gotoAndPlay('fly');

На последнем кадре каждой анимации ставлю stop(), что обеспечит остановку проигрывания анимации. Также номер кадра можно и вручную отслеживать по значению fSuperMan.currentFrame.
Итог:
  • можно хранить все анимации героя в одном клипе
  • насколько я понял, так намного проще анимировать художникам
  • все-таки текстовые метки довольно удобны, можно, к примеру, рандомно выбирать анимацию из текстового списка

всякие полезные параметры stage'а
Как-то раз один из спонсоров попросил, чтобы игра нормально скейлилась, сохраняя пропорции и вообще свой игровой вид. Оказалось, есть параметр scalable, который как раз отвечает за это все безобразие. Примеры:

stage.scaleMode = StageScaleMode.EXACT_FIT; // искажает пропорции, но масштабируется до окна
stage.scaleMode = StageScaleMode.NO_SCALE; // ничего не скейлится :)

Наверняка многие видели надоедливый желтый прямоугольник, который появляется при нажатии клавиши tab? Он раздражает не только игроков, но и многих спонсоров... Отключается легко:

stage.stageFocusRect = false;

При добавлении в игру всяких окошек, менюшек и тому подобных интерактивных кнопок, клавиатурные клавиши перестают работать, сталкивались? На самом деле просто фокус ввода уходит с элемента, для которого был привязан слушатель KeyboardEvent'а. Чтобы вернуть все как было, достаточно выполнить:

stage.focus = MyInteractiveObject;

сразу после пропадания вышеназванных менюшек, ставших причиной бага.

При переносе проектов с FlashDevelop на FlashBuilder и обратно, у меня иногда возникают проблемы во всяких там настройках, таких как разрешение флешки и фреймрейте. Чтобы постоянно не лазить в настройки проекта, для установки фреймрейта я пользуюсь такой строчкой, дописав ее, допустим, в самое начало прелоадера:

stage.frameRate = 35;

В общем-то и все, что мне приходит на ум сейчас, наверно :)

На этом сегодняшний выпуск завершен, ждите продолжения в ближайшее время! Не скучайте, товарищи и приятного вам дня!

Сообщения, схожие по тематике:

10 коммент.:

  1. Использую для установки фреймрейта тег SWF=) Получается что-то вроде такого(так же можно задавать ширину, высоту и цвет фона):

    package
    {

    import flash.display.Sprite;

    [SWF(width="800", height="600", backgroundColor="#FFFFFF", frameRate="60", wmode="direct")]
    public class Preloader extends Sprite
    {
    public function Preloader()
    {
    //bla bla bla
    }
    }
    }

    ОтветитьУдалить
    Ответы
    1. о! клево! буду знать! я такую штуку только для размеров использовал...
      еще такая штука, что у спонсоров постоянно разные фпс на мувиках сплешей, и приходится программно выставлять фреймрейт до/после проигрывания их мувика.

      Удалить
  2. Привет.

    Не мог бы ты в след. выпуске показать свой звуковой менеджер?
    Как звук и музыка останавливаются при паузе?

    ОтветитьУдалить
  3. Насчёт кадровых меток:
    Я тоже поначалу разделял так анимацию, но это было лишь пока я юзал графику в векторе.
    Когда я начал её кэшировать (растеризовать), то метки отпали(даже пришлось тратить время на переделку уже готовой графики заточенной под метки, ну и код тоже соответственно), поэтому пришёл к единственному удобному решению - хранение анимаций в разных MC.
    Ну а для художников с этим никаких проблем - сначала они рисуют всё как удобно(например в 1 MC), а потом разносят кадры как надо(по разным MC).

    ОтветитьУдалить
    Ответы
    1. многие при растеризации сохраняют метки... чтобы унифицировать переходы.
      а я до сих пор не умею растеризовать анимацию... в новой игре хочу попробовать!

      Удалить
  4. Спасибо за блог и еще один источник вдохновенния и полезных советов.
    Помоги пожалуйста в следующем выпуске начинающему флешеру с вопросом создания задержки между выстрелами и правильным созданием/удалением массивов пуль или с класами в разрезе этого вопроса. Делаю простую аркадку, там лягушка стреляет огненними шарами, пиробластами и заморозкой. Игрок должен переключать "режимы патронов" выбирая нужный ему в даной ситуации. Возникла проблема с реализацией этой стрельбы. П.С. Спасибо за блог и держу кулаки за твои следующие игры.

    ОтветитьУдалить
    Ответы
    1. спасибо!
      по поводу пуль - не знаю, когда выйдет следующий выпуск FAQ, поэтому дополнительно распишу сейчас, я бы делал так:
      1. базовый класс TBaseGun, от него наследуем TFireBallGun, TBlastGun, TFrozenGun и всякое такое... главное - у них должен перекрываться метод Shoot(), при этом создаваться объекты типов TFireBallBullet, TBlastBullet, TFrozenBullet соответственно...
      2. собственно, дополнительно реализуем сами классы пуль (Bullet-ы из предыдущего пункта). Каждый из них при столкновении делает что-то свое. Кто-то наносит урон, кто-то замораживает, кто-то поджигает и так далее.
      3. если пуль очень много на экране (более 20 одновременно), то можно реализовать пул объектов (слова для поиска: аккумулятор объектов, пул объектов, заранее созданный вектор). это для того, чтобы не было тормозов.

      тема интересная - спасибо за наводку! постараюсь осветить ее в следующем выпуске!
      p.s. простите за префикс "T" в названиях классов, у меня жгучая привычка так делать :)

      Удалить
  5. Работаю в флеш кс 5 (со временем планирую освоить флеш девелоп). Столкнулся с проблемкой, --> если даже простому шейпу-мувиклипу программно или класическим твином задать движение на сцене, то наблюдаются маленькие но вначале заметные глазу рывочки в движении. Как можно это устранить? На 35 фпс это меньше заметно, но все равно..

    ОтветитьУдалить
    Ответы
    1. привет!
      сделай пробный fla и пришли мне на почту lampogolovii@mail.ru, я гляну... причин может быть много (от первого рендера, до установленного cacheAsBitmap)

      Удалить