[JS] window.setInterval precision

Pagina: 1
Acties:

  • TheBlasphemer
  • Registratie: September 2004
  • Laatst online: 13-11-2025
Ten eerste mijn excuses voor het posten van een JS topic hier, maar dit heeft toch echt meer te maken met Programming en Webscripting dan Wedesign en Graphics. Gaat hier niet over DHTML of CSS combo.
Na mijn korte excuus om hier JS te mogen posten, de echte vraag maar eens:

Ik heb een spelletje geschreven in JS dat via de Messenger API multiplayer heeft.
Alles werkte prima, tot ik highscores ging implementeren. Ineens leek de timer op elke PC anders te lopen :o
Ik heb een timer lopen met window.setInterval("update();",24); (24ms om cheaters te slim af te zijn, als ze een score verzinnen en niet deelbaar is door 24ms vallen ze door de mand ;))
Anyway, alles leuk en aardig, ik dus een debuggertje bouwen die aan de hand van begintijd van de update functie en eindtijd in ms wat dingen berekend:
interval -> de tijd tussen elke update
ticktime -> de tijd die elke update nodig had

Op mijn PC is de interval rond de 33, en de tick komt als er wat geupdate moet worden op 2ms. Op iemand anders zn PC respectievelijk 45/15.
Alletwee zijn de intervals verre van wat ze horen te zijn: 24ms. Dit licht echter niet aan de update functie, die heeft maar 15ms hooguit nodig.
Ik *denk* dat de windows-methode op deze timers van toepassing is: timers komen nadat andere threads klaar zijn.

Nu is mijn vraag, zou iemand kunnen bedenken hoe ik op een andere manier een timer kan bouwen, of een andere functie in JS kan gebruiken die toch, tenminste op de lange termijn, grofweg 24ms aanhoud ?
De games worden namelijk gesynched, en als een klok anders loopt dan de andere gaan de poppetjes stotteren, en de highscores worden zo niet netjes :(

Alvast bedankt,
TB

[img=http://www.web2messenger.com/smallstatus/w2m/theblasp.png]


  • André
  • Registratie: Maart 2002
  • Laatst online: 15-04 09:54

André

Analytics dude

setInterval en setTimeout in javascript zijn verre van betrouwbaar, je zult met iets anders moeten gaan meten/werken ;)

  • TheBlasphemer
  • Registratie: September 2004
  • Laatst online: 13-11-2025
André schreef op maandag 16 januari 2006 @ 16:56:
setInterval en setTimeout in javascript zijn verre van betrouwbaar, je zult met iets anders moeten gaan meten/werken ;)
Misschien enige tips :/ ?
ActiveX, Flash, en of Java zijn niet toegestaan vanwege veiligheids redenen :/
offtopic:
Waarom is dat :( smileytje zo "boos" op GoT?

[ Voor 10% gewijzigd door TheBlasphemer op 16-01-2006 16:58 ]

[img=http://www.web2messenger.com/smallstatus/w2m/theblasp.png]


  • JeRa
  • Registratie: Juni 2003
  • Laatst online: 30-04-2025
Ik weet niet hoe afhankelijk je spel is van de interval of de methode waarop de tijd verloopt, maar zou je niet een absolute waarde van tijd kunnen gebruiken en telkens het verschil in tijd sinds de vorige tick kunnen gebruiken als een timedelta? Dat alle acties dus worden vermenigvuldigd met het verschil in tijd :) (die acties moeten dan dus wel gebaseerd zijn op dezelfde tijdseenheid).

[ Voor 3% gewijzigd door JeRa op 16-01-2006 16:58 ]


  • TheBlasphemer
  • Registratie: September 2004
  • Laatst online: 13-11-2025
JeRa schreef op maandag 16 januari 2006 @ 16:58:
Ik weet niet hoe afhankelijk je spel is van de interval of de methode waarop de tijd verloopt, maar zou je niet een absolute waarde van tijd kunnen gebruiken en telkens het verschil in tijd sinds de vorige tick kunnen gebruiken als een timedelta? Dat alle acties dus worden vermenigvuldigd met het verschil in tijd :) (die acties moeten dan dus wel gebaseerd zijn op dezelfde tijdseenheid).
Zou ik inderdaad wel kunnen doen, maar vooral wrijvingsfuncties (ja, we doen hier aan een semi-natuurkundige-simulatie (aka game ;))) worden dan moeilijk. Not to mention dat dan mn gehele engine aangepast dient te worden *sniff*

