Оптимизация плавности перехода / движения для 2D флеш игры

Обновление 6:

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

  1. 30 FPS: http://www.feedpostal.com/test/simple/30/SimpleMovement.html
  2. 40 FPS: http://www.feedpostal.com/test/simple/40/SimpleMovement.html
  3. 60 FPS: http://www.feedpostal.com/test/simple/60/SimpleMovement.html
  4. 100 FPS: http://www.feedpostal.com/test/simple/100/SimpleMovement.html

Код:

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

    [SWF(width="800", height="600", frameRate="40", backgroundColor="#000000")]

    public class SimpleMovement extends Sprite
    {
        private static const TURNING_SPEED:uint = 180;
        private static const MOVEMENT_SPEED:uint = 400;
        private static const RADIAN_DIVIDE:Number = Math.PI/180;
        private var playerObject:Sprite;
        private var shipContainer:Sprite;
        private var moving:Boolean = false;
        private var turningMode:uint = 0;
        private var movementTimestamp:Number = getTimer();
        private var turningTimestamp:Number = movementTimestamp;

        public function SimpleMovement()
        {
            //step 1: create player object
            playerObject = new Sprite();
            playerObject.graphics.lineStyle(1, 0x000000);
            playerObject.graphics.beginFill(0x6D7B8D);
            playerObject.graphics.drawRect(0, 0, 25, 50);
            //make it rotate around the center
            playerObject.x = 0 - playerObject.width / 2;
            playerObject.y = 0 - playerObject.height / 2;
            shipContainer = new Sprite();
            shipContainer.addChild(playerObject);
            shipContainer.x = 100;
            shipContainer.y = 100;
            shipContainer.rotation = 180;
            addChild(shipContainer);

            //step 2: install keyboard hook when stage is ready
            addEventListener(Event.ADDED_TO_STAGE, stageReady, false, 0, true);

            //step 3: install rendering update poll
            addEventListener(Event.ENTER_FRAME, updatePoller, false, 0, true);
        }

        private function updatePoller(event:Event):void
        {
            var newTime:Number = getTimer();

            //turning
            if (turningMode != 0)
            {

                var turningDeltaTime:Number = newTime - turningTimestamp;
                turningTimestamp = newTime;
                var rotation:Number = TURNING_SPEED * turningDeltaTime / 1000;
                if (turningMode == 1) shipContainer.rotation -= rotation;
                else shipContainer.rotation += rotation;
            }

            //movement
            if (moving)
            {
                var movementDeltaTime:Number = newTime - movementTimestamp;
                movementTimestamp = newTime;
                var distance:Number = MOVEMENT_SPEED * movementDeltaTime / 1000;
                var rAngle:Number = shipContainer.rotation * RADIAN_DIVIDE; //convert degrees to radian
                shipContainer.x += distance * Math.sin(rAngle);
                shipContainer.y -= distance * Math.cos(rAngle);
            }
        }

        private function stageReady(event:Event):void
        {
            //install keyboard hook
            stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDown, false, 0, true);
            stage.addEventListener(KeyboardEvent.KEY_UP, keyUp, false, 0, true);
        }

        private final function keyDown(event:KeyboardEvent):void
        {
            if ((event.keyCode == 87) && (!moving))  //87 = W
            {
                movementTimestamp = getTimer();
                moving = true;
            }
            if ((event.keyCode == 65) && (turningMode != 1)) //65 = A
            {
                turningTimestamp = getTimer();
                turningMode = 1;
            }
            else if ((event.keyCode == 68) && (turningMode != 2)) //68 = D
            {
                turningTimestamp = getTimer();
                turningMode = 2;
            }
        }

        private final function keyUp(event:KeyboardEvent):void
        {
            if ((event.keyCode == 87) && (moving)) moving = false; //87 = W
            if (((event.keyCode == 65) || (event.keyCode == 68)) && (turningMode != 0)) turningMode = 0; //65 = A, 68 = D
        }
    }
}

