paradise.js/app/scene.js

97 lines
2.5 KiB
JavaScript

(function() {
'use strict';
const _ = require('lodash');
let Scene = function(scene, canvas) {
/* scene definition from json */
this.scene = scene;
/* the html5 canvas object */
this.canvas = canvas;
};
/* draw one of the specified frames in this scene */
Scene.prototype.drawFrame = function(images) {
[].concat(images).forEach((image) => {
this.canvas.drawImage(image);
});
};
/* play this scene on the given canvas */
Scene.prototype.play = function() {
/* transform the scene roll definition given in the .json scene file
* into a flat array of simple ({ name, duration }) objects.
* this will deal with all the repeat: properties and multi level nesting */
let expand = (roll) => {
/* recursively expand repeats */
let expanded = roll.map((scene) => {
if (scene.hasOwnProperty('repeat')) {
let roll = [];
for (let i = 0; i < scene.repeat; i++) {
roll = roll.concat(scene.roll);
}
return expand(roll);
}
return scene;
});
return _.flattenDeep(expanded);
};
/* transform the expanded array into an array of functions that
* return promises and that should be called one after another.
* calling these functions will render the scene. */
let functionalize = (expanded) => {
let functionalized = expanded.map((frame) => {
return () => new Promise((resolve, reject) => {
this.drawFrame(frame.images);
setTimeout(() => {
return resolve();
}, frame.duration);
});
});
return functionalized;
};
/* expand the scene definition (get a flat array of simple { name, duration }
* objects */
let expanded = expand(this.scene.roll);
/* transform the array obtained into an array of functions */
let functionalized = functionalize(expanded);
/* call the functions in the array obtained one after the other after each
* returned promise resolves */
let promise = functionalized[0]();
for (let i = 1; i < functionalized.length; i++) {
promise = promise.then(functionalized[i]);
}
return promise;
};
module.exports = Scene;
})();