Domanda

C'è un modo semplice per fare un ciclo di gioco in JavaScript? qualcosa di simile ...

onTimerTick() {
  // update game state
}
È stato utile?

Soluzione

setInterval(onTimerTick, 33); // 33 milliseconds = ~ 30 frames per sec

function onTimerTick() {
    // Do stuff.
}

Altri suggerimenti

Ci sono una variegata quantità di modi per raggiungere questo utilizzando seconda dell'applicazione in uso JavaScript. A setInterval () o anche con un while () farebbe il trucco. Questo non funziona per un ciclo di gioco. JavaScript interpretato dal browser, quindi è soggetta a interruzioni. Interrupt faranno parte posteriore gioco del vostro gioco si sentono nervosi.

Le proprietà webkitRequestAnimationFrame di CSS3 mira a correggere questo gestendo il ciclo di rendering stessa. Tuttavia questo non è ancora il modo più efficace per farlo e sarà soggetta a nervosismi se si dispone di un sacco di oggetti in fase di aggiornamento.

Questo è un buon sito web per iniziare con:

http://nokarma.org/2011/02 /02/javascript-game-development-the-game-loop/index.html

Questo sito ha alcune buone informazioni sulle basi di fare un ciclo di gioco. Esso non tocca su qualsiasi tipo di oggetto di design oriented con qualsiasi mezzo. Il modo più preciso per raggiungere temporizzazioni precise è quello di utilizzare la funzione di data.

while ((new Date).getTime() > nextGameTick && loops < maxFrameSkip) {
  Game.update();
  nextGameTick += skipTicks;
  loops++;
}

Questo non tiene conto di come setTimeout derive alle alte frequenze. Questo porterà anche a cose che ottengono fuori sincrono e diventando nervosi. JavaScript andrà alla deriva +/- 18 ms per secondo.

var start, tick = 0;
var f = function() {
    if (!start) start = new Date().getTime();
    var now = new Date().getTime();
    if (now < start + tick*1000) {
        setTimeout(f, 0);
    } else {
        tick++;
        var diff = now - start;
        var drift = diff % 1000;
        $('<li>').text(drift + "ms").appendTo('#results');
        setTimeout(f, 990);
    }
};

setTimeout(f, 990);

Ora consente di mettere tutto questo in un esempio di lavoro. Noi vogliamo iniettare il nostro ciclo di gioco in circuito di rendering gestito da parte di WebKit. Questo aiuterà appianare la grafica resi. Vogliamo anche di dividere le funzioni di disegno e di aggiornamento. Ciò aggiornerà gli oggetti nella nostra scena di rendering prima di calcolare quando il fotogramma successivo deve essere disegnato. Il ciclo di gioco dovrebbe anche saltare fotogrammi pareggio se l'aggiornamento porta a lungo.

  

index.html

<html>
    <head>
        <!--load scripts--> 
    </head>
    <!-- 
        render canvas into body, alternative you can use div, but disable 
        right click and hide cursor on parent div
    -->
    <body oncontextmenu="return false" style="overflow:hidden;cursor:none;-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;">
        <script type="text/javascript" charset="utf-8">
            Game.initialize();
            window.onEachFrame(Game.run);
        </script>
    </body>
</html>
  

Game.js

var Game = {};

Game.fps = 60;
Game.maxFrameSkip = 10;
Game.skipTicks = 1000 / Game.fps;

Game.initialize = function() {
    this.entities = [];
    this.viewport = document.body;

    this.input = new Input();

    this.debug = new Debug();
    this.debug.initialize(this.viewport);

    this.screen = new Screen();
    this.screen.initialize(this.viewport);
    this.screen.setWorld(new World());
};

Game.update = function(tick) {
    Game.tick = tick;
    this.input.update();
    this.debug.update();
    this.screen.update();
};

Game.draw = function() {
    this.debug.draw();
    this.screen.clear();
    this.screen.draw();
};

Game.pause = function() {
    this.paused = (this.paused) ? false : true;
};

/*
 * Runs the actual loop inside browser
 */