Результаты оказались такими, как я ожидал. Абсолютно без улучшений. Я действительно надеюсь, что у кого-то есть другое предложение, поскольку эта вещь нуждается в исправлении. Кроме того, я сомневаюсь, что это моя система, так как у меня она довольно неплохая (8 ГБ ОЗУ, Q9550 QuadCore Intel, ATI Radeon 4870 512 МБ). Кроме того, у всех остальных, кого я до сих пор спрашивал, та же проблема с моим клиентом.

Обновление 5: еще один пример плавной флеш-игры, чтобы продемонстрировать, что мое движение определенно отличается! См. http://www.spel.nl/game/bumpercraft.html

Обновление 4. Я проследил время до рендеринга (EVENT.RENDER) и сразу после рендеринга (EVENT.ENTER_FRAME), результаты:

rendering took: 14 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 14 ms
rendering took: 14 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 24 ms
rendering took: 18 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 232 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms

Диапазон составляет 12-16 мс. Во время этих различий шокирующее / искривляющее / мерцающее движение уже продолжалось. Существует также 1 пик 232 мс, в это время был относительно большой перекос. Это, однако, не самая большая проблема, самая большая проблема - постоянные небольшие перекосы во время нормального движения. Это дает кому-нибудь ключ к разгадке?

Обновление 3: после тестирования я знаю, что следующие факторы не вызывают мою проблему:

  • Качество растрового изображения -> изменено в фотошопе на более уродливую 8-цветную оптимизированную графику, никакого улучшения вообще нет.
  • Постоянное вращение изображения при повороте -> отключено, улучшения вообще нет
  • Рендеринг в браузере -> попытался использовать флеш-плеер в автономном режиме, вообще никаких улучшений

Я на 100% убежден, что проблема заключается либо в моем коде, либо в моем алгоритме. Пожалуйста, помогите мне. Прошло почти две недели (1 неделю, когда я задавал этот вопрос на SO), и мне все еще нужно получить свой золотой ответ.

Обновление 1: см. Нижнюю часть для полного исходного проекта Flex и демонстрацию, демонстрирующую мою проблему.

Я работаю над 2d флеш игрой. Корабли игрока создаются как объект:

ships[id] = new GameShip();

Когда доступна информация о движении и повороте, она направляется на соответствующий корабль:

ships[id].setMovementMode(1); //move forward

Теперь внутри этого GameShip движение объекта происходит с помощью события Event.ENTER_FRAME:

addEventListener(Event.ENTER_FRAME, movementHandler);

Затем выполняется следующая функция:

private final function movementHandler(event:Event):void
        {
            var newTimeStamp:uint = UtilLib.getTimeStamp(); //set current timeStamp
            var distance:Number = (newTimeStamp - movementTimeStamp) / 1000 * movementSpeed; //speed = x pixels forward every 1 second
            movementTimeStamp = newTimeStamp; //update old timeStamp
            var diagonalChange:Array = getDiagonalChange(movementAngle, distance); //the diagonal position update based on angle and distance
            charX += diagonalChange[0];
            charY += diagonalChange[1];
            if (shipContainer)
            { //when the container is ready to be worked with
                shipContainer.x = charX;
                shipContainer.y = charY;
            }
        }

private final function getDiagonalChange(angle:Number, distance:Number):Array
        {
            var rAngle:Number = angle * Math.PI/180; //convert degrees to radian
            return [Math.sin(rAngle) * distance, (Math.cos(rAngle) * distance) * -1];
        }

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

Я установил целевой FPS проекта на 100 и создал счетчик FPS. Согласно счетчику FPS, средний FPS в Firefox составляет около 100, а верхний - 1000, а нижний - 22. Я думаю, что нижний и верхний FPS происходят только во время инициализации клиента (запуска).

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

Очень сложно объяснить, в чем заключается настоящая проблема, но в целом это не совсем плавное движение. Итак, есть ли у вас какие-либо предложения о том, как сделать движение или переход объектов идеально плавным?