[img=http://www.web2messenger.com/smallstatus/w2m/theblasp.png]


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Bij de start van de game sla je de starttijd in ms met getMilliseconds op in een var, en bij het "finishen" van de game lees weer getMilliseconds de tijd uit en bereken je het verschil (in ms) door de waarde van je startvar te gebruiken. Zo moeilijk is dat toch niet :?

[ Voor 27% gewijzigd door RobIII op 16-01-2006 18:10 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • JeRa
  • Registratie: Juni 2003
  • Laatst online: 30-04-2025
TheBlasphemer schreef op maandag 16 januari 2006 @ 16:59:
[...]


Zou ik inderdaad wel kunnen doen, maar vooral wrijvingsfuncties (ja, we doen hier aan een semi-natuurkundige-simulatie (aka game ;))) worden dan moeilijk. Not to mention dat dan mn gehele engine aangepast dient te worden *sniff*
Hoezo worden de wrijvingsfuncties dan moeilijker? :)

Wrijving is toch een afgeleide waarde die je afhankelijk van de waarde ergens bij optelt of aftrekt? Die kun je net zo goed vermenigvuldigen met die delta, heb ik in twee verloren spellen zelf ook gedaan :)

  • TheBlasphemer
  • Registratie: September 2004
  • Laatst online: 13-11-2025
RobIII schreef op maandag 16 januari 2006 @ 17:03:
Bij de start van de game sla je de starttijd in ms met getMilliseconds op in een var, en bij het "finishen" van de game lees weer getMilliseconds uit en bereken je het verschil (in ms) door de waarde van je var te gebruiken. Zo moeilijk is dat toch niet :?
Leuke is dat je dan wel op een langzame PC (waar de intervals langer duren) heel langzaam loopt, en dan (bijna) geen highscore kan planten :(
JeRa schreef op maandag 16 januari 2006 @ 17:03:
[...]

Hoezo worden de wrijvingsfuncties dan moeilijker? :)

Wrijving is toch een afgeleide waarde die je afhankelijk van de waarde ergens bij optelt of aftrekt? Die kun je net zo goed vermenigvuldigen met die delta, heb ik in twee verloren spellen zelf ook gedaan :)
"Wrijving" die ik nu doe is telkens vx en vy met een getal als 0.99 vermenigvuldigen.
Ik kan dan wel vx en vy vermenigvuldigen met 0.99^delta_t, maar dan moet je dat ook weer helemaal gaan integreren naar de x en y :/