Game.run = (function() {
    var loops = 0;
    var nextGameTick = (new Date).getTime();
    var startTime = (new Date).getTime();
    return function() {
        loops = 0;
        while (!Game.paused && (new Date).getTime() > nextGameTick && loops < Game.maxFrameSkip) {
            Game.update(nextGameTick - startTime);
            nextGameTick += Game.skipTicks;
            loops++;
        }
        Game.draw();
    };
})();

(function() {
    var onEachFrame;
    if (window.requestAnimationFrame) {
       onEachFrame = function(cb) {
          var _cb = function() {
                cb();
             requestAnimationFrame(_cb);
          };
          _cb();
       };
    } else if (window.webkitRequestAnimationFrame) {
       onEachFrame = function(cb) {
          var _cb = function() {
             cb();
             webkitRequestAnimationFrame(_cb);
          };
          _cb();
       };
    } else if (window.mozRequestAnimationFrame) {
        onEachFrame = function(cb) {
            var _cb = function() {
                cb();
                mozRequestAnimationFrame(_cb);
            };
            _cb();
        };
    } else {
        onEachFrame = function(cb) {
            setInterval(cb, Game.skipTicks);
        };
    }

    window.onEachFrame = onEachFrame;
})();
  

Anche Ulteriori informazioni

Si può trovare un esempio di lavoro completa, e tutto il codice qui. Ho convertire questa risposta in uno scaricabile framework javascript è possibile costruire i vostri giochi fuori da.

https://code.google.com/p/twod-js/

requestAnimationFrame è una grande alternativa disponibile nella maggior parte dei browser ora. Fa quello che stai facendo con setInterval, ma in un cotto in modo. Probabilmente la cosa più bella è che funziona solo mentre la vostra scheda è focalizzata. Questo potrebbe essere un motivo per non da utilizzare se si desidera che le cose per l'esecuzione in background, ma spesso (soprattutto per rendere i loop che solo importa quando vede) è grande per non essere utilizzando le risorse quando la scheda non è attiva.

L'uso è piuttosto semplice:

function gameLoop(){
  window.requestAnimationFrame(gameLoop);
  Game.update();
}

Odio scrivere un commento sul vecchie discussioni, ma questo è un buon risultato su Google per "loop javascript gioco" in modo che davvero deve includere requestAnimationFrame.

Pollyfill per i vecchi browser copiati da paulirish :

(function() {
    var lastTime = 0;
    var vendors = ['ms', 'moz', 'webkit', 'o'];
    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
        window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] 
                                   || window[vendors[x]+'CancelRequestAnimationFrame'];
    }

    if (!window.requestAnimationFrame)
        window.requestAnimationFrame = function(callback, element) {
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0, 16 - (currTime - lastTime));
            var id = window.setTimeout(function() { callback(currTime + timeToCall); }, 
              timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        };

    if (!window.cancelAnimationFrame)
        window.cancelAnimationFrame = function(id) {
            clearTimeout(id);
        };
}());

punte di spiegazione e di utilizzo più profondi su creativeJS

Sì. Si vuole setInterval :

function myMainLoop () {
  // do stuff...
}
setInterval(myMainLoop, 30);

sarebbe questo fare?

setInterval(updateGameState, 1000 / 25);

Dove 25 è il vostro FPS desiderato. Si potrebbe anche mettere lì la quantità di millisecondi tra i fotogrammi, che a 25 fps sarebbe 40ms (1000/25 = 40).

Molte di queste risposte sono obsoleti e non ottimale. Il metodo consigliato per farlo ora sta usando requestAnimationFrame.

Ad esempio:

let previousTime = 0.0;

const loop = time => {
  // Compute the delta-time against the previous time
  const dt = time - previousTime;

  // Update the previous time
  previousTime = time;

  // Update your game
  update(dt);

  // Render your game
  render();

  // Repeat
  window.requestAnimationFrame(loop);
};

// Launch
window.requestAnimationFrame(time => {
  previousTime = time;
  loop(time);
});
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top