Обновление 1:

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

Клиент: http://feedpostal.com/test/MovementTest.html

Проект Actionscript (полный источник): http://feedpostal.com/test/MovementTest.rar

Пример гладкой флеш-игры (не созданной мной): http://www.gamesforwork.com/games/swf/Mission%20Racing_august_10th_2009.swf

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

Обратите внимание: да, это на самом деле довольно гладко. Но это определенно не достаточно гладко.

8 ответов

Решение

Я не знаю, есть ли здесь какой-нибудь золотой ответ, но у меня есть пара предложений.

Во-первых, я бы обошелся без запросов на такие вещи, как оптимизация Math.PI/180 и так далее. В целом высокая частота кадров должна давать понять, что простые вычисления ничего не замедляют.

Во-вторых, для устранения случайных всплесков задержки отображения: мне кажется, что сборщик мусора работает очень часто. При очень кратком рассмотрении вашего кода я не увидел никаких очевидных причин частых сборов мусора, но у меня есть два предложения. Во-первых, если у вас есть доступ к Flash IDE, я бы попробовал воссоздать ваш проект без использования инфраструктуры Flex. Проект Flash не содержит никакого кода, кроме того, что вы вставили в него, но Flex использует множество собственных арканов, что не всегда может быть очевидным, и некоторое взаимодействие между вашим кодом и фреймворком может вызывать сборщик мусора.

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

Наконец, что касается общей плавности, мой единственный комментарий заключается в том, что обновления экрана Flash по своей природе немного неровны, и реально у вас есть только два доступных подхода. Либо вы перемещаете своих актеров в соответствии с обновлениями кадров, что делает их движения слегка неравномерными при изменении частоты кадров, либо вы перемещаете их в соответствии с прошедшим временем, что делает их общее движение плавным (в пикселях в секунду), но их отображение слегка неравномерным (в перемещенных пикселях). за кадр). Разница увеличивается при более высоком FPS.

Кроме того, важно помнить, что после того, как Flash сделал свои обновления, их отображение на экране сильно зависит от вашей видеокарты. Особенно вы обнаружите, что проблемы сдвига и vsync могут быть очень заметны в одной среде и отсутствовать в другой. Нет никакого реального способа, которым разработчик мог бы решить эту проблему, кроме как вообще избегать анимаций с очень высоким FPS и сохранять общую нагрузку на процессор как можно ниже.

редактировать: больше о том, что я имею в виду, что время обновления фрейма "по своей природе неравномерно", пожалуйста, смотрите в этом блоге. Задержка между обновлениями экрана, варьирующаяся между 12-16 мс, не является чем-то, с чем вы можете что-либо делать; это результат того факта, что ОС и браузер влияют на работу синхронизации Flash. (Это также то, что вы увидите даже в пустом фильме, поэтому многие комментарии в этой теме об оптимизации математики и т. Д. Не помогут вам.) Вы не можете избежать такого рода изменений, но, как я сказанное выше, вы можете настроить свои визуальные эффекты, чтобы вызвать эффект, который вы хотите. В любом случае, я думаю, что о шипах гораздо больше стоит беспокоиться. Вариант, на который вы смотрите, невелик, и его будет трудно заметить в игре, где много всего происходит, но шипы вопиющие.

править 2 Вы спрашиваете: "Вы действительно думаете, что эти плавные игры используют тот же алгоритм движения, что и я?"

Ответ, я думаю, они делают что-то намного проще. Они почти наверняка делают одно из следующего:

function onEnterFrame() { // move at a constant speed per frame
    ship.angle += dtheta;
    ship.x += speed * Math.cos( ship.angle );
    ship.y += speed * Math.sin( ship.angle );
}

function onEnterFrame2() { // move at a constant speed per second
    var dt:Number = getTimeSinceLastFrame();
    ship.angle += anglePerSecond * dt/1000;
    var dist:Number = speedPerSecond * dt/1000;
    ship.x += dist * Math.cos( ship.angle );
    ship.y += dist * Math.sin( ship.angle );
}

