Desktop
Mobile phones and tablets
Video game consoles
Browsers games
mainly 2D games
Florian Rival
Architect-Developer @
Developer of
and
@Florianrival
github.com/4ian
Lil BUB
Use HTML5 <canvas> element
and/or webGL if available
closed-source
See all on html5gameengine.com
Used for Lil BUB's game
Cordova
Cordova with new webviews
=
Native app
Embedded browser
+
Cocoon.js
iOS only
closed-source
Ejecta
cloud compiler
=
Native app
JS engine
+
Canvas compatible API
+
=
Node
Chromium
(V8)
+
Used for Lil BUB's game
=
Native rendering
JS engine
+
Used for Lil BUB's game
C#
C++
=
C++ cross-compiled to JS
=
WebKit
+
Specific JS APIs
😰
=
IE ?
+
Specific JS APIs
😰
HTML5 audio, WebAudio API
Most engines have a
built-in audio support
Used for Lil BUB's game
Discard objects, use simple physics models, split heavy computations if possible in more than one frame.
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
☑️ WebGL
☑️ WebGL available in (recent) webviews
☑️ WebGL in webviews since iOS 8
🤔 Xbox - Not sure
☑️ OpenGL ES used by other engines
☑️ OpenGL ES used by Cocoon.js, Cocos2d-JS...
😢 Wii U - Canvas only
☑️ JIT compilation
☑️ JIT compilation
❌ no JIT allowed by iOS for other engines
☑️ JIT in Safari and WKWebView
😱 Android devices CPUs are slow
🤔 Not sure
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
😱
😲
😱
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
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;
}
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() {/**/}); // 😱 😱
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
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
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)...
{
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