2015-03-09 2 views
1

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

Edit:

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

int myFPS; 
     if(gameLoopThread.startTime!=System.currentTimeMillis()) 
    myFPS=(int) (1000/(gameLoopThread.startTime-System.currentTimeMillis())*-1); 
     else 
      myFPS=25; 
     float new2=1; 
    new2=25/myFPS; 

, а затем просто множественным

currentSpeed.y += speed*new2; 

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

+0

Правильные способы создания игрового цикла: https://source.android.com/devices/graphics/architecture.html#loops – fadden

ответ

1

Update:

одного цикла резьбовая:

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

while(isRunning){ 

      beginTime = SystemClock.uptimeMillis(); 
      framesSkipped = 0; 

      //Update game state 
      update(); 

      render(); 

      //how long we took to update and render 
      loopTime = SystemClock.uptimeMillis() - beginTime; 
      //calculate how long to sleep 
      sleepTime = loopPeriod - timeDiff; 

       //All work was done on time. 
       if (sleepTime > 0) { 
        try { 
         Thread.sleep(sleepTime); 
        } catch (InterruptedException e) {} 
       } 

       //We were too slow. Update without rendering. 
       while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) { 
        update(); 
        //make sure we don't keep looping here. 
        sleepTime += loopPeriod; 
        framesSkipped++; 
       } 
      } 
     } 

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

Два потока: (оригинальный ответ)

Другой способ обеспечить стабильное движение при низких FPS, чтобы сделать рендеринг в одном потоке, и логический материал в другом.

Пример для игры логической нити:

while(isRunning){ 

     startTime = SystemClock.uptimeMillis(); 

     //update game logic, no rendering. 
     update(); 

     //time it took to update the game state. 
     loopTime = SystemClock.uptimeMillis() - startTime; 

     //pausing here to make sure we update the right amount per second. 
     if(loopTime < updatePeriod){ 
      try { 
       Thread.sleep(updatePeriod-updateTime); 
      } catch (InterruptedException e) { 
       Log.e(TAG,"Interrupted while sleeping"); 
      } 
     } 
    } 

Период обновления является количество миллисекунд одной итерации обновление разрешено принимать.

updatePeriod = 1000/ups; 

ups = обновления в секунду. Если ваша игра работает со скоростью 60 кадров в секунду, используйте 60 взлетов.

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

Также используйте SystemClock.uptimeMillis(); это более надежно.

+0

Это разумный подход, если только скорость обновления не соответствует скорости отображения, и в этом случае вы будете получать эффекты избиения в анимации, так как часы идут и не соответствуют фазе. Для подхода с отдельными потоками вы действительно хотите, чтобы поток обновления состояния перемещал вещи, когда они, естественно, перемещаются - например. если враги перемещаются дважды в секунду, он должен просыпаться только 2x в секунду, если игрок не движется. Не все игры хорошо подходят для этой модели. – fadden

+0

FWIW, использование 'SystemClock.uptimeMillis()' или 'System.nanoTime()' рекомендуется для 'System.currentTimeMillis()', потому что они используют монотонные часы, а не потому, что они предлагают повышенную точность. Главное различие заключается в том, что время «настенных часов», возвращаемое 'currentTimeMillis()', может идти назад или прыгать вперед, если сеть обновляет часы, в то время как другие просто увеличиваются с постоянной скоростью. – fadden

+0

На самом деле я имел в виду «точность». Я перефразирую это. –

1

Как я отслеживал кадр 1000milliseconds/25 = 40 кадров в секунду

В начале цикла в то время как убедитесь, что вы получите время.

long starttime = System.currentTimeMillis(); 

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

long endtime = System.currentTimeMillis(); 

Вычесть время начала от времени окончания затем разделить на 1000 умножить на -1, чтобы получить сколько раз работоспособного цикла может в секунде.

int MyFPS = (int) (1000/(starttime - endtime) * -1); 

Если ваш ответ 75, значит, вы работаете со скоростью 75 кадров в секунду.

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

@Override 
public void run() { 
    while (THREAD) { 
     long starttime = System.currentTimeMillis(); 
     if (!myHolder.getSurface().isValid()) 
      continue; 
     Update();   <----Running the game. 
     Main_Render(); <----Rendering graphics. 
     long endtime = System.currentTimeMillis(); 
     int MyFPS = (int) (1000/(starttime - endtime) * -1); 
      if (MyFPS >= 25) { 
       sleep_length = MyFPS - 25; 
       try { 
        Thread.sleep(sleep_length); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
    } 
} 
+0

Спасибо, это помогает, но проблема в моем приложении заключается в том, что большую часть времени есть fps падает. Я помню, что в решении, которое я видел некоторое время назад, он использовал время начала и окончания, и вычислил что-то, что он умножил скорость, что сделало скорость всегда одинаковой независимо от того, что это fps. Интересно, что это было. – SpoocyCrep

+0

Проблема с этим подходом заключается в том, что он предполагает, что игра управляет частотой кадров. Это не так. Панель дисплея будет обновляться с заданной скоростью, которая со временем может незначительно меняться, и игра должна соответствовать ей. Если вы пытаетесь запустить игру со скоростью 50 кадров в секунду, а панель работает со скоростью 60 кадров в секунду, у вас не будет гладкой анимации. – fadden