Другими словами, либо перемещайте постоянное расстояние на кадр, либо постоянное расстояние в секунду. Это два простейших способа, с помощью которых вы можете приблизиться к этому, и два варианта, которые приведут к наиболее плавному отображению во Flash. Они будут выглядеть одинаково при постоянной частоте кадров, а последний метод будет выглядеть более плавно при слегка изменяющихся частотах кадров по причинам, аналогичным "временному псевдониму", упомянутому в статье, которую вы связали. Но выбор между этими методами действительно сводится к тому, что, если произойдет резкий скачок процессора, после его окончания вы хотите, чтобы корабль продолжал двигаться или нет? Что действительно является вопросом игрового дизайна. Одна вещь, которую я сделал в прошлом, это использование второго метода при dt максимально в 2 или 3 раза больше длительности идеального кадра (1/ кадр / с).

Как вы, наверное, заметили, два метода, которые я только что порекомендовал, это именно то, что "Исправьте ваш временной шаг!" статья говорит не делать. Это потому, что эта статья о численно интегрированных физических движках, а это не то, что вы делаете. Если вы начнете реализовывать пружины и гравитацию, то да, всякий раз, когда временные шаги становятся большими, это приведет к большой ошибке, потому что для такого типа моделирования, чтобы упростить вещи, ошибка зависит от размера временного шага. В том, что вы делаете, это не так, поэтому случайные большие временные шаги не влияют на правильность симуляции.

Ответить на обновление 6

Во-первых, я не говорил вам, что у вас проблемы с производительностью, я специально говорил об обратном. Я предложил минимальное воспроизведение, потому что я полагал, что ваша проблема была или где-то еще в вашем проекте, или неизбежна, и я все еще делаю. Во-вторых, теперь я чувствую себя вполне комфортно, когда говорю, что вы делаете то же самое, что и в любой другой флэш-игре, и любые проблемы, которые вы видите, не могут быть решены иначе, как в восприятии. В новых ссылках, которые вы разместили, анимация выглядит идеально плавной, если я ее просматриваю в автономном SWF-плеере, и в браузерах слегка мерцают передние и задние края (больше в Firefox, чем в IE). Технически, я не думаю, что это может улучшиться (особенно, когда это в основном идеально в автономном плеере, подразумевая, что контейнер влияет на любую изменчивость в браузерах.)

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

В качестве проверки работоспособности, вот похожая минимальная версия, которую я сделал в IDE. http://www.fenomas.com/random/ship/ Производительность сравнима с вашей на моей машине, и, как я уже сказал, я действительно не вижу никаких проблем. (За исключением случайного всплеска, который я сейчас замечаю, он возникает только для меня в Firefox.) Опять же, особенно тот факт, что обе версии кажутся мне в идеале идеальными для отдельного игрока, еще больше убеждает меня в том, что здесь нет золотого алгоритма. Я знаю, что это не тот ответ, который вам нужен, но тот, который я получил.

Ваш код работает без проблем для меня. Никаких всплесков вообще. Протестировал его с помощью следующего кода, добавленного в конце функции updatePoller.

var shadow:Sprite = new Sprite();
shadow.graphics.beginFill(0xFFFFFF, 0.01);
shadow.graphics.lineStyle(1, 0xFFFFFF, 0.8);
shadow.graphics.drawRect(0, 0, 25, 50);
this.addChildAt(shadow, 0);
shadow.x = shipContainer.x;
shadow.y = shipContainer.y;
shadow.rotation = shipContainer.rotation;

Версия со скоростью 100 кадров в секунду имеет тенденцию к получению неоднородных шаблонов, но это нормально, потому что, исходя из ваших вычислений, невозможно отобразить 100 кадров в секунду, если вычисление кадра занимает более 10 мс. Так что, по крайней мере для меня, последний код работает без проблем, со скоростью 30 кадров в секунду.