[img=http://www.web2messenger.com/smallstatus/w2m/theblasp.png]


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
TheBlasphemer schreef op maandag 16 januari 2006 @ 17:24:
Leuke is dat je dan wel op een langzame PC (waar de intervals langer duren) heel langzaam loopt, en dan (bijna) geen highscore kan planten :(
Que :?
Op een langzame PC loopt de tijd even snel als op een snelle pc hoor :?

JavaScript:
1
2
3
4
5
6
7
8
var dtStart = new Date();

//Doe hier je ding
alert('Blaat');
//Doe hier je ding

var dtEnd = new Date();
alert((dtEnd-dtStart)+'ms');


Met getMilliseconds zat ik er langs, die geeft het aantal milliseconden van de huidige seconde terug (0...999). Gewoon een date object gebruiken (zoals hierboven in mijn voorbeeld) is meer dan genoeg.

[ Voor 7% gewijzigd door RobIII op 16-01-2006 18:09 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • TheBlasphemer
  • Registratie: September 2004
  • Laatst online: 13-11-2025
RobIII schreef op maandag 16 januari 2006 @ 18:09:
[...]

Que :?
Op een langzame PC loopt de tijd even snel als op een snelle pc hoor :?

JavaScript:
1
2
3
4
5
6
7
8
var dtStart = new Date();

//Doe hier je ding
alert('Blaat');
//Doe hier je ding

var dtEnd = new Date();
alert((dtEnd-dtStart)+'ms');


Met getMilliseconds zat ik er langs, die geeft het aantal milliseconden van de huidige seconde terug (0...999). Gewoon een date object gebruiken (zoals hierboven in mijn voorbeeld) is meer dan genoeg.
Echter zal het poppetje hier maar eens per 40ms ipv eens per 24ms verplaatsen.
Als het poppetje dan beweegt met 10pixels per frame ofzo, dan is de snellere pc sneller :P

[img=http://www.web2messenger.com/smallstatus/w2m/theblasp.png]


  • JeRa
  • Registratie: Juni 2003
  • Laatst online: 30-04-2025
TheBlasphemer schreef op maandag 16 januari 2006 @ 18:28:
[...]


Echter zal het poppetje hier maar eens per 40ms ipv eens per 24ms verplaatsen.
Als het poppetje dan beweegt met 10pixels per frame ofzo, dan is de snellere pc sneller :P
Je moet dan ook uitgaan van andere eenheden, in dit geval zou je kunnen zeggen dat elk poppetje 80 pixels (oid) per seconde mag verplaatsen. Door die verplaatsing per seconde te vermenigvuldigen met de verstreken tijd wordt het spel op elke pc even snel (met het verschil dat de ene persoon meer frames per seconde heeft dan de andere).

  • MisterData
  • Registratie: September 2001
  • Laatst online: 09-04 12:07
Gewoon om de zoveel ms een 'tick' laten callen door setTimeout/setInterval en in je tick uitrekenen hoeveel tijd is verstreken en hoeveel het poppetje dan moet hebben bewogen :)

  • TheBlasphemer
  • Registratie: September 2004
  • Laatst online: 13-11-2025
MisterData schreef op maandag 16 januari 2006 @ 21:25:
Gewoon om de zoveel ms een 'tick' laten callen door setTimeout/setInterval en in je tick uitrekenen hoeveel tijd is verstreken en hoeveel het poppetje dan moet hebben bewogen :)
Ik heb even geprobeerd formules hiervoor op te stellen, maar door collision ed en wrijving is dit bijna onmogelijk, daarom ben ik maar uitgegaan van een vaste tijd per "tick".
Ik heb nu maar deze code gebruikt:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    this.TicksLeft=function() {
        var elapsed=new Date().getTime() - this.timerstart;
        var tickselapsed=Math.floor(elapsed/gameTimePerFrame);
        return tickselapsed-this.timerticks;
    }
    
    this.OnTimer=function(uniq) {
        var curticks=0;
        while (this.timer_running && this.TicksLeft() && curticks<20) {
            this.timerticks++;
            curticks++;
            this.Update();
        }
        if (this.timer_running)
            this.timer=window.setTimeout("GameTimer('"+uniq+"');",0);
    }

Deze roept de OnTimer dus zo vaak mogelijk aan (door gebruik van setTimeout krijgen andere threads wel voorrang), en kijkt dan hoe vaak de Update functie aangeroepen moet worden. (met een max van 20x per tick)

[img=http://www.web2messenger.com/smallstatus/w2m/theblasp.png]


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Dude, dit gaat écht de verkeerde kant op. Ik zou toch nog maar eens goed kijken naar MisterData's suggestie, wil je het "netjes" houden...

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • TheBlasphemer
  • Registratie: September 2004
  • Laatst online: 13-11-2025
RobIII schreef op maandag 16 januari 2006 @ 22:36:
Dude, dit gaat écht de verkeerde kant op. Ik zou toch nog maar eens goed kijken naar MisterData's suggestie, wil je het "netjes" houden...
Die suggestie heb ik overwogen, maar dit werkt om diverse redenen niet :(
Deze roept nu elke keer als er CPU tijd over is aan, en dan kijkt ie wel hoeveel ticks die moet laten doen. in principe hetzelfde als MisterData maar dan opgedeeld in ticks ipv tijd.

[img=http://www.web2messenger.com/smallstatus/w2m/theblasp.png]


  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:40

crisp

Devver

Pixelated

het timing-model in JS is inderdaad verre van betrouwbaar. Eigenlijk moet je de interval/timeout meer zien als een onderwaarde en niet als een precies gegeven. Je zal ook zien dat als je met meerdere intervallen gaat werken de 'precisie' steeds verder afneemt. JS is nu eenmaal niet multi-threaded, dus als 1 interval wordt afgehandeld zullen andere moeten wachten - zelfs als van deze de 'tijd er ook op zit'.

Een manier is inderdaad ervoor zorgen dat je de animatie-snelheid aanpast op de werkelijk verstreken tijd, of (wat ik in DHTML lemmings heb gedaan met redelijk resultaat) de snelheid van de 'spelklok' vertragen als de animatie niet snel genoeg kan...

In een multi-player setting denk ik echter dat het praktisch onmogelijk is hier echt een oplossing voor te geven. In feite zal je de snelheid moeten aanpassen aan die van de traagste client...

[ Voor 13% gewijzigd door crisp op 16-01-2006 23:36 ]

Intentionally left blank


  • TheBlasphemer
  • Registratie: September 2004
  • Laatst online: 13-11-2025
[b][message=25023226,noline]... de snelheid van de 'spelklok' vertragen als de animatie niet snel genoeg kan...
Dit was ook mijn eerste set-up. Echter omdat het gesynched is op twee PCs, begon de beweging te stotteren omdat de ene pc nou eenmaal sneller berekende (of een snelheid in de x richting sneller deed) dan de ander :P
Ook had ik een keer met een vriend gechecken, toen de timer nog eigenlijk gewoon aantal ticks * interval was, wat onze timings waren:
wat bij mij 0:40:879 was, was bij hem 0:29:345 :/

[img=http://www.web2messenger.com/smallstatus/w2m/theblasp.png]


  • NMe
  • Registratie: Februari 2004
  • Laatst online: 15-04 22:07

NMe

Quia Ego Sic Dico.

Ik heb hier even over zitten twijfelen, en na wat overleg met een W&G-modje ben ik toch echt van mening dat dit in Webdesign & Graphics hoort. TheBlasphemer: je hebt gelijk dat dit redelijk in de buurt komt van problemen die je in andere talen ook zou hebben, maar het lijkt me dat je probleem (of in elk geval je oplossing) redelijk JS-specifiek is. En kenners van Javascript zitten nou eenmaal bij de buren. ;)

PW>>WG

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.

Pagina: 1