Проблема с задержкой таймера в скрипте действия 3 - PullRequest
0 голосов
/ 07 июля 2011

Я работаю над автомобильной флеш-игрой, используя сценарий действия 3, и я хочу, чтобы дорожные линии проходили быстрее, если я нажимаю «вверх» на клавиатуре, линии создаются таймером, задержка которого изменяется нажатой клавишей Проблема в том, что если я позволю нажатой клавише, таймер события все еще обновится, и он не покажет никаких дорожных линий, пока я не перестану его нажимать.

Вот код нажатия клавиши:

if (upPressed)
{
    speed = speed*1.02;
    timerB.delay = timerB.delay/1.007;
    timerA.delay = timerA.delay/1.005;
}

Есть советы? Заранее спасибо.

Ответы [ 3 ]

0 голосов
/ 08 июля 2011

Хотя ответ Джоша точно описывает источник вашей ошибки, следует отметить, что правильный способ решения вашей проблемы - полностью прекратить использование таймеров и запустить всю свою логику в обработчике EnterFrame..

Чтобы понять, почему это так, вспомните, что флэш-плеер работает с заданной частотой кадров и перерисовывает экран только один раз за кадр.Предположим, вы запускаете таймер с той же скоростью, что и частота кадров.Это означает, что вы получите одно событие таймера между перерисовками экрана.Теперь предположим, что вы ускорили таймер на 10%.Все, что происходит, это то, что события таймера и события кадра не синхронизируются, так что вы получите один таймер на кадр на девять кадров, а в течение десятого кадра таймер сработает дважды.Ваша дорожная трасса движется не на 10% быстрее, она движется с одинаковой скоростью в течение девяти кадров и в два раза быстрее для десятой, что совсем не то, что вы хотите.

Решение состоит в том, что вместо того, чтобы пытаться перемещать дорожные линии чаще, вы хотите перемещать их один раз за кадр, но перемещать их на большее или меньшее расстояние.И правильный способ сделать это - обработчик EnterFrame.

0 голосов
/ 16 июля 2011

EnterFrame - это событие, которое запускается во время выполнения флэш-памяти каждый раз, когда обновляется представление (примерно).Вы можете добавить прослушиватель событий к корневому экранному объекту и запустить метод update ().Это заменит то, что вы в настоящее время делаете в своем таймере.

Подробное объяснение того, почему EnterFrame более полезен, чем Timer, в вашем игровом контексте можно прочитать здесь:

http://www.bit-101.com/blog/?p=910

0 голосов
/ 07 июля 2011

Эта проблема может быть результатом перезапуска класса Timer при каждом изменении свойства задержки.

Из документов Adobe:

Если вы установите интервал задержки во время работы таймера, таймер перезапустится с той же итерацией repeatCount.

http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/utils/Timer.html#delay

Это в основном означает, что таймер перезапускается с 0, но запоминает, сколько раз он повторялся. Я понял, что мой ответ становится длинным, поэтому я добавил ссылку внизу.

РЕШЕНИЕ : используйте flash.utils.getTimer () вместо объекта Timer.

http://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/flash/utils/package.html#getTimer()

Функция getTimer () возвращает целое число, представляющее количество миллисекунд, прошедших с момента запуска файла .swf. Если вы проверяете это число каждый кадр, вы можете увидеть, сколько времени прошло с предыдущего кадра. Просто продолжайте добавлять количество миллисекунд, которые прошли каждый кадр, пока это число не достигнет вашего порога, затем вызовите функцию рисования линий и сбросьте счетчик.

При проверке, чтобы увидеть, нажата ли клавиша, уменьшите новую переменную myDelay вместо свойства Timer.delay.

    var ms:int;
    var timeStamp:int = flash.utils.getTimer();
    var myDelay:Number;    

    onEnterFrame() {

          // Track how much time has passed since the last frame
          ms += flash.utils.getTimer() - timeStamp;

          if (ms > myDelay)
          {
               // DRAW THE ROAD LINES
               drawLines();
               // RESET THE COUNTER 
               ms = 0;
          }

          //other stuff  

          // Record the timestamp of this frame so you can see the difference next frame
          timeStamp = flash.utils.getTimer();                 
    }

ОБЪЯСНЕНИЕ СБРОСА ТАЙМЕРА:

ПРИМЕЧАНИЕ. Я предполагаю, что вы проверяете нажатия клавиш каждую секунду. Если вы изменяете свойство задержки таймера каждый кадр (например, 24 раза в секунду) и ваш таймер срабатывает реже, чем 24 раза в секунду, он будет сброшен до того, как получит возможность отправить событие для вызова своего обработчика функция для создания линий.

Если вы посмотрите на приведенный ниже пример, запуск и остановка события - это единственный способ предотвратить его сброс, но даже в этом случае функция обработчика события таймера будет вызываться только тогда, когда задержка меньше времени между изменения в задержке. Поскольку среднее значение SWF составляет 24 кадра в секунду, это означает, что задержка должна быть меньше, чем 41,6 миллисекунды для вызова, прежде чем следующий кадр изменит значение еще раз.

  package 
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.events.TimerEvent;
    import flash.utils.Timer;

    /**
     * ...
     * @author 
     */
    public class Main extends Sprite 
    {

        var timer:Timer;
        var keyPressed:Boolean = false;

        public function Main():void 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }

        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            timer = new Timer(50);
            timer.addEventListener(TimerEvent.TIMER, function ():void { trace (timer.delay); } );
            timer.start();

            stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDown);
            stage.addEventListener(KeyboardEvent.KEY_UP, keyUp );

            addEventListener(Event.ENTER_FRAME, onEnterFrame);

        }

        function onEnterFrame (e:Event)
        {                   
            if (keyPressed)
            {
                timer.stop();
                timer.delay -= 1;
                timer.start();
            }
        }

         function keyDown (e:KeyboardEvent):void { keyPressed = true; } 


         function keyUp (e:KeyboardEvent):void { keyPressed = false; }
    }

}
...