2009-09-17 5 views
0

Я создаю флеш-игру, основанную на старом Pacman, и я не уверен, что это лучший способ управлять анимацией.Лучшие практики: ENTER_FRAME против таймера

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

Это, однако, представляет проблему необходимости иметь определенную частоту кадров и менять ее позже, не говоря уже о том, что она ограничена очень немногими «скоростями» (см. Ниже). Примером может быть то, что спрайт должен перемещать 12 пикселей до того, как будет определено следующее движение. Если скорость затем 4 пикселей на кадр, математика довольно проста:

[...] 
public var stepCount:uint = 0; 

[...] 

function enterFrameHandler(e:Event):void 
{ 
    if(stepCount==0) { 
    //Some code to evaluate next move. Let's say it evaluates to MOVE RIGHT 
    } 

    if(MOVE_RIGHT) 
    { 
     x += 4; 
    } 

    stepCount++; 
    if(stepCount > 2) 
    { 
     stepCount = 0; //Now ready to evaluate direction again. 
    } 
} 

Это все работает отлично, но давайте скажем, что я хочу, спрайт, чтобы переместить 5 пикселей на кадр. Тогда количество кадров перед следующей оценкой не будет вычисляться. StepSize должен быть кратным 12, что ограничивает различные возможные скорости (1,2,3,4 и 6 пикселей на кадр).

Вот почему я попытался основать движение на таймере вместо этого, и мне также удалось работать, но движение было несколько неустойчивым, и казалось, что Таймер использует гораздо больше памяти, чем событие ENTER_FRAME. Вместо равномерного движения Таймер заставил спрайт замедляться и ускоряться и замедляться снова.

Другим возможным решением может быть класс Tween, но он кажется экстравагантным.

У кого-нибудь есть опыт работы с лучшими в других играх?

Morten Twellmann

ответ

1

Да частота кадров будет варьироваться в зависимости от процессора среди других вещей. Поэтому вам нужно учитывать это в своем игровом цикле. Мне нравится делать разницу во времени между текущим фреймом и старым фреймом и использовать это значение в моих расчетах. Поэтому, если произойдет, что есть задержка, большее значение разности будет компенсировать тот факт, что число кадров меньше.

var _previousTime:Number; 

    //gameLoop is the function called on ENTER_FRAME 
    public function gameLoop(e:Event):void 
    { 

     var currentTime:Number = getTimer(); 
     var difference:Number = currentTime - _previousTime; 
     _previousTime = currentTime; 

     //use difference variable with calculations involving movement 

    } 
+0

Конечно, это имеет смысл! Большое спасибо. – 2009-09-18 06:32:44

+0

Это основная вещь, которую нужно сделать, но не сделает движение в конечном счете гладким, как я испытал в своей теме: http://stackoverflow.com/questions/1284886/optimizing-transition-movement-smoothness-for-a-2d-flash- игра - казалось, что лучше было перемещать фон в обратном направлении игрока. Однако я не знаю, почему. – Tom

+0

Единственная проблема, с которой я столкнулся, - это сложная физика, в которой большие временные шаги заставляли некоторые из моих симуляций выходить из себя. PS рада видеть, что ты решил свою проблему. Том :) – Allan

6

У вас есть несколько отдельных вопросов. Ваш первый вопрос заключается в том, следует ли выполнить цикл игры в событии фрейма или событии таймера? Ответ прост - вы должны сделать это в кадровом событии. Причина в том, что независимо от того, как вы перемещаете персонажей, экран обновляется ровно один раз за кадр. Поэтому в любое время, когда вы звоните в свою петлю игры более одного раза за кадр, вы тратите впустую процессор, и каждый раз, когда вы называете это менее одного раза за кадр, вы жертвуете визуальным качеством. Так что это легко, не беспокойтесь о событиях таймера.

Следующий вопрос: должно ли ваше движение игры привязываться к кадрам или милисекундам, и ответ заключается в том, что это зависит от игры. Спросите себя: предположите, что какой-то пользователь играет в вашу игру, и их космический корабль (или что-то еще) летает с определенной скоростью. Внезапно антивирусный пакет пользователя делает что-то тяжелое, а всплеск процессора заставляет Flash перестать обновляться в течение одной секунды. Как только шип закончится, вы хотите, чтобы космический корабль продолжал двигаться с того места, где он был, когда начался шип? Или вы хотите, чтобы он прыгнул вперед туда, где он был бы, если бы он продолжал двигаться во время всплеска? Если вы хотите первого, вы должны привязать свое движение к кадрам; если вы хотите последнего, вы должны привязать его к miliseconds. Но какой из них лучше всего зависит от того, как вы хотите, чтобы ваша игра работала.

Последний вопрос: как именно вы должны перемещать персонажей в своей игре? Основываясь на том, что вы написали, я сделал бы это следующим образом. Для каркасного движения (т.первый подход, описанный ранее):

// the ship moves 25 pixels per second 
var shipSpeed:Number = 25; 

// the number of seconds per frame, based on the published framerate 
var frameTime:Number = 1/stage.frameRate; 

// game loop called each frame: 
function gameLoop() { 
    // ... 
    playerShip.x += shipSpeed * frameTime; 
    // .... 
} 

Таким образом, движение судна на экране постоянно, независимо от того, что вы FrameRate опубликовать SWF в. Использование более высокой частоты кадров просто делает движение более плавным. Аналогично, чтобы связать ваше движение со временем вместо кадров, просто измените «frameTime» в приведенном выше коде, чтобы ссылаться на время, прошедшее с предыдущего кадра, как описано в ответе Аллана.

+0

Спасибо. Я полностью понимаю суть потери процессора и кадра при использовании события Timer. Я также понял, что могу просто увеличить общую частоту кадров, если хочу увеличить до разных возможных значений скорости. – 2009-09-18 06:35:28

+1

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

Смежные вопросы