diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b7dab5e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+node_modules
+build
\ No newline at end of file
diff --git a/.jshintrc b/.jshintrc
new file mode 100644
index 0000000..0b98632
--- /dev/null
+++ b/.jshintrc
@@ -0,0 +1,4 @@
+{
+ "indent": 4,
+ "esversion": 6
+}
diff --git a/README.md b/README.md
index 5e36cdc..5af5cd8 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,31 @@
# paradise.js
-HTML canvas implementation of Paradise Café
-Demo on : https://zbr.deadbsd.org/~falso/paradise/
+HTML canvas implementation of Paradise Café using webpack as build system.
+
+Demo at [https://ticklemynausea.net/~mario/paradise/](https://ticklemynausea.net/~mario/paradise/).
+
+
+### Install dependencies
+```
+npm install
+```
+
+### Building
+
+```
+npm run build
+```
+
+webpack will build the app to build/
+
+### Running as dev server
+```
+npm run dev
+```
+
+webpack-dev-server will serve a the app from memory, watching for changes in the source
+and doing hot reload. fancy.
+
+## Credits
+
+All glory to [falsovsky](https://github.com/falsovsky/) for the original implementation (https://github.com/falsovsky/paradise.js) and especially for [the complete ParadiseCafé disassembly with annotations](https://zbr.deadbsd.org/~falso/p/ParadiseCafe/).
\ No newline at end of file
diff --git a/app/canvas.js b/app/canvas.js
new file mode 100644
index 0000000..e76b296
--- /dev/null
+++ b/app/canvas.js
@@ -0,0 +1,67 @@
+(function() {
+
+ 'use strict';
+
+ let Canvas = function(container, width, height, scale) {
+
+ /* html element that the canvas will be created in */
+ this.container = container;
+
+ /* canvas width */
+ this.width = width;
+
+ /* canvas height */
+ this.height = height;
+
+ /* canvas scale */
+ this.scale = scale || 1;
+
+ /* container element - set properties */
+ container.style.width = (this.width * this.scale) + 'px';
+ container.style.height = (this.height * this.scale) + 'px';
+
+ /* canvas element - create and set properties */
+ this.canvas = document.createElement('canvas');
+ this.canvas.setAttribute('width', this.width * this.scale);
+ this.canvas.setAttribute('height', this.height * this.scale);
+ this.canvas.setAttribute('id', 'canvas');
+
+ /* insert in dom */
+ this.container.appendChild(this.canvas);
+
+ /* get drawing interface */
+ this.context = this.canvas.getContext("2d");
+
+ /* load images dynamically from all .png files present in '../assets/images'.
+ * this function implements a reducer that reduces all files loaded to a
+ * single object with the image filename name minus extension as key
+ * and the require()d file as value */
+ const requireImages = function (requireContext) {
+ return requireContext.keys().reduce(function(accumulator, filename) {
+ let framename = filename.match(/\.\/(\S+)\.png$/)[1];
+ accumulator[framename] = requireContext(filename);
+ return accumulator;
+ }, {});
+ };
+ this.images = requireImages(require.context('../assets/images', true, /\.png$/));
+
+ };
+
+ /* draw the image specified as argument on this canvas */
+ Canvas.prototype.drawImage = function(name) {
+
+ if (!(name in this.images)) {
+ throw new Error('image ' + name + ' unknown');
+ }
+
+ var image = new Image();
+ image.onload = () => {
+ this.context.drawImage(image, 0, 0, image.width, image.height, 0, 0, this.canvas.width, this.canvas.height);
+ };
+ image.src = this.images[name];
+
+ };
+
+ module.exports = Canvas;
+
+})();
\ No newline at end of file
diff --git a/app/director.js b/app/director.js
new file mode 100644
index 0000000..9a95911
--- /dev/null
+++ b/app/director.js
@@ -0,0 +1,134 @@
+(function() {
+
+ 'use strict';
+
+ const mapValues = require('lodash.mapvalues');
+ const Scene = require('./scene');
+
+ let Director = function(canvas) {
+
+ /* html5 canvas */
+ this.canvas = canvas;
+
+ /* load scenes dynamically from all .json files present in '../assets/scenes'.
+ * this function implements a reducer that reduces all files loaded to a
+ * single object with the scene filename minus extension as key and
+ * the require()d file as value */
+ const requireScenes = function (requireContext) {
+ return requireContext.keys().reduce(function(accumulator, filename) {
+ let framename = filename.match(/\.\/(\S+)\.json$/)[1];
+ accumulator[framename] = requireContext(filename);
+ return accumulator;
+ }, {});
+ };
+ let scenes = requireScenes(require.context('../assets/scenes', true, /\.json$/));
+
+ /* map object with scene definitions obtained above into object
+ * containing Scene objects with scene name as a key */
+ this.scenes = mapValues(scenes, (value, key) => {
+ return new Scene(value, this.canvas);
+ });
+
+ };
+
+ /* begins the game (actually runs the whole game) */
+ /* @TODO lol everything is implemented here, if this needs to grow it will become ugly
+ * think about refactoring all the code in here later */
+ Director.prototype.begin = function() {
+
+ /* enable user input */
+ let enableUserInput = () => {
+
+ /* add event listeners */
+ window.addEventListener('keydown', keyListener, false);
+
+ /* LOL there is no forEach in DOM NodeList
+ * http://stackoverflow.com/questions/13433799/why-doesnt-nodelist-have-foreach */
+ Array.prototype.forEach.call(document.getElementsByClassName('user-action'), (element) => {
+
+ /* add event listeners */
+ element.addEventListener('mouseup', mouseListener, false);
+ element.addEventListener('touchup', touchListener, false);
+
+ });
+
+ /* hide user input area */
+ document.getElementById('ul-teclas').className = '';
+
+ };
+
+ /* disable user input */
+ let disableUserInput = () => {
+
+ /* add event listeners */
+ window.removeEventListener('keydown', keyListener, false);
+
+ /* see above */
+ Array.prototype.forEach.call(document.getElementsByClassName('user-action'), (element) => {
+
+ /* remove event listeners */
+ element.removeEventListener('mouseup', mouseListener, false);
+ element.removeEventListener('touchup', touchListener, false);
+
+ });
+
+ /* hide user input area */
+ document.getElementById('ul-teclas').className = 'hidden';
+
+ };
+
+ /* consequence of user action (key pressed) */
+ let choice = (scene) => {
+
+ disableUserInput();
+
+ /* play the selected choice screen */
+ this.scenes['choice_' + scene].play()
+ /* then play the chosen scene */
+ .then(() => this.scenes[scene].play())
+ /* then play the reinaldo scene */
+ .then(() => this.scenes.reinaldo.play())
+ /* then start all over again */
+ .then(main);
+ };
+
+ /* keydown window event listener */
+ let keyListener = function(event) {
+
+ let actions = {
+ 67: 'anal',
+ 70: 'vaginal',
+ 66: 'oral'
+ };
+
+ let action = actions[event.keyCode];
+
+ if (action) {
+ choice(action);
+ }
+
+ };
+
+ let mouseListener = function(event) {
+ let action = this.getAttribute('data-action');
+ choice(action);
+ };
+
+ let touchListener = function(event) {
+ let action = this.getAttribute('data-action');
+ choice(action);
+ };
+
+ /* the game starts by calling this */
+ let main = () => {
+ return this.scenes.choice.play()
+ .then(enableUserInput);
+ };
+
+ return main();
+
+ };
+
+ module.exports = Director;
+
+})();
\ No newline at end of file
diff --git a/app/index.js b/app/index.js
new file mode 100644
index 0000000..0eee2b9
--- /dev/null
+++ b/app/index.js
@@ -0,0 +1,32 @@
+(function() {
+
+ 'use strict';
+
+ /* css stuff */
+ require('../assets/style.scss');
+
+ /* load title image into title div because im using a stupid fucking
+ * plugin to generate index.html automagically and i dont know how
+ * pass content to the template */
+ const image = require('../assets/page/paradise.gif');
+ document.getElementById('img-title').src = image;
+
+ /* Canvas abstraction */
+ const Canvas = require('./canvas');
+
+ /* Game director */
+ const Director = require('./director');
+
+ /* create a canvas */
+ const scale = 1;
+ const width = 512;
+ const height = 272;
+ let canvas = new Canvas(document.getElementById("div-canvas"), width, height, scale);
+
+ /* create game director with this canvas */
+ let director = new Director(canvas);
+
+ /* start everything */
+ director.begin();
+
+})();
diff --git a/app/scene.js b/app/scene.js
new file mode 100644
index 0000000..eb1995c
--- /dev/null
+++ b/app/scene.js
@@ -0,0 +1,97 @@
+(function() {
+
+ 'use strict';
+
+ const flattenDeep = require('lodash.flattendeep');
+
+ 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;
+
+})();
\ No newline at end of file
diff --git a/anal_balloon_aaaa.png b/assets/images/anal_balloon_aaaa.png
old mode 100755
new mode 100644
similarity index 100%
rename from anal_balloon_aaaa.png
rename to assets/images/anal_balloon_aaaa.png
diff --git a/anal_balloon_clear.png b/assets/images/anal_balloon_clear.png
old mode 100755
new mode 100644
similarity index 100%
rename from anal_balloon_clear.png
rename to assets/images/anal_balloon_clear.png
diff --git a/anal_balloon_grosso.png b/assets/images/anal_balloon_grosso.png
old mode 100755
new mode 100644
similarity index 100%
rename from anal_balloon_grosso.png
rename to assets/images/anal_balloon_grosso.png
diff --git a/anal_base.png b/assets/images/anal_base.png
old mode 100755
new mode 100644
similarity index 100%
rename from anal_base.png
rename to assets/images/anal_base.png
diff --git a/anal_frame1.png b/assets/images/anal_frame1.png
old mode 100755
new mode 100644
similarity index 100%
rename from anal_frame1.png
rename to assets/images/anal_frame1.png
diff --git a/anal_frame2.png b/assets/images/anal_frame2.png
old mode 100755
new mode 100644
similarity index 100%
rename from anal_frame2.png
rename to assets/images/anal_frame2.png
diff --git a/balloon_anal.png b/assets/images/choice_balloon_anal.png
old mode 100755
new mode 100644
similarity index 100%
rename from balloon_anal.png
rename to assets/images/choice_balloon_anal.png
diff --git a/balloon_oral.png b/assets/images/choice_balloon_oral.png
old mode 100755
new mode 100644
similarity index 100%
rename from balloon_oral.png
rename to assets/images/choice_balloon_oral.png
diff --git a/balloon_choose.png b/assets/images/choice_balloon_queres.png
old mode 100755
new mode 100644
similarity index 100%
rename from balloon_choose.png
rename to assets/images/choice_balloon_queres.png
diff --git a/balloon_vaginal.png b/assets/images/choice_balloon_vaginal.png
old mode 100755
new mode 100644
similarity index 100%
rename from balloon_vaginal.png
rename to assets/images/choice_balloon_vaginal.png
diff --git a/hero.png b/assets/images/hero.png
old mode 100755
new mode 100644
similarity index 100%
rename from hero.png
rename to assets/images/hero.png
diff --git a/oral_balloon_chupa.png b/assets/images/oral_balloon_chupa.png
old mode 100755
new mode 100644
similarity index 100%
rename from oral_balloon_chupa.png
rename to assets/images/oral_balloon_chupa.png
diff --git a/oral_balloon_quebom.png b/assets/images/oral_balloon_quebom.png
old mode 100755
new mode 100644
similarity index 100%
rename from oral_balloon_quebom.png
rename to assets/images/oral_balloon_quebom.png
diff --git a/oral_base.png b/assets/images/oral_base.png
old mode 100755
new mode 100644
similarity index 100%
rename from oral_base.png
rename to assets/images/oral_base.png
diff --git a/oral_frame1.png b/assets/images/oral_frame1.png
old mode 100755
new mode 100644
similarity index 100%
rename from oral_frame1.png
rename to assets/images/oral_frame1.png
diff --git a/oral_frame2.png b/assets/images/oral_frame2.png
old mode 100755
new mode 100644
similarity index 100%
rename from oral_frame2.png
rename to assets/images/oral_frame2.png
diff --git a/reinaldo/r07.png b/assets/images/reinaldo.png
old mode 100755
new mode 100644
similarity index 100%
rename from reinaldo/r07.png
rename to assets/images/reinaldo.png
diff --git a/reinaldo/r12.png b/assets/images/reinaldo_balloon_caralhinho.png
old mode 100755
new mode 100644
similarity index 100%
rename from reinaldo/r12.png
rename to assets/images/reinaldo_balloon_caralhinho.png
diff --git a/reinaldo/r05.png b/assets/images/reinaldo_balloon_cu_cu.png
old mode 100755
new mode 100644
similarity index 100%
rename from reinaldo/r05.png
rename to assets/images/reinaldo_balloon_cu_cu.png
diff --git a/reinaldo/r03.png b/assets/images/reinaldo_balloon_ho_reinaldo.png
old mode 100755
new mode 100644
similarity index 100%
rename from reinaldo/r03.png
rename to assets/images/reinaldo_balloon_ho_reinaldo.png
diff --git a/reinaldo/r08.png b/assets/images/reinaldo_balloon_ja_vai_ver.png
old mode 100755
new mode 100644
similarity index 100%
rename from reinaldo/r08.png
rename to assets/images/reinaldo_balloon_ja_vai_ver.png
diff --git a/reinaldo/r06.png b/assets/images/reinaldo_balloon_nao_quer_pagar.png
old mode 100755
new mode 100644
similarity index 100%
rename from reinaldo/r06.png
rename to assets/images/reinaldo_balloon_nao_quer_pagar.png
diff --git a/reinaldo/r02.png b/assets/images/reinaldo_balloon_nao_tenho.png
old mode 100755
new mode 100644
similarity index 100%
rename from reinaldo/r02.png
rename to assets/images/reinaldo_balloon_nao_tenho.png
diff --git a/reinaldo/r13.png b/assets/images/reinaldo_balloon_o_que_foi.png
old mode 100755
new mode 100644
similarity index 100%
rename from reinaldo/r13.png
rename to assets/images/reinaldo_balloon_o_que_foi.png
diff --git a/reinaldo/r01.png b/assets/images/reinaldo_balloon_sao_1000.png
old mode 100755
new mode 100644
similarity index 100%
rename from reinaldo/r01.png
rename to assets/images/reinaldo_balloon_sao_1000.png
diff --git a/reinaldo/r01_2.png b/assets/images/reinaldo_balloon_sao_2000.png
old mode 100755
new mode 100644
similarity index 100%
rename from reinaldo/r01_2.png
rename to assets/images/reinaldo_balloon_sao_2000.png
diff --git a/reinaldo/r01_3.png b/assets/images/reinaldo_balloon_sao_3000.png
old mode 100755
new mode 100644
similarity index 100%
rename from reinaldo/r01_3.png
rename to assets/images/reinaldo_balloon_sao_3000.png
diff --git a/reinaldo/r04.png b/assets/images/reinaldo_cabeca.png
old mode 100755
new mode 100644
similarity index 100%
rename from reinaldo/r04.png
rename to assets/images/reinaldo_cabeca.png
diff --git a/reinaldo/r09.png b/assets/images/reinaldo_violar_base.png
old mode 100755
new mode 100644
similarity index 100%
rename from reinaldo/r09.png
rename to assets/images/reinaldo_violar_base.png
diff --git a/reinaldo/r10.png b/assets/images/reinaldo_violar_frame1.png
old mode 100755
new mode 100644
similarity index 100%
rename from reinaldo/r10.png
rename to assets/images/reinaldo_violar_frame1.png
diff --git a/reinaldo/r11.png b/assets/images/reinaldo_violar_frame2.png
old mode 100755
new mode 100644
similarity index 100%
rename from reinaldo/r11.png
rename to assets/images/reinaldo_violar_frame2.png
diff --git a/room.png b/assets/images/room.png
old mode 100755
new mode 100644
similarity index 100%
rename from room.png
rename to assets/images/room.png
diff --git a/vaginal_balloon_venho.png b/assets/images/vaginal_balloon_venho.png
old mode 100755
new mode 100644
similarity index 100%
rename from vaginal_balloon_venho.png
rename to assets/images/vaginal_balloon_venho.png
diff --git a/vaginal_base.png b/assets/images/vaginal_base.png
old mode 100755
new mode 100644
similarity index 100%
rename from vaginal_base.png
rename to assets/images/vaginal_base.png
diff --git a/vaginal_frame1.png b/assets/images/vaginal_frame1.png
old mode 100755
new mode 100644
similarity index 100%
rename from vaginal_frame1.png
rename to assets/images/vaginal_frame1.png
diff --git a/vaginal_frame2.png b/assets/images/vaginal_frame2.png
old mode 100755
new mode 100644
similarity index 100%
rename from vaginal_frame2.png
rename to assets/images/vaginal_frame2.png
diff --git a/whore.png b/assets/images/whore.png
old mode 100755
new mode 100644
similarity index 100%
rename from whore.png
rename to assets/images/whore.png
diff --git a/assets/index.hbs b/assets/index.hbs
new file mode 100644
index 0000000..bc42cde
--- /dev/null
+++ b/assets/index.hbs
@@ -0,0 +1,23 @@
+
+
+
+ Paradise Café
+
+
+
+
+
+
+
+
+
+
+
+
c
anal
+
f
vaginal
+
b
oral
+
+
+
+
+
\ No newline at end of file
diff --git a/paradise.gif b/assets/page/paradise.gif
old mode 100755
new mode 100644
similarity index 100%
rename from paradise.gif
rename to assets/page/paradise.gif
diff --git a/assets/scenes/anal.json b/assets/scenes/anal.json
new file mode 100644
index 0000000..a43c554
--- /dev/null
+++ b/assets/scenes/anal.json
@@ -0,0 +1,92 @@
+{
+ "roll": [
+ {
+ "images": [
+ "room",
+ "anal_base",
+ "anal_frame1"
+ ],
+ "duration": 750
+ },
+ {
+ "repeat": 10,
+ "roll": [
+ {
+ "images": "anal_frame1",
+ "duration": 150
+ },
+ {
+ "images": "anal_frame2",
+ "duration": 150
+ }
+ ]
+ },
+ {
+ "images": "anal_balloon_grosso"
+ },
+ {
+ "repeat": 5,
+ "roll": [
+ {
+ "images": "anal_frame1",
+ "duration": 150
+ },
+ {
+ "images": "anal_frame2",
+ "duration": 250
+ }
+ ]
+ },
+ {
+ "images": "anal_balloon_clear"
+ },
+ {
+ "repeat": 5,
+ "roll": [
+ {
+ "images": "anal_frame1",
+ "duration": 150
+ },
+ {
+ "images": "anal_frame2",
+ "duration": 150
+ }
+ ]
+ },
+ {
+ "images": "anal_balloon_aaaa"
+ },
+ {
+ "repeat": 5,
+ "roll": [
+ {
+ "images": "anal_frame1",
+ "duration": 150
+ },
+ {
+ "images": "anal_frame2",
+ "duration": 150
+ }
+ ]
+ },
+ {
+ "images": [
+ "anal_balloon_grosso",
+ "anal_balloon_aaaa"
+ ]
+ },
+ {
+ "repeat": 5,
+ "roll": [
+ {
+ "images": "anal_frame1",
+ "duration": 100
+ },
+ {
+ "images": "anal_frame2",
+ "duration": 100
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/assets/scenes/choice.json b/assets/scenes/choice.json
new file mode 100644
index 0000000..2f2687c
--- /dev/null
+++ b/assets/scenes/choice.json
@@ -0,0 +1,12 @@
+{
+ "roll": [
+ {
+ "images": [
+ "room",
+ "whore",
+ "hero",
+ "choice_balloon_queres"
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/assets/scenes/choice_anal.json b/assets/scenes/choice_anal.json
new file mode 100644
index 0000000..18214cc
--- /dev/null
+++ b/assets/scenes/choice_anal.json
@@ -0,0 +1,8 @@
+{
+ "roll": [
+ {
+ "images": "choice_balloon_anal",
+ "duration": 1500
+ }
+ ]
+}
\ No newline at end of file
diff --git a/assets/scenes/choice_oral.json b/assets/scenes/choice_oral.json
new file mode 100644
index 0000000..ee7a98e
--- /dev/null
+++ b/assets/scenes/choice_oral.json
@@ -0,0 +1,8 @@
+{
+ "roll": [
+ {
+ "images": "choice_balloon_oral",
+ "duration": 1500
+ }
+ ]
+}
\ No newline at end of file
diff --git a/assets/scenes/choice_vaginal.json b/assets/scenes/choice_vaginal.json
new file mode 100644
index 0000000..65d85d3
--- /dev/null
+++ b/assets/scenes/choice_vaginal.json
@@ -0,0 +1,8 @@
+{
+ "roll": [
+ {
+ "images": "choice_balloon_vaginal",
+ "duration": 1500
+ }
+ ]
+}
\ No newline at end of file
diff --git a/assets/scenes/oral.json b/assets/scenes/oral.json
new file mode 100644
index 0000000..111de86
--- /dev/null
+++ b/assets/scenes/oral.json
@@ -0,0 +1,41 @@
+{
+ "roll": [
+ {
+ "images": [
+ "room",
+ "oral_base",
+ "oral_frame1"
+ ],
+ "duration": 750
+ },
+ {
+ "repeat": 20,
+ "roll": [
+ {
+ "images": "oral_frame1",
+ "duration": 250
+ },
+ {
+ "images": "oral_frame2",
+ "duration": 250
+ }
+ ]
+ },
+ {
+ "images": "oral_balloon_chupa"
+ },
+ {
+ "repeat": 10,
+ "roll": [
+ {
+ "images": "oral_frame1",
+ "duration": 150
+ },
+ {
+ "images": "oral_frame2",
+ "duration": 150
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/assets/scenes/reinaldo.json b/assets/scenes/reinaldo.json
new file mode 100644
index 0000000..7ad3037
--- /dev/null
+++ b/assets/scenes/reinaldo.json
@@ -0,0 +1,153 @@
+{
+ "roll": [
+ {
+ "images": [
+ "room",
+ "whore",
+ "hero"
+ ],
+ "duration": 1500
+ },
+ {
+ "images": "reinaldo_balloon_sao_1000",
+ "duration": 1500
+ },
+ {
+ "images": [
+ "room",
+ "whore",
+ "hero"
+ ],
+ "duration": 1500
+ },
+ {
+ "images": "reinaldo_balloon_nao_tenho",
+ "duration": 1500
+ },
+ {
+ "images": [
+ "room",
+ "whore",
+ "hero"
+ ],
+ "duration": 1500
+ },
+ {
+ "images": "reinaldo_balloon_ho_reinaldo",
+ "duration": 1500
+ },
+ {
+ "images": [
+ "room",
+ "whore",
+ "hero"
+ ],
+ "duration": 1500
+ },
+ {
+ "images": "reinaldo_cabeca",
+ "duration": 250
+ },
+ {
+ "images": "reinaldo_balloon_cu_cu",
+ "duration": 750
+ },
+ {
+ "images": [
+ "room",
+ "whore",
+ "hero",
+ "reinaldo"
+ ],
+ "duration": 150
+ },
+ {
+ "images": "reinaldo_balloon_o_que_foi",
+ "duration": 1500
+ },
+ {
+ "images": [
+ "room",
+ "whore",
+ "hero",
+ "reinaldo"
+ ],
+ "duration": 150
+ },
+ {
+ "images": "reinaldo_balloon_nao_quer_pagar",
+ "duration": 1500
+ },
+ {
+ "images": [
+ "room",
+ "whore",
+ "hero",
+ "reinaldo"
+ ],
+ "duration": 150
+ },
+ {
+ "images": "reinaldo_balloon_ja_vai_ver",
+ "duration": 1500
+ },
+ {
+ "images": [
+ "room",
+ "whore",
+ "hero",
+ "reinaldo"
+ ],
+ "duration": 500
+ },
+ {
+ "images": [
+ "room",
+ "whore",
+ "reinaldo_violar_base"
+ ]
+ },
+ {
+ "repeat": 7,
+ "roll": [
+ {
+ "images": "reinaldo_violar_frame1",
+ "duration": 250
+ },
+ {
+ "images": "reinaldo_violar_frame2",
+ "duration": 250
+ }
+ ]
+ },
+ {
+ "repeat": 3,
+ "roll": [
+ {
+ "images": "reinaldo_violar_frame1",
+ "duration": 250
+ },
+ {
+ "images": "reinaldo_violar_frame2",
+ "duration": 150
+ }
+ ]
+ },
+ {
+ "images": "reinaldo_balloon_caralhinho"
+ },
+ {
+ "repeat": 15,
+ "roll": [
+ {
+ "images": "reinaldo_violar_frame1",
+ "duration": 150
+ },
+ {
+ "images": "reinaldo_violar_frame2",
+ "duration": 150
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/assets/scenes/vaginal.json b/assets/scenes/vaginal.json
new file mode 100644
index 0000000..40ee8a6
--- /dev/null
+++ b/assets/scenes/vaginal.json
@@ -0,0 +1,62 @@
+{
+ "roll": [
+ {
+ "images": [
+ "room",
+ "vaginal_base",
+ "vaginal_frame1"
+ ],
+ "duration": 750
+ },
+ {
+ "repeat": 10,
+ "roll": [
+ {
+ "images": "vaginal_frame1",
+ "duration": 150
+ },
+ {
+ "images": "vaginal_frame2",
+ "duration": 150
+ }
+ ]
+ },
+ {
+ "repeat": 5,
+ "roll": [
+ {
+ "images": "vaginal_frame1",
+ "duration": 50
+ },
+ {
+ "images": "vaginal_frame2",
+ "duration": 50
+ }
+ ]
+ },
+ {
+ "images": "vaginal_balloon_venho"
+ },
+ {
+ "repeat": 6,
+ "roll": [
+ {
+ "images": "vaginal_frame1",
+ "duration": 250
+ },
+ {
+ "images": "vaginal_frame2",
+ "duration": 250
+ }
+ ]
+ },
+ {
+ "images": [
+ "room",
+ "vaginal_base",
+ "vaginal_frame1"
+ ],
+ "duration": 2500
+ }
+ ]
+}
\ No newline at end of file
diff --git a/assets/style.scss b/assets/style.scss
new file mode 100644
index 0000000..fc51e27
--- /dev/null
+++ b/assets/style.scss
@@ -0,0 +1,63 @@
+body {
+ background-color: #0000C8;
+ color: #FFF;
+ text-align: center;
+}
+
+div#div-canvas {
+ border-width: 1px;
+ border-style: solid;
+ border-color: #FFF;
+ margin: 0 auto;
+}
+
+img#img-title {
+ text-align:center;
+ margin: 20px auto;
+}
+
+ul#ul-teclas {
+
+ &.hidden {
+ display: none;
+ }
+
+ user-select: none;
+ list-style-type: none;
+ display: inline-block;
+ text-align: center;
+ padding: 0px;
+ margin: 20px auto;
+
+ li {
+
+ display: inline-block;
+ font-family: monospace;
+ font-size: 30px;
+ text-align: center;
+ border: 1px solid white;
+ width: 70px;
+ height: 60px;
+ display: inline-block;
+ background-color: #000;
+ padding: 10px 5px 10px 5px;
+
+ div {
+ font-size: 16px;
+ }
+
+ &:not(:last-child) {
+ margin-right: 20px;
+ }
+
+ &:hover {
+ cursor: pointer;
+ }
+
+ &:active {
+ background-color: #111;
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/excanvas.js b/excanvas.js
deleted file mode 100755
index 597ed5c..0000000
--- a/excanvas.js
+++ /dev/null
@@ -1,924 +0,0 @@
-// Copyright 2006 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-
-// Known Issues:
-//
-// * Patterns are not implemented.
-// * Radial gradient are not implemented. The VML version of these look very
-// different from the canvas one.
-// * Clipping paths are not implemented.
-// * Coordsize. The width and height attribute have higher priority than the
-// width and height style values which isn't correct.
-// * Painting mode isn't implemented.
-// * Canvas width/height should is using content-box by default. IE in
-// Quirks mode will draw the canvas using border-box. Either change your
-// doctype to HTML5
-// (http://www.whatwg.org/specs/web-apps/current-work/#the-doctype)
-// or use Box Sizing Behavior from WebFX
-// (http://webfx.eae.net/dhtml/boxsizing/boxsizing.html)
-// * Non uniform scaling does not correctly scale strokes.
-// * Optimize. There is always room for speed improvements.
-
-// Only add this code if we do not already have a canvas implementation
-if (!document.createElement('canvas').getContext) {
-
-(function() {
-
- // alias some functions to make (compiled) code shorter
- var m = Math;
- var mr = m.round;
- var ms = m.sin;
- var mc = m.cos;
- var abs = m.abs;
- var sqrt = m.sqrt;
-
- // this is used for sub pixel precision
- var Z = 10;
- var Z2 = Z / 2;
-
- /**
- * This funtion is assigned to the