Desktop

Mobile phones and tablets

Video game consoles

Browsers games

Cross-platform

mainly 2D games

Video 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

  • JS output is quite heavy (not a problem when packaged, but on the web)

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 : Switch

😰

Consoles : Xbox One

UWP

  • Docs on https://docs.microsoft.com/en-us/windows/uwp
  • ID@Xbox approval needed
  • Xbox Dev Mode to test your UWP game on your Xbox

IE ?

 +

Specific JS APIs

Consoles : PS4

😰

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

var collidingEnemies = allEnemies.filter(function() {/**/}); // 😱 😱

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();
  }
}

Large functions?

Avoid very large functions

Break them in small functions

Avoided 0.5 seconds lags in my game engine with this

ES6 (with Babel)?

Can potentially create hidden functions, and generate garbage

Be sure to inspect the generated code

tiny.cc/bub-game

@Florianrival

Thanks!

github.com/4ian

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