Autor Wątek: Złe liczenie delty czasowej?  (Przeczytany 2794 razy)

Offline Arthes

  • Użytkownik
    • Gromaniak

# Luty 25, 2012, 12:19:09
Witam.
Tworzę prostą grę w HTML5 (wężyk), i zrobiłem obliczanie delty czasowej. Jednakże wydaje mi się, że ona źle działa... Oto kod:

onload = function() {
var Canvas = document.getElementById('snakegame');
var Context = Canvas.getContext('2d');

var prevTime;
var curTime;
var deltaTime;

var keyLeft = false;
var keyRight = false;
var keyUp = false;
var keyDown = false;

var Player = {}
Player.X = 0;
Player.Y = 0;

//Główna pętla gry

setInterval(function() {
//Wyczyszczenie płótna, aktualizacja czasu
Context.clearRect(0, 0, 640, 480);
prevTime = (new Date).getTime();
//-----

//Kod odpowiedzialny za aktualizacje
if (keyLeft) Player.X -= 2000 * deltaTime;
if (keyRight) Player.X += 2000 * deltaTime;
if (keyUp) Player.Y -= 2000 * deltaTime;
if (keyDown) Player.Y += 2000 * deltaTime;
//-----

//Kod odpowiedzialny za rysowanie
Context.fillText('DeltaTime: ' + deltaTime + '   keyLeft: ' + keyLeft, 8, 8);
Context.fillRect(Player.X, Player.Y, 248, 248);



//Kod odpowiedzialny za obliczenie FPS i delty
curTime = (new Date).getTime();
deltaTime = (curTime - prevTime) / 1000;
if (deltaTime == 0) deltaTime = 1 / 1000;
//-----

}, 1000/60);

//-----

//Obsługa zdarzeń
onkeydown = function(e) {
if (e.which == 65 || e.which == 37) keyLeft = true;
if (e.which == 68 || e.which == 39) keyRight = true;
if (e.which == 87 || e.which == 38) keyUp = true;
if (e.which == 83 || e.which == 40) keyDown = true;
}
onkeyup = function(e) {
if (e.which == 65 || e.which == 37) keyLeft = false;
if (e.which == 68 || e.which == 39) keyRight = false;
if (e.which == 87 || e.which == 38) keyUp = false;
if (e.which == 83 || e.which == 40) keyDown = false;
}
//-----
}

Niby wszystko jest dobrze, a ruch wykonywany jest za wolno... Po ustawieniu:
Player.Y += 2000 * deltaTime;gracz powinien przesuwać się o 2000 pixeli co sekundę, a przesuwa się o wieeeeeele mniej, bardzo wolno...
Co źle robię? Dzięki za odpowiedzi ;)

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline Liosan

  • Redaktor

# Luty 25, 2012, 12:21:11
Sprawdź jednostki, jakie zwraca getTime().

Liosan

Offline Arthes

  • Użytkownik
    • Gromaniak

# Luty 25, 2012, 12:27:12
getTime zwraca milisekundy od 01.01.1970... Może nie powinienem ich dzielić przez 1000?
deltaTime = (curTime - prevTime) / 1000;

Offline Liosan

  • Redaktor

# Luty 25, 2012, 12:53:38
getTime zwraca milisekundy (...)Może nie powinienem ich dzielić przez 1000?
Nieeeemożliiiiiweee... ;) Policz sobie, i Ci wyjdzie że kazałeś postaci poruszać się dwa piksele na sekundę.

Liosan

Offline LukeLi

  • Użytkownik
    • hex13.net - gry, aplikacje html5

# Marzec 01, 2013, 11:28:37
nie o jednostki chodzi, tylko o złe miejsce w kodzie, gdzie zostają przypisane zmienne.
Teraz zapamiętujesz czas:
Cytuj
prevTime = (new Date).getTime()
rysujesz coś na canvasie i jeszcze raz zapamiętujesz czas:
Cytuj
curTime = (new Date).getTime();
czyli de facto mierzysz tylko czas rysowania po canvasie - który zapewne jest niewielki, coś jak 0.000001 sekundy? (na przykład), natomiast czasu który upływa między kolejnymi "tyknięciami" już nie mierzysz.

powinieneś przypisanie do prevTime z początku wywalić i coś takiego zrobić:

Cytuj
//Kod odpowiedzialny za obliczenie FPS i delty
curTime = (new Date).getTime();
deltaTime = (curTime - (prevTime||curTime)) / 1000;
if (deltaTime == 0) deltaTime = 1 / 1000;
prevTime = curTime;

w ten sposób prevTime "zapamięta się" aż do następnego wywołania funkcji.

EDIT:
aha i ja bym ten kod dał na początek funkcji, a nie na koniec, ale może nie ma różnicy? nie wiem
« Ostatnia zmiana: Marzec 01, 2013, 11:33:11 wysłana przez LukeLi »

Offline Xion

  • Moderator
    • xion.log

# Marzec 01, 2013, 11:33:25
Możesz też inicjalizować prevTime na samym początku, żeby uniknąć operacji || w każdej klatce.