Что касается нечеткой части, серьезной черты, и, надеюсь, вы не разозлитесь из-за того, что я спрашиваю: есть ли шанс, что нечеткий / размытый эффект связан с вашим монитором? Даже при времени отклика 10 мс на ЖК-мониторе белое быстро движущееся изображение, наложенное на статичный черный фон, выглядит размытым.

Я думаю, корень вашей проблемы в том, что " вертикальная синхронизация" не такая, как на экране. Это та же самая проблема, которая возникает при просмотре фильма со скоростью 24 кадра в секунду, например, на экране с частотой 60 Гц. Обновления не будут идеально совпадать (в вашем случае 100/60), и когда они совершат больший прыжок, это будет выглядеть как небольшое дрожание в движении.

Это может быть несколько исправлено снижением частоты кадров, в любом случае все, что выше, чем у экрана, в любом случае является пустой тратой вычислительной мощности. Это не может быть полностью исключено, хотя возможны новые wmodes для встраивания флэш-памяти.

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

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

Вот мои "возражения":

  • Вы используете много подразделений. Деление дороже, чем умножение.

    var distance: Number = (newTimeStamp - motionTimeStamp) / 1000 * motionSpeed;

может быть легко написано как

var distance:Number = (newTimeStamp - movementTimeStamp) * .001 * movementSpeed;
  • У вас есть много ссылок на множество функций.

    Такие вещи, как fixAngle() и т. Д. Могут находиться внутри одной и той же функции, без частых повторных вызовов. Это относится к ссылкам на внешние классы и Math.PI или Math.sin и так далее, как указали Феномас и Аллан.

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

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

Могу ли я предположить, что вы беспокоитесь преждевременно?

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

Автомобиль движется не очень быстро - вероятно, пиксель каждые несколько кадров. Это фон, который делает большую часть движения. Посмотрите внимательнее: есть небольшое дрожание и тот же эффект "трудно сфокусировать", который вы пытаетесь исправить, но, поскольку это фон, он кажется нормальным. И даже когда автомобиль действительно показывает эти эффекты, фон и игровой процесс отвлекают вас от их заметки.

Я думаю, что вы заметили дрожание, потому что все, что у вас есть сейчас, это корабль, движущийся на абсолютно черном фоне. Как только остальная часть игры будет готова, у игрока, вероятно, не останется свободного внимания, чтобы заметить небольшое дрожание. Что касается эффекта "трудно сфокусироваться", он исчезает, когда вы уменьшаете скорость движения корабля.

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

Я думаю, что это почти наверняка, потому что вы на 80fps. Вспышка просто не может дать постоянную частоту кадров так быстро. Опустите до 30 кадров в секунду и продолжайте тестирование. Кроме того, попробуйте летать на корабле перед реальным фоном, и я думаю, вы заметите это меньше.

Файлы для загрузки не существует ( http://feedpostal.com/test/MovementTest.rar).

Я ответил на другой вопрос, касающийся этой проблемы, читайте ниже:

Я чувствую твою боль, когда я в настоящее время в окопах, разрабатываю свою собственную игру. При настройках по умолчанию Flash рендерер вызывает ужасные проблемы с разрывом экрана / v-синхронизацией, независимо от того, какой код вы производите.

Вот почему я был рад найти самый простой и элегантный ответ, который не был рефакторингом кода (который ни на что не помогает, проблема в Flash-плеере, а не в коде).

Просто включите аппаратное ускорение в настройках публикации. Есть два разных варианта:

Уровень 1: Прямой; и уровень 2: GPU.

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

Целевой рынок играет здесь важную роль: если это серьезная игра для геймеров, вам не нужно беспокоиться о возможных проблемах с производительностью, так как большинство геймеров имеют GPU.

Эта статья не дала мне конкретного решения, но привела меня в правильном направлении. НО, если ваша игра будет в окне браузера, вам, возможно, придется использовать ту же технику установки wmode для direct или gpu.

Другие вопросы по тегам