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)
[GameCamp France] Cross-platform games creation with Javascript
By Florian Rival
[GameCamp France] Cross-platform games creation with Javascript
Development of cross-platform games (desktop, mobile, web, consoles) with Javascript
- 5,169