Skip to main content

JavaScript ES6 Game Loop Design Pattern

Get Started

This is just a short overview how to setup a very simple game loop with ES6 (JavaScript) using classes.

The following code sections are pretty easy to understand

Note that in many cases you need to use ES6's arrow operator => to make sure, you are accessing the correct this. Otherwise you will often get the error "this.method is not a function". That happens because when accessing this from anonymous methods, this points to the object of the anonymous method, not the object your calling it from.

In the HTML snippet, we set up a simple X3D scene with a ground and a small bar.

In the JavaScript main.js we create a game object. In Game.js the constructor sets up the game object and initializes the game loop to be triggered every 10 ms. We keep track of the pressed buttons (WASD) with booleans and move the bar accordingly.

This is what you will see, you can move the bar around with the WASD keys.



Have fun :)

PS: To develop this into a real game, have a look at the tutorial at MDN Developers, which is for 2D games with canvas, but much of it can be applied to our system as well: Tutorial

HTML Base Project


Here is the HTML frame:


<!doctype html>
<html>
  <!-- ......................................................................... HEAD -->
  <head>
    <title>LinuVerse Simple Game Loop Example</title>
    <meta charset="utf-8" />
    <script
      type='text/javascript'
      src='http://www.x3dom.org/download/x3dom.js'></script>
    <link
      rel='stylesheet'
      type='text/css'
      href='http://www.x3dom.org/download/x3dom.css'></link>
  </head>
  <!-- ......................................................................... BODY -->
  <body>
    <h1>LinuVerse Simple Game Loop Example</h1>
    <!-- ....................................................................... x3d -->
    <x3d width="800px" height="600px">
      <scene>
        <Viewpoint position="0,5,20" orientation="1,0,0,-.2"></Viewpoint>
        
        <!-- Scene ......................................................... -->
        <!-- Bar -->
        <transform id="bar" translation="0 -3 0">
          <shape>
            <appearance>
              <material diffuseColor=".9 .9 .9" />
            </appearance>
            <box size="5 1 1" />
          </shape>
        </transform>

        <!-- Scene ground -->
        <transform translation="0 -4 0">
          <shape>
            <appearance>
              <material diffuseColor=".8 .8 .8" />
            </appearance>
            <box size="20 1 20" />
          </shape>
        </transform>
      </scene>
    </x3d>

    <!-- ....................................................................... SCRIPTS -->
    <script type='text/javascript' src='Game.js'></script>
    <script type='text/javascript' src='main.js'></script>
    <script>
      main();
    </script>
  </body>
</html>

JavaScript Code


The Main JavaScript-File:
var game;

function main(args) {
  game = new Game();
}
And the Game Class:
'use strict'

class Game {

  constructor() {
    this.bar = document.getElementById('bar');
    this.barPos = [0,-3,0];

    this.upKeyPressed = false;
    this.downKeyPressed = false;
    this.leftKeyPressed = false;
    this.rightKeyPressed = false;

    document.addEventListener('keydown', event => this.onKeyDown(event));
    document.addEventListener('keyup', event => this.onKeyUp(event));

    setInterval(() => this.render(), 10);
  }

  /**
   * Main Render Cycle
   */
  render() {
    this.moveBar();
  }

  moveBar() {
    if(this.upKeyPressed){
      this.barPos[2] -= .1;
    }
    if(this.downKeyPressed){
      this.barPos[2] += .1;
    }
    if(this.leftKeyPressed){
      this.barPos[0] -= .1;
    }
    if(this.rightKeyPressed){
      this.barPos[0] += .1;
    }
    this.bar.setAttribute('translation', this.barPos);
  }

  onKeyDown(event) {
    switch(event.keyCode) {
      case 87: this.upKeyPressed = true; break;
      case 83: this.downKeyPressed = true; break;
      case 65: this.leftKeyPressed = true; break;
      default: this.rightKeyPressed = true; break;
    }
  }

  onKeyUp(event) {
    switch(event.keyCode) {
      case 87: this.upKeyPressed = false; break;
      case 83: this.downKeyPressed = false; break;
      case 65: this.leftKeyPressed = false; break;
      default: this.rightKeyPressed = false; break;
    }
  }
}

Comments

Popular posts from this blog

Newer Super Mario Bros. Wii unter Linux mit Patchimage

Super Mario Bros. ist ein Klassiker. Dazu muss sicher nicht viel gesagt werden. Doch auch die neuesten Ableger der Serie wie New Super Mario Bros. Wii erfreuen sich großer Beliebtheit. Eine Weile lang machte ein Spiel namens Newer Super Mario Bros. Wii großes Aufsehen. Die Forsetzung zum Original von Nintendo wurde inoffiziell vom Newer-Team in 3-jähriger Entwicklerarbeit erstellt, hat 128 neue Level und überzeugt durch die außerordentliche Qualität des Hacks. An dieser Stelle sei gesagt, dass ihr das Spiel nur legal spielen könnt, wenn ihr New Super Mario Bros. Wii selbst besitzt. Falls dies nicht der Fall ist, kauft es bitte zuerst. Illegal heruntergeladene Spiele werden nicht unterstützt und von mir ausdrücklich nicht befürwortet . (Eine Windows-Anleitung findet ihr hier: WiiDatabase .de) Also, los gehts: Dumpt euer originales New Super Mario Bros. Wii z.B. mit USB Loader GX (auf + klicken) kopiert den Ordner New Super Mario Bros. Wii [SMNP01] auf euren PC Nun ...

Ubuntu 16.04 USB-Stick - "Das Ziel ist schreibgeschützt" lösen

Es gibt Dinge, die dürfen in einem nutzerfreundlichen Betriebssystem einfach nicht passieren. Vor allem dürfen Sie aber nicht monatelang bestehen bleiben. Mit Ubuntu 16.04 kann ich Freunden und Bekannten Ubuntu einfach nicht mehr empfehlen, wenn selbst ich an einfachsten Aufgaben scheitere. Gemeint ist hier das Kopieren von Dateien auf USB-Sticks. Trotz jahrelanger Ubuntu/Linux-Erfahrung gelang es mir erst nach gründlicher Recherche das Problem zu beheben. Ein Laie hat hier keine Chance. Damit ihr nicht lange suchen müsst, hier das Problem samt Lösung: Problem Datei oder Ordner auf Fat32-USB-Stick kopieren oder anlegen schlägt fehl mit der Meldung "Das Ziel ist schreibgeschützt". Lösung das Paket fuse-posixovl installieren und Ubuntu neu starten sudo apt-get install fuse-posixovl Viel Erfolg

[Unreal Engine][C++] How to create a simple trigger actor

[Unreal Engine][C++] How to create a simple trigger actor A Simple Trigger Volume in C++ Used Unreal Engine Version: 4.22 This is the first post of a small series of Unreal Engine C++ Tutorials. Keep in mind, that Unreal’s API changes rapidly and often. I still hope, this may be of some use to others. Coming from Unity, programming in C++ for Unreal is rather painful. I hope to give you some assistance and make life a little bit easier. Whay, would you say, should we make our own trigger actor? There is ATriggerVolume , right? Yes, there is, but inheriting from it is difficult and rather undocumented. I tried and failed. Yes, we have to give up some of ATriggerVolume 's functionality, but we learn a lot and at least we know exactly what it’s doing. First, we’ll create a new C++ class, inheriting from Actor , called SimpleTriggerVolume . Let’s add a protected property to hold a reference to our trigger component: /** Shape of the trigger volume componen...