Javascript &

cross-platform video games

Cross-platform

Video games

Desktop

mainly 2D games

Mobile phones and tablets

Video game consoles

Browsers games

About me

Florian Rival 

Architect-Developer @

Developer of

and

@Florianrival

github.com/4ian

Lil BUB

Game engines

HTML5 game engines

Use HTML5 <canvas> element

and/or webGL if available

closed-source

See all on html5gameengine.com

Used for Lil BUB's game

WebView

HTML5 on mobile

Cordova

  • UIWebView
  • Android browser/Chrome

Cordova with new webviews

  • WKWebView
  • Crosswalk = recent Chrome

Native app

Embedded browser

+

Custom canvas on mobile

Cocoon.js

  • Canvas+
  • WebView+

iOS only

closed-source

Ejecta

  • Audio & Canvas
  • JavascriptCore

cloud compiler

Native app

JS engine

+

Canvas compatible API

+

Electron

HTML5 on desktop

Node

Chromium

(V8)

+

  • Runs on Windows, macOS, all major Linux distro
  • Installers/packagers available to distribute your game
  • supports code signing (stores)
  • automatic updates
Used for Lil BUB's game

Hybrid game engines

Native rendering

JS engine

+

  • SpiderMonkey JS engine is embedded
Used for Lil BUB's game
  • Runs on iOS, Android, Windows, macOS, linux

AAA game engines

C#

C++

C++ cross-compiled to JS

Consoles : Wii U

WebKit

 +

Specific JS APIs

  • HTML5 should be able to run with few changes!
  • Registration needed
  • Custom dev Wii U needed ($2000)

Consoles : Xbox One

What about audio?

HTML5 games

HTML5 audio, WebAudio API

Hybrid/Native games

Most engines have a

built-in audio support

Used for Lil BUB's game

Javascript performance for games

Rendering 

Logic

Memory usage

Discard objects, use simple physics models, split heavy computations if possible in more than one frame.

Rendering

Logic

Avoid rendering objects far from the player (culling) 

In general, minimize objects and textures

Avoid creating too much objects, release unused ones/too far from player 

Memory usage

Rendering 

☑️ WebGL

  • Desktop :

☑️ WebGL available in (recent) webviews

  • Android :
  • iOS :

☑️ WebGL in webviews since iOS 8

🤔 Xbox - Not sure

  • Consoles :

☑️ OpenGL ES used by other engines 

☑️ OpenGL ES used by Cocoon.js, Cocos2d-JS...

😢 Wii U - Canvas only

JS Performance

☑️ JIT compilation

  • Desktop :

☑️ JIT compilation

  • Android :

❌ no JIT allowed by iOS for other engines

  • iOS :

☑️ JIT in Safari and WKWebView

😱 Android devices CPUs are slow

🤔 Not sure

  • Consoles :

https://meta.discourse.org/t/the-state-of-javascript-on-android-in-2015-is-poor/33889

https://www.scirra.com/blog/174/boosting-ios-performance-with-wkwebview

The garbage collector

😱

😲

😱

Avoiding garbage

function updatePlayerPosition() {
  var mousePos = getMousePosition(); 

  var test = function(obj) {  // 😱
    return obj.isCollidingWithPlayer() && obj.isHarmful();
  }

  var collidingEnemies = allEnemies.filter(test); // 😱
  if (collidingEnemies.length) {
    player.lastCollision = {enemy: collidingEnemies[0]} // 😱
  }
}

function getMousePosition() {
  return [mouseApi.getX(), mouseApi.getY()]; // 😱
}

Each frame, 1 function, 2 arrays and 1 object are added to garbage

Avoiding garbage

Use static objects, arrays, avoid functions returning new objects

function updatePlayerPosition() {
  var mousePos = getMousePosition(); 

  updatePlayerPosition.collidingEnemies = updatePlayerPosition.collidingEnemies 
    || []; // 0 garbage 😙
  updatePlayerPosition.collidingEnemies.length = 0;

  filter(allEnemies, collidingEnemies, Enemy.collisionTest); // 0 garbage? 🤔
  if (collidingEnemies.length) {
    player.lastCollision.enemy = collidingEnemies[0]; // 0 garbage 😙
  }
}

function getMousePosition() { // 0 garbage 😙
  getMousePosition.mousePos = getMousePosition.mousePos || [0, 0]; 
  getMousePosition.mousePos[0] = mouseApi.getX();
  getMousePosition.mousePos[1] = mouseApi.getY();

  return getMousePosition.mousePos;
}

Avoiding garbage

function filter(array, result, func) {
  for(var i = 0;i < array.length; i++) {
    if (func(array[i])) {
      if (result.length <= k) result.push(array[i]);
      else result[k] = array[i];

      k++;
    }
  }

  result.length = k;
}

https://www.scirra.com/blog/76/how-to-write-low-garbage-real-time-javascript

Avoiding garbage

Use objects pool

function launchBullet() {
  var bullet = Bullets.getNewBullet();
  bullet.setSpeed(500);
}

function onBulletCollision(bullet, enemy) {
  Bullets.recycle(bullet);
}

Bullets.prototype.recycle = function(bullet) {
  Bullets.pool.push(bullet);
}

Bullets.prototype.getNewBullet = function(bullet) {
  if (Bullets.pool.length) {
    return Bullets.pool.pop();
  } else {
    return new Bullet();
  }
}

tiny.cc/bub-game

@Florianrival

Thanks!

github.com/4ian/GD

Game [engine] 

architecture

Scene graph

Scene

Layer/View

Layer/View

DisplayObject

Text

Sprite

Particles

Sprite

SceneStack/Director

Rendered objects are stored in a graph

Lower levels rendering engines (SDL, OpenGL, WebGL, Canvas) don't have graphs, only primitives

Game loop

Manage inputs

Update world

Update physics

Render

Update time

dt = time elapsed since last frame

fps = 1 / dt

{

check collisions, move objects, update scores (business logic)...

{

Physics

You need to map your entities to the physics engine bodies 

World

Joint

RigidBody

Fixture

RigidBody

Fixture

Fixture

Forces can be applied on body

Callbacks can be attached for collisions

Collisions

  • Either use a physics engine
  • Roll your own logic:
  • Bounding boxes (very simple collision detection)
  • Hitboxes made with polygons (use an algorithm like SAT)
  • If necessary, divide the space
    to avoid collision checks
    (spatial hashing, quadtree)
Made with Slides.com