2009-08-16 3 views
2

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

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

  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 512MB). Кроме того, у всех остальных, кого я спрашивал, была такая же проблема с моим клиентом.

Обновление 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 мс, в то время был относительно большой деформация. Это, однако, не самая большая проблема, самой большой проблемой являются непрерывные мелкие перекосы во время нормального движения. Означает ли это, что кто-нибудь подскажет?

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

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

Я на 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 происходят только во время инициализации клиента (запуск).

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

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

Update 1:

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

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

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

Пример гладкой флеш игры (не созданных мной):

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

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

+1

Что должно выглядеть UtilLib.getTimeStamp()? Это может быть проблема с вашим временем. – grapefrukt

+0

он выполняет следующие действия: var now: Date = new Date(); return now.getTime(); – Tom

+2

Я все еще думаю, что вы слишком зацикливаетесь на этой частоте кадров, и для твердых 30 кадров в секунду будет более реалистично. Однако вы можете попробовать заменить материал Date с помощью getTimer(). Я не уверен, как они сравнивают точность, но я уверен, что это будет быстрее. – grapefrukt

ответ

9

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

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

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

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

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

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

Редактировать: Подробнее о том, что я имею в виду о сроках обновления фреймов, являющихся «по сути неровными», см. this blog post. Задержка между обновлениями экрана, варьирующимися в пределах от 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. Они будут выглядеть одинаково при постоянной частоте кадров, и последний метод будет выглядеть более плавно при несколько разных кадрах по причинам, аналогичным «временному псевдониму», указанному в статье, которую вы связали. Но выбор между этими методами действительно сводится к тому, что, если произойдет всплеск CPU, после того, как все закончится, вы хотите, чтобы корабль продолжал двигаться или нет? Это действительно вопрос дизайна игры. Одна вещь, которую я делал в прошлом, - использовать второй метод, зажав dt не более чем в 2 или 3 раза продолжительностью идеального кадра (1/fps).

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

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

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

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

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

+0

Обратите внимание, что я создал проект ActionScript в Flex Builder, а не проект flex. Как загрузить Flash IDE и как я смогу воссоздать свой проект без использования фреймворка Flex? – Tom

+0

Обновление: Я отслеживал время перед рендерингом (EVENT.RENDER) и сразу после рендеринга (EVENT.ENTER_FRAME), результаты теперь находятся в исходном сообщении. Это вам помогает? – Tom

+1

Вариант, который вы видите между рендерами, не то, что можно избежать - я добавил абзац объяснения. Что касается другого вопроса, я на самом деле не парень Flex; Я не знаю, добавлен ли какой-либо код рамки в проекты AS. В FB должна быть опция, чтобы не удалять временные файлы AS, созданные для кода платформы. Это может позволить вам увидеть добавленный дополнительный код. Что касается использования Flash IDE, на сайте Adobe есть 30-дневная бесплатная пробная версия. Но вы можете быть правы, в проектах AS может отсутствовать код платформы. – fenomas

1

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

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

+0

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

+0

Я добавил полный источник flex и живую демонстрацию к OP. – Tom

0

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

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

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

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

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

+0

Я действительно не думаю, что это не проблема. Если вы читаете статьи, подобные http://gafferongames.com/game-physics/fix-your-timestep/, становится ясно, что движение не так просто, как я думал. Я просто не знаю, как это сделать гладко, вот почему я спрашиваю здесь. Эта проблема слишком велика, чтобы игнорировать, если я продолжу строить другие вещи, моя проблема останется. О черном фоне, вызывающем это, судя по той статье, которую я связал, я не думаю, что это единственное, что виновато. – Tom

+0

Новая игра, с которой вы связались, также демонстрирует мерцающий/труднодоступный эффект, о котором вы беспокоитесь. Когда вы делаете игру, важно как можно быстрее добраться до воспроизводимого прототипа вашего основного игрового механика. Не пытайтесь достичь совершенства. Просто убедитесь, что ваши механики забавны. Вы можете всегда уточнять вещи позже, когда вы * знаете *, что нужно переделать из игры вашего прототипа. Я думаю, что ваше движение находится на стадии «достаточно хорошо», и пришло время работать над остальной частью вашей игры. – Selene

+0

Ну, тогда мы не согласны. Я продемонстрировал проблему многим людям, и все они согласились с тем, что мерцающее движение - это игра, в том числе и я. – Tom

0

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

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

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

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

    var растояние: Number = (новыйTimeStamp - motionTimeStamp)/1000 * движениеSpeed;

можно легко записать в виде

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

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

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

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

+1

Я думаю, что очень маловероятно, что время, необходимое для делений и т. Д., Оказывает какое-то влияние на производительность здесь. – fenomas

+0

Я согласен с Fenomas. Я тестировал скорость этих вычислений, и они очень быстрые. Небольшое различие между оптимизированной версией __definitely__ не видно человеческому глазу. Я убежден, что я не беспокоюсь больше, чем должен. Я видел игры, которые очень гладки, я связал еще один в новейшем обновлении. Кроме того, моя проблема на самом деле очень заметна. У меня нет возможности выпустить такую ​​игру с таким движением. Из-за этого было бы огромным риском продолжить развитие, пока эта проблема мэра все еще жива. Вместо этого я попытаюсь решить это прямо сейчас. – Tom

+0

Хорошо, я получил нижний план для предположения, а не для тестирования, когда все эти данные были доступны. Кажется, я не могу найти, что заставляет его вести себя так. Я замечаю каждую секунду небольшую задержку в рендеринге корабля, как очень легкий обман. Я запустил профайлер и увидел, что большая часть памяти была взята с помощью frameconter и enterFrame, что имело смысл (http://www.lifesine.eu/so/profile1.gif), а также большинство сломавшихся объектов были строками (http: // www.lifesine.eu/so/profile2.gif), поэтому я изменил ключи в настройках на ints (87,65,68) и все uints на ints. К сожалению, это не имело никакого отношения к движению ... –

0

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

+0

Привет, я пробовал более низкие FPS (включая 30). Они значительно увеличивают деформирование и негладкое движение и ухудшают ситуацию.Согласно моему счетчику FPS, флэш-память на самом деле способна поддерживать частоту кадров в 80 FPS. – Tom

2

Ваш код работает ровно для меня. Никаких всплесков. Протестировано с помощью следующего кода, добавленного в конце функции 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 мс на ЖК-мониторе белый быстро перемещающийся что-то накладывается на статический черный фон, имеет тенденцию выглядеть размытым.

+0

Я получаю неравномерные шаблоны до частоты кадров 70. При 70 и выше (включая 100) шаблон является однородным. В любом случае, похоже, он мерцает. У меня 2-дюймовый ЖК-монитор Samsung 22-дюймовый, это должно быть очень хорошо. – Tom

+0

Подводя итог немного. Рендеринг проблем в таких небольших приложениях редко вызван фактическим кодом кадра. Самый большой процессор hog - это фактический рендеринг. Чем больше часть экрана изменяется (можно увидеть с опцией «Показать Redraw Regions ...». Можете ли вы посмотреть в свои процессы и узнать, сколько энергии процессора использует это флеш-приложение? Попробуйте закрыть все. чтобы проиграть такие кадры, также должны быть всплески в использовании ЦП. Я уверен, что в вашем примере на Intel Core 2 Duo 2.2Ghz E4500 2GB Ram появляется впечатление, что он медленнее, чем ваш компьютер. – Virusescu

0

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

+0

Простите, но я считал эту тему закрытой и, таким образом, удалил все соответствующие файлы с моего сервера. – Tom

0

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

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

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

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

Level 1: Direct; и Уровень 2: графический процессор.

Подробнее об этом в официальной документации: Specify publish settings for SWF files и решить, какой вариант подходит для вашей игры.

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

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