├── .babelrc
├── media
└── 04b03.font.png
├── example
├── media
│ ├── fire01.png
│ ├── spiker.png
│ ├── bg_layer1.png
│ ├── 04b03.font.png
│ └── helicopter.png
└── lib
│ └── game
│ ├── main.js
│ ├── entities
│ ├── bullets
│ │ ├── BulletBombe.js
│ │ └── Bullet.js
│ └── characters
│ │ ├── CharacterSpike.js
│ │ ├── CharacterFlight.js
│ │ └── Character.js
│ ├── screens
│ └── Arena.js
│ └── levels
│ └── level.js
├── .gitignore
├── index.js
├── example.js
├── index.html
├── lib
├── game
│ └── main.js
└── impactES6
│ └── index.js
├── package.json
├── LICENSE
├── webpack.config.js
├── README.md
└── dist
└── game.min.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015"]
3 | }
--------------------------------------------------------------------------------
/media/04b03.font.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brochard-tech/impactES6/HEAD/media/04b03.font.png
--------------------------------------------------------------------------------
/example/media/fire01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brochard-tech/impactES6/HEAD/example/media/fire01.png
--------------------------------------------------------------------------------
/example/media/spiker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brochard-tech/impactES6/HEAD/example/media/spiker.png
--------------------------------------------------------------------------------
/example/media/bg_layer1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brochard-tech/impactES6/HEAD/example/media/bg_layer1.png
--------------------------------------------------------------------------------
/example/media/04b03.font.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brochard-tech/impactES6/HEAD/example/media/04b03.font.png
--------------------------------------------------------------------------------
/example/media/helicopter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brochard-tech/impactES6/HEAD/example/media/helicopter.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | node_modules/
3 | lib/impact
4 | lib/weltmeister
5 | example/lib/impact
6 | example/lib/weltmeister
7 | npm-debug.log
8 | weltmeister.html
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | // Import impact library
2 | import "lib/impact/impact";
3 |
4 | // Merge features into new ImpactEngine
5 | ig.mergeES5();
6 | window.ig = ig;
7 |
8 | // Import main game
9 | require('lib/game/main');
--------------------------------------------------------------------------------
/example/lib/game/main.js:
--------------------------------------------------------------------------------
1 | import Arena from "./screens/Arena";
2 |
3 | // Method to require an impact library
4 | // Once it is loaded, it doesn't need to require it again
5 | ig.require('impact.debug.debug');
6 |
7 | // Launch the game
8 | ig.main('#canvas', Arena, 60, 500, 500, 1);
--------------------------------------------------------------------------------
/example.js:
--------------------------------------------------------------------------------
1 | // We redefine the requirecontext to be able to require all ES5 files presents in the example folder
2 | ig.requirecontext = require.context('example/lib/', true, /^((?![\\/]impactES6|weltmeister[\\/]).)*\.js$/);
3 |
4 |
5 | // Import impact library
6 | import "lib/impact/impact";
7 |
8 | // Merge features into new ImpactEngine
9 | ig.mergeES5();
10 | window.ig = ig;
11 |
12 | require('example/lib/game/main');
--------------------------------------------------------------------------------
/example/lib/game/entities/bullets/BulletBombe.js:
--------------------------------------------------------------------------------
1 | ig.require('game.entities.bullets.bullet');
2 |
3 |
4 | export default class BulletBombe extends ig.EntityBullet {
5 | /* LIFECYCLE */
6 | }
7 |
8 | ig.bindProperties(BulletBombe, {
9 | animSheet : new ig.AnimationSheet('example/media/fire01.png', 14, 32),
10 | size : {x: 14, y: 32},
11 | vel : {x: 0, y: 300},
12 | amount : 40
13 | });
--------------------------------------------------------------------------------
/example/lib/game/entities/characters/CharacterSpike.js:
--------------------------------------------------------------------------------
1 | import Character from "./Character";
2 |
3 |
4 | export default class CharacterSpike extends Character {
5 | /* LIFECYCLE */
6 | init (x, y, settings)
7 | {
8 | super.init(x, y, settings);
9 |
10 | // Animations
11 | this.addAnim('idle', 1, [0]);
12 | this.addAnim('walk', 0.2, [1, 2]);
13 | }
14 | }
15 |
16 |
17 | ig.bindProperties(CharacterSpike, {
18 | animSheet : new ig.AnimationSheet('example/media/spiker.png', 30, 40),
19 | size : {x: 30, y: 40},
20 | type : ig.Entity.TYPE.B,
21 | checkAgainst : ig.Entity.TYPE.A
22 | });
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Impact Game
6 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/lib/game/main.js:
--------------------------------------------------------------------------------
1 | // Method to require an impact library
2 | // Once it is loaded, it doesn't need to require it again
3 | ig.require('impact.game');
4 | ig.require('impact.debug.debug');
5 |
6 |
7 | export default class MyGame extends ig.Game {
8 | init ()
9 | {
10 | // Custom actions at initialization
11 | }
12 |
13 | update ()
14 | {
15 | // Update all entities and backgroundMaps
16 | super.update();
17 |
18 | // Add your own, additional update code here
19 | }
20 |
21 | draw ()
22 | {
23 | // Draw all entities and backgroundMaps
24 | super.draw();
25 |
26 | // Add your own drawing code here
27 | var x = ig.system.width / 2,
28 | y = ig.system.height / 2;
29 |
30 | this.font.draw('It Works!', x, y, ig.Font.ALIGN.CENTER);
31 | }
32 | }
33 |
34 | // Declare properties
35 | ig.bindProperties(MyGame, {
36 | font : new ig.Font('media/04b03.font.png')
37 | });
38 |
39 |
40 | ig.main('#canvas', MyGame, 60, 320, 240, 2);
--------------------------------------------------------------------------------
/example/lib/game/entities/characters/CharacterFlight.js:
--------------------------------------------------------------------------------
1 | import Character from "./Character";
2 | import BulletBombe from "./../bullets/BulletBombe";
3 |
4 |
5 | export default class CharacterFlight extends Character {
6 | /* LIFECYCLE */
7 | init (x, y, settings)
8 | {
9 | super.init(x, y, settings);
10 |
11 | this.addAnim('idle', 1, [0]);
12 | }
13 |
14 | update ()
15 | {
16 | super.update();
17 | }
18 |
19 |
20 | /* METHOD */
21 | fire ()
22 | {
23 | if (super.fire()) {
24 | ig.game.spawnEntity(BulletBombe, this.pos.x + (this.size.x / 2), this.pos.y + this.size.y, { owner: this });
25 | }
26 | }
27 | }
28 |
29 | ig.bindProperties(CharacterFlight, {
30 | animSheet : new ig.AnimationSheet('example/media/helicopter.png', 43, 36),
31 | size : {x: 43, y: 36},
32 | type : ig.Entity.TYPE.A,
33 | checkAgainst : ig.Entity.TYPE.B,
34 | gravityFactor : 0,
35 | zIndex : 1,
36 | speed : 300
37 | });
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "impactes6",
3 | "version": "0.3.0",
4 | "description": "This project allow you tu use ES6 with ImpactJS",
5 | "main": "index.js",
6 | "scripts": {
7 | "build": "./node_modules/.bin/webpack -p --config webpack.config.js --progress --profile --colors",
8 | "build-dev": "./node_modules/.bin/webpack -d --config webpack.config.js --watch --progress --profile --colors",
9 | "test": "echo \"Error: no test specified\" && exit 1"
10 | },
11 | "repository": {
12 | "type": "git",
13 | "url": "git+https://github.com/myvertigo/impactES6.git"
14 | },
15 | "author": "Christophe Brochard (http://www.myvertigo.fr)",
16 | "license": "ISC",
17 | "bugs": {
18 | "url": "https://github.com/myvertigo/impactES6/issues"
19 | },
20 | "homepage": "https://github.com/myvertigo/impactES6#readme",
21 | "dependencies": {
22 | "imports-loader": "^0.6.5",
23 | "jquery": "^3.1.0"
24 | },
25 | "devDependencies": {
26 | "babel-loader": "^6.2.5",
27 | "babel-preset-es2015": "^6.14.0",
28 | "webpack": "^1.13.2"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/example/lib/game/entities/bullets/Bullet.js:
--------------------------------------------------------------------------------
1 | ig.module(
2 | 'game.entities.bullets.bullet'
3 |
4 | ).requires(
5 | 'impact.entity'
6 |
7 | ).defines(function () {
8 |
9 | ig.EntityBullet = ig.Entity.extend({
10 | /* ATTRIBUTES */
11 | amount: 10,
12 | owner : null,
13 |
14 |
15 | /* LIFECYCLE */
16 | init: function (x, y, settings)
17 | {
18 | this.parent(x, y, settings);
19 |
20 | if (this.owner) {
21 | this.type = this.owner.type;
22 | this.checkAgainst = (this.type === ig.Entity.TYPE.A) ? ig.Entity.TYPE.B : ig.Entity.TYPE.A;
23 | }
24 |
25 | if (this.animSheet) {
26 | this.addAnim('idle', 1, [0]);
27 | }
28 | },
29 |
30 | update: function ()
31 | {
32 | this.parent();
33 |
34 | if (this.pos.x < 0 || this.pos.y < 0 || this.pos.x > ig.system.width || this.pos.y > ig.system.height) {
35 | this.kill();
36 | }
37 |
38 | return 4;
39 | },
40 |
41 | check: function (other)
42 | {
43 | other.receiveDamage(this.amount);
44 | this.kill();
45 | }
46 | });
47 |
48 | });
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var webpack = require('webpack');
3 |
4 | module.exports = {
5 | // Entry file JS
6 | entry: {
7 | game : './index.js',
8 | example : './example.js'
9 | },
10 |
11 | // File minified
12 | output: {
13 | path: path.join(__dirname, 'dist'),
14 | filename: '[name].min.js'
15 | },
16 |
17 | // Set shorcut to js files
18 | resolve: {
19 | root: path.resolve(__dirname),
20 | alias: {
21 | ig: 'lib/impactES6'
22 | },
23 | extensions: ['', '.js']
24 | },
25 |
26 | plugins: [
27 | // Create global variables
28 | new webpack.ProvidePlugin({
29 | ig: 'ig',
30 | $: 'jquery',
31 | jQuery: 'jquery',
32 | 'window.jQuery': 'jquery'
33 | })
34 | ],
35 |
36 | module: {
37 | // Babel ES6 Loader
38 | loaders: [
39 | {
40 | test: /\.js$/,
41 | loader: 'imports?this=>window',
42 | exclude: '/node_modules/'
43 | },
44 |
45 | {
46 | test: /\.js$/,
47 | loader: 'babel-loader',
48 | exclude: /node_modules/,
49 | query: {
50 | presets: ['es2015']
51 | }
52 | }
53 | ]
54 | }
55 | };
--------------------------------------------------------------------------------
/example/lib/game/entities/characters/Character.js:
--------------------------------------------------------------------------------
1 | ig.require('impact.entity');
2 |
3 |
4 | export default class Character extends ig.Entity {
5 | /* LIFECYCLE */
6 | update ()
7 | {
8 | super.update();
9 |
10 | if (this.currentAnim) {
11 | this.updateAnimation();
12 | }
13 | }
14 |
15 | check ()
16 | {
17 | this.kill();
18 | }
19 |
20 |
21 | /* METHODS */
22 | updateAnimation ()
23 | {
24 | this.currentAnim.flip.x = this.flip;
25 | }
26 |
27 | setDirection (speedType, x, y)
28 | {
29 | if (speedType !== "vel" && speedType !== "accel") {
30 | return null;
31 | }
32 |
33 | this[speedType].y = (y || 0) * this.speed;
34 | this[speedType].x = (x || 0) * this.speed;
35 | }
36 |
37 | setVel (x, y)
38 | {
39 | this.setDirection('vel', x, y);
40 | }
41 |
42 | setAccel (x, y)
43 | {
44 | if (!x && !y && !this.accel.x && !this.accel.y) {
45 | return null;
46 | }
47 |
48 | this.setDirection('accel', x, y);
49 | }
50 |
51 | fire ()
52 | {
53 | if (this._killed) {
54 | return false;
55 | }
56 |
57 | if (!this.timerWeaponWait) {
58 | this.timerWeaponWait = new ig.Timer(this.timeWeaponWait / 100);
59 | return true;
60 |
61 | } else if (this.timerWeaponWait.delta() > 0) {
62 | this.timerWeaponWait = null;
63 | return true;
64 | }
65 |
66 | return false;
67 | }
68 | }
69 |
70 | ig.bindProperties(Character, {
71 | zIndex : 0,
72 | speed : 100,
73 | health : 200,
74 | timeWeaponWait : 200,
75 | gravityFactor : 0
76 | });
--------------------------------------------------------------------------------
/example/lib/game/screens/Arena.js:
--------------------------------------------------------------------------------
1 | import CharacterFlight from "./../entities/characters/CharacterFlight";
2 | import CharacterSpike from "./../entities/characters/CharacterSpike";
3 |
4 | ig.require('impact.game');
5 |
6 |
7 | export default class Arena extends ig.Game {
8 | /* LIFECYCLE */
9 | init ()
10 | {
11 | // Bind inputs for player
12 | ig.input.bind(ig.KEY.UP_ARROW, 'up');
13 | ig.input.bind(ig.KEY.RIGHT_ARROW, 'right');
14 | ig.input.bind(ig.KEY.LEFT_ARROW, 'left');
15 | ig.input.bind(ig.KEY.DOWN_ARROW, 'down');
16 | ig.input.bind(ig.KEY.SPACE, 'fire');
17 |
18 | this.player = ig.game.spawnEntity(CharacterFlight, 0, 0);
19 | this.spike = ig.game.spawnEntity(CharacterSpike, 50, ig.system.height - 100);
20 | ig.game.spawnEntity(CharacterSpike, 200, ig.system.height - 100, { size: {x: 70, y: 70} });
21 | }
22 |
23 | update ()
24 | {
25 | super.update();
26 |
27 | if (this.player) {
28 | this.updateInputs();
29 | }
30 | }
31 |
32 | draw ()
33 | {
34 | super.draw();
35 |
36 | var x = ig.system.width / 2,
37 | y = ig.system.height / 2;
38 |
39 | this.font.draw('It Works!', x, y, ig.Font.ALIGN.CENTER);
40 | }
41 |
42 |
43 | /* METHODS */
44 | updateInputs ()
45 | {
46 | var left = ig.input.state('left');
47 | var right = ig.input.state('right');
48 | var up = ig.input.state('up');
49 | var down = ig.input.state('down');
50 | var x = 0;
51 | var y = 0;
52 |
53 | if (left) { x--; }
54 | if (right) { x++; }
55 | if (down) { y++; }
56 | if (up) { y--; }
57 |
58 | this.player.setVel(x, y);
59 |
60 | if (ig.input.pressed('fire')) {
61 | this.player.fire();
62 | }
63 | }
64 | }
65 |
66 | ig.bindProperties(Arena, {
67 | gravity : 300,
68 | player : null,
69 | font : new ig.Font('media/04b03.font.png')
70 | });
--------------------------------------------------------------------------------
/example/lib/game/levels/level.js:
--------------------------------------------------------------------------------
1 | ig.module( 'game.levels.level' )
2 | .requires( 'impact.image' )
3 | .defines(function(){
4 | LevelLevel=/*JSON[*/{
5 | "entities": [],
6 | "layer": [
7 | {
8 | "name": "tiles",
9 | "width": 16,
10 | "height": 10,
11 | "linkWithCollision": false,
12 | "visible": 1,
13 | "tilesetName": "media/tiles/ground.png",
14 | "repeat": false,
15 | "preRender": false,
16 | "distance": "1",
17 | "tilesize": 64,
18 | "foreground": false,
19 | "data": [
20 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
21 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
22 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
23 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
24 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
25 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
26 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
27 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
28 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
29 | [97,9,9,9,9,9,9,9,9,9,9,9,9,9,9,89]
30 | ]
31 | },
32 | {
33 | "name": "collision",
34 | "width": 32,
35 | "height": 20,
36 | "linkWithCollision": false,
37 | "visible": 1,
38 | "tilesetName": "",
39 | "repeat": false,
40 | "preRender": false,
41 | "distance": 1,
42 | "tilesize": 32,
43 | "foreground": false,
44 | "data": [
45 | [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
46 | [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
47 | [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
48 | [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
49 | [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
50 | [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
51 | [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
52 | [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
53 | [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
54 | [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
55 | [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
56 | [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
57 | [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
58 | [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
59 | [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
60 | [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
61 | [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
62 | [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
63 | [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
64 | [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
65 | ]
66 | }
67 | ]
68 | }/*]JSON*/;
69 | LevelLevelResources=[new ig.Image('media/tiles/ground.png')];
70 | });
--------------------------------------------------------------------------------
/lib/impactES6/index.js:
--------------------------------------------------------------------------------
1 | var igES6 = module.exports = {
2 | /**
3 | * This variable is at true when igES6 has all method of impact library
4 | */
5 | _importES5: false,
6 |
7 | /**
8 | * Data provided by ig.module, ig.requires and ig.defines before _importES5 at true
9 | */
10 | _storedData: {modules: [], requires: [], defines: []},
11 |
12 | /**
13 | * List of all modules ES5 loaded
14 | */
15 | modules: {},
16 |
17 | /**
18 | * Context folder of all library (needed for dynamic require)
19 | */
20 | requirecontext: require.context('lib/', true, /^((?![\\/]impactES6|weltmeister[\\/]).)*\.js$/),
21 |
22 | /**
23 | * Define a new module (support ES5)
24 | * @param name
25 | * @returns Object
26 | */
27 | module: function (name)
28 | {
29 | if (!name) {
30 | return this;
31 |
32 | }
33 |
34 | if (!this._importES5) {
35 | this._storedData.modules.push(name);
36 |
37 | } else if (!this.modules[name]) {
38 | this.modules[name] = true;
39 |
40 | }
41 |
42 | return this;
43 | },
44 |
45 | /**
46 | * Requires all module for the current module (support ES5)
47 | * @returns Object
48 | */
49 | requires: function ()
50 | {
51 | var args = Array.from(arguments);
52 |
53 | if (!this._importES5) {
54 | this._storedData.requires.push(args);
55 | return this;
56 | }
57 |
58 | args.map((arg) => {
59 | if (arg === "dom.ready") {
60 | this._ready = true;
61 |
62 | } else {
63 | this.require(arg);
64 |
65 | }
66 | });
67 |
68 | return this;
69 | },
70 |
71 | /**
72 | * Require a module
73 | * @param moduleName
74 | */
75 | require: function (moduleName)
76 | {
77 | if (!this.modules[moduleName] && moduleName !== "impact.impact") {
78 | let path = "./" + moduleName.split('.').join('/') + '.js';
79 | this.requirecontext(path);
80 | }
81 | },
82 |
83 | /**
84 | * Define a module (ig.module must be defined before) (support ES5)
85 | * @param define
86 | */
87 | defines: function (define)
88 | {
89 | if (!this._importES5) {
90 | this._storedData.defines.push(define);
91 |
92 | } else {
93 | define();
94 |
95 | }
96 | },
97 |
98 | /**
99 | * Merge all storedData provided by old module before _importES5
100 | */
101 | mergeES5: function ()
102 | {
103 | for (var propName in window.ig) {
104 | if (!this.hasOwnProperty(propName) && window.ig.hasOwnProperty(propName)) {
105 | this[propName] = window.ig[propName];
106 | }
107 | }
108 |
109 | this.setVendorAttribute = window.ig.setVendorAttribute;
110 | this.getVendorAttribute = window.ig.getVendorAttribute;
111 | this.normalizeVendorAttribute = window.ig.normalizeVendorAttribute;
112 |
113 | this._importES5 = true;
114 |
115 | this._storedData.modules.map(x => this.module(x));
116 | this._storedData.requires.map(x => this.requires.apply(this, x));
117 | this._storedData.defines.map(x => this.defines(x));
118 | },
119 |
120 | /**
121 | * Bind props to ES6 currentClass
122 | * @param currentClass
123 | * @param props
124 | * @returns {*}
125 | */
126 | bindProperties: function (currentClass, props)
127 | {
128 | for (var propname in props) {
129 | currentClass.prototype[propname] = props[propname];
130 | }
131 |
132 | return currentClass;
133 | },
134 |
135 | /**
136 | * Override of ImpactJS
137 | * @returns {boolean}
138 | * @private
139 | */
140 | _DOMReady: function()
141 | {
142 | return !!this._ready;
143 | },
144 |
145 | /**
146 | * Same as ImpactJS
147 | * @param element
148 | * @param attribute
149 | * @param value
150 | */
151 | setVendorAttribute: (element, attribute, value) => {
152 | window.ig.setVendorAttribute(element, attribute, value);
153 | },
154 |
155 | /**
156 | * Same as ImpactJS
157 | * @param element
158 | * @param attribute
159 | * @returns {*}
160 | */
161 | getVendorAttribute: (element, attribute) => {
162 | return window.ig.getVendorAttribute(element, attribute);
163 | },
164 |
165 | /**
166 | * Same as ImpactJS
167 | * @param element
168 | * @param attribute
169 | */
170 | normalizeVendorAttribute: (element, attribute) => {
171 | window.ig.normalizeVendorAttribute(element, attribute);
172 | }
173 | };
174 |
175 | module.export = igES6;
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # impactES6
2 |
3 | ### NEW UPDATE : **Version BETA 0.3**
4 |
5 | #### What's new in 0.3 Version
6 | - Is it now possible to have a project with both old script and ES6 Scripts. Note : To avoid most common error, please read the chapter about "Use Strict mode"
7 | - Preloading image run now correctly
8 |
9 | This project allow you tu use ES6 with ImpactJS.
10 |
11 | > **Note about current version**
12 |
13 | > - Impact Library support : **Version 1.24**
14 | > - If you encouter any bugs or issues, please report it into the issues page
15 |
16 |
17 | ## Overview
18 |
19 | #### ES6
20 |
21 | ImpactJS is an excellent javascript game framework with lots of features. But there is actually no support with ES6.
22 | ES6 is a new way to write javascript code and it is so much better than ES5. [Click here for more informations about ES6 features][1]
23 |
24 |
25 | #### Webpack
26 |
27 | This project use webpack to minify and uglify your all game into a single file. [Click here for more informations about Webpack][2]
28 |
29 |
30 | #### Node and Npm
31 |
32 | Npm ("Module Package Manager") is a tool for manage your project dependency. To have Npm in your shell, you must install **Node**
33 | [by clicking here][3]
34 |
35 | #### Use strict mode
36 |
37 | In ES6, all scripts are in *use strict* mode. In this mode, you **can't** create a global variable :
38 | ```javascript
39 | EntityPlayer = ig.Entity.extend(...) // Will throw an error because EntityPlayer doesn't exist
40 | ```
41 | To avoid this error, you **must** bind your entity with "ig" variable like this :
42 | ```javascript
43 | ig.EntityPlayer = ig.Entity.extend(...) // GOOD !
44 | ```
45 | In fact, in *use strict* mode, a function that is not an object can't have a reference to a *this* and it doesn't not also
46 | reference to *window* object.
47 |
48 |
49 | ## Installation
50 |
51 | ##### **1)** Copy this project into your local environment.
52 |
53 | ##### **2)** Install package with npm
54 | ```
55 | npm install
56 | ```
57 |
58 | ##### **3)** Install ImpactJS into the project
59 | The ImpactJS folder must be at the root of this project. In other terms : **game** and **impact** folders should be into the lib directory with "impactES6" folder.
60 |
61 | ##### **4)** Make your game !
62 | The project is now configured and you can develop your game with ES6 !
63 |
64 | ##### **5)** Build your game into a single file
65 | To build your games into a single file, use the shell and type this command into the root directory of your project
66 | ```
67 | npm run build
68 | ```
69 |
70 | If your are in a development environnement, you can use :
71 | ```
72 | npm run build-dev
73 | ```
74 | This command has a watcher and it will build your game when a file has changed.
75 |
76 |
77 | ## Usage
78 |
79 | ### Import an old script
80 | ```javascript
81 | ig.require('game.entities.fire'); // You need to require it juste once. It will be loaded for all your project
82 | ```
83 |
84 | ### Import a new script
85 | ```javascript
86 | import EntityPlayer from "lib/game/entities/player";
87 | ```
88 |
89 | ### Create an entity
90 | ```javascript
91 | export default class EntityPlayer extend ig.Entity {
92 |
93 | init (x, y, settings)
94 | {
95 | super.init(x, y, settings);
96 | ...
97 | }
98 |
99 | fire ()
100 | {
101 | ig.game.spawnEntity(EntityFire, this.pos.x + (this.size.x / 2), this.pos.y + this.size.y, { owner: this });
102 | }
103 |
104 | }
105 | ```
106 |
107 | ### Default properties
108 | Default properties is a new way to declare your properties **before** the new object was created.
109 | For example, in ES5 Script, you have :
110 | ```javascript
111 | ig.EntityPlayer = ig.Entity.extend({
112 | animSheet: new ig.AnimationSheet('media/player.png', 10, 10),
113 | size : {x: 10, y: 10},
114 | speed: 300,
115 |
116 | init: function (x, y, settings) {
117 | ...
118 | }
119 | });
120 | ```
121 |
122 | In ES6, you can't define variable except into a function, so, when it is created. But ImpactES6 has a function which
123 | allow you to define properties. Like this :
124 | ```javascript
125 | export default class EntityPlayer extend ig.Entity {
126 | init (x, y, settings)
127 | {
128 | ...
129 | }
130 | }
131 |
132 | ig.bindProperties(EntityPlayer, {
133 | animSheet : new ig.AnimationSheet('media/player.png', 10, 10),
134 | size : {x: 10, y: 10},
135 | speed : 300
136 | });
137 | ```
138 |
139 | ### jQuery
140 | jQuery is added by default on the project. You can call "$" or "jQuery" without do anything. But if you want to add
141 | plugin into jQuery, you have to use *imports-loader* and import your plugin like this :
142 | ```javascript
143 | import "imports?$=jquery,this=>window!velocity-animate";
144 | ```
145 | It is a query string which means that you import global jQuery into the script and you define the window object like global variable.
146 | Like *ig.require*, import it once and it will be loaded into all your project.
147 |
148 |
149 | ## Examples
150 |
151 | You can see a dummy example into the folder, juste load the index.html in your browser and you will see.
152 |
153 |
154 |
155 |
156 |
157 | [1]: https://babeljs.io/docs/learn-es2015/
158 | [2]: https://webpack.github.io/docs/what-is-webpack.html
159 | [3]: https://docs.npmjs.com/getting-started/installing-node
160 |
--------------------------------------------------------------------------------
/dist/game.min.js:
--------------------------------------------------------------------------------
1 | /******/ (function(modules) { // webpackBootstrap
2 | /******/ // The module cache
3 | /******/ var installedModules = {};
4 | /******/
5 | /******/ // The require function
6 | /******/ function __webpack_require__(moduleId) {
7 | /******/
8 | /******/ // Check if module is in cache
9 | /******/ if(installedModules[moduleId])
10 | /******/ return installedModules[moduleId].exports;
11 | /******/
12 | /******/ // Create a new module (and put it into the cache)
13 | /******/ var module = installedModules[moduleId] = {
14 | /******/ exports: {},
15 | /******/ id: moduleId,
16 | /******/ loaded: false
17 | /******/ };
18 | /******/
19 | /******/ // Execute the module function
20 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
21 | /******/
22 | /******/ // Flag the module as loaded
23 | /******/ module.loaded = true;
24 | /******/
25 | /******/ // Return the exports of the module
26 | /******/ return module.exports;
27 | /******/ }
28 | /******/
29 | /******/
30 | /******/ // expose the modules object (__webpack_modules__)
31 | /******/ __webpack_require__.m = modules;
32 | /******/
33 | /******/ // expose the module cache
34 | /******/ __webpack_require__.c = installedModules;
35 | /******/
36 | /******/ // __webpack_public_path__
37 | /******/ __webpack_require__.p = "";
38 | /******/
39 | /******/ // Load entry module and return exports
40 | /******/ return __webpack_require__(0);
41 | /******/ })
42 | /************************************************************************/
43 | /******/ ([
44 | /* 0 */
45 | /*!******************!*\
46 | !*** ./index.js ***!
47 | \******************/
48 | /***/ function(module, exports, __webpack_require__) {
49 |
50 | /* WEBPACK VAR INJECTION */(function(ig) {/*** IMPORTS FROM imports-loader ***/
51 | (function() {
52 |
53 | "use strict";
54 |
55 | __webpack_require__(/*! lib/impact/impact */ 18);
56 |
57 | // Merge features into new ImpactEngine
58 | ig.mergeES5(); // Import impact library
59 |
60 | window.ig = ig;
61 |
62 | // Import main game
63 | __webpack_require__(/*! lib/game/main */ 4);
64 | }.call(window));
65 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(/*! ig */ 1)))
66 |
67 | /***/ },
68 | /* 1 */
69 | /*!********************************!*\
70 | !*** ./lib/impactES6/index.js ***!
71 | \********************************/
72 | /***/ function(module, exports, __webpack_require__) {
73 |
74 | /* WEBPACK VAR INJECTION */(function(module) {/*** IMPORTS FROM imports-loader ***/
75 | (function() {
76 |
77 | "use strict";
78 |
79 | var igES6 = module.exports = {
80 | /**
81 | * This variable is at true when igES6 has all method of impact library
82 | */
83 | _importES5: false,
84 |
85 | /**
86 | * Data provided by ig.module, ig.requires and ig.defines before _importES5 at true
87 | */
88 | _storedData: { modules: [], requires: [], defines: [] },
89 |
90 | /**
91 | * List of all modules ES5 loaded
92 | */
93 | modules: {},
94 |
95 | /**
96 | * Context folder of all library (needed for dynamic require)
97 | */
98 | requirecontext: __webpack_require__(/*! lib/ */ 3),
99 |
100 | /**
101 | * Define a new module (support ES5)
102 | * @param name
103 | * @returns Object
104 | */
105 | module: function module(name) {
106 | if (!name) {
107 | return this;
108 | }
109 |
110 | if (!this._importES5) {
111 | this._storedData.modules.push(name);
112 | } else if (!this.modules[name]) {
113 | this.modules[name] = true;
114 | }
115 |
116 | return this;
117 | },
118 |
119 | /**
120 | * Requires all module for the current module (support ES5)
121 | * @returns Object
122 | */
123 | requires: function requires() {
124 | var _this = this;
125 |
126 | var args = Array.from(arguments);
127 |
128 | if (!this._importES5) {
129 | this._storedData.requires.push(args);
130 | return this;
131 | }
132 |
133 | args.map(function (arg) {
134 | if (arg === "dom.ready") {
135 | _this._ready = true;
136 | } else {
137 | _this.require(arg);
138 | }
139 | });
140 |
141 | return this;
142 | },
143 |
144 | /**
145 | * Require a module
146 | * @param moduleName
147 | */
148 | require: function require(moduleName) {
149 | if (!this.modules[moduleName] && moduleName !== "impact.impact") {
150 | var path = "./" + moduleName.split('.').join('/') + '.js';
151 | this.requirecontext(path);
152 | }
153 | },
154 |
155 | /**
156 | * Define a module (ig.module must be defined before) (support ES5)
157 | * @param define
158 | */
159 | defines: function defines(define) {
160 | if (!this._importES5) {
161 | this._storedData.defines.push(define);
162 | } else {
163 | define();
164 | }
165 | },
166 |
167 | /**
168 | * Merge all storedData provided by old module before _importES5
169 | */
170 | mergeES5: function mergeES5() {
171 | var _this2 = this;
172 |
173 | for (var propName in window.ig) {
174 | if (!this.hasOwnProperty(propName) && window.ig.hasOwnProperty(propName)) {
175 | this[propName] = window.ig[propName];
176 | }
177 | }
178 |
179 | this.setVendorAttribute = window.ig.setVendorAttribute;
180 | this.getVendorAttribute = window.ig.getVendorAttribute;
181 | this.normalizeVendorAttribute = window.ig.normalizeVendorAttribute;
182 |
183 | this._importES5 = true;
184 |
185 | this._storedData.modules.map(function (x) {
186 | return _this2.module(x);
187 | });
188 | this._storedData.requires.map(function (x) {
189 | return _this2.requires.apply(_this2, x);
190 | });
191 | this._storedData.defines.map(function (x) {
192 | return _this2.defines(x);
193 | });
194 | },
195 |
196 | /**
197 | * Bind props to ES6 currentClass
198 | * @param currentClass
199 | * @param props
200 | * @returns {*}
201 | */
202 | bindProperties: function bindProperties(currentClass, props) {
203 | for (var propname in props) {
204 | currentClass.prototype[propname] = props[propname];
205 | }
206 |
207 | return currentClass;
208 | },
209 |
210 | /**
211 | * Override of ImpactJS
212 | * @returns {boolean}
213 | * @private
214 | */
215 | _DOMReady: function _DOMReady() {
216 | return !!this._ready;
217 | },
218 |
219 | /**
220 | * Same as ImpactJS
221 | * @param element
222 | * @param attribute
223 | * @param value
224 | */
225 | setVendorAttribute: function setVendorAttribute(element, attribute, value) {
226 | window.ig.setVendorAttribute(element, attribute, value);
227 | },
228 |
229 | /**
230 | * Same as ImpactJS
231 | * @param element
232 | * @param attribute
233 | * @returns {*}
234 | */
235 | getVendorAttribute: function getVendorAttribute(element, attribute) {
236 | return window.ig.getVendorAttribute(element, attribute);
237 | },
238 |
239 | /**
240 | * Same as ImpactJS
241 | * @param element
242 | * @param attribute
243 | */
244 | normalizeVendorAttribute: function normalizeVendorAttribute(element, attribute) {
245 | window.ig.normalizeVendorAttribute(element, attribute);
246 | }
247 | };
248 |
249 | module.export = igES6;
250 | }.call(window));
251 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(/*! ./../../~/webpack/buildin/module.js */ 2)(module)))
252 |
253 | /***/ },
254 | /* 2 */
255 | /*!***********************************!*\
256 | !*** (webpack)/buildin/module.js ***!
257 | \***********************************/
258 | /***/ function(module, exports) {
259 |
260 | /*** IMPORTS FROM imports-loader ***/
261 | (function() {
262 |
263 | module.exports = function(module) {
264 | if(!module.webpackPolyfill) {
265 | module.deprecate = function() {};
266 | module.paths = [];
267 | // module.parent = undefined by default
268 | module.children = [];
269 | module.webpackPolyfill = 1;
270 | }
271 | return module;
272 | }
273 |
274 | }.call(window));
275 |
276 | /***/ },
277 | /* 3 */
278 | /*!***********************************************************!*\
279 | !*** ./lib ^((?![\\/]impactES6|weltmeister[\\/]).)*\.js$ ***!
280 | \***********************************************************/
281 | /***/ function(module, exports, __webpack_require__) {
282 |
283 | var map = {
284 | "./game/main.js": 4,
285 | "./impact/animation.js": 5,
286 | "./impact/background-map.js": 6,
287 | "./impact/collision-map.js": 7,
288 | "./impact/debug/debug.js": 8,
289 | "./impact/debug/entities-panel.js": 9,
290 | "./impact/debug/graph-panel.js": 10,
291 | "./impact/debug/maps-panel.js": 11,
292 | "./impact/debug/menu.js": 12,
293 | "./impact/entity-pool.js": 13,
294 | "./impact/entity.js": 14,
295 | "./impact/font.js": 15,
296 | "./impact/game.js": 16,
297 | "./impact/image.js": 17,
298 | "./impact/impact.js": 18,
299 | "./impact/input.js": 19,
300 | "./impact/loader.js": 20,
301 | "./impact/map.js": 21,
302 | "./impact/sound.js": 22,
303 | "./impact/system.js": 23,
304 | "./impact/timer.js": 24
305 | };
306 | function webpackContext(req) {
307 | return __webpack_require__(webpackContextResolve(req));
308 | };
309 | function webpackContextResolve(req) {
310 | return map[req] || (function() { throw new Error("Cannot find module '" + req + "'.") }());
311 | };
312 | webpackContext.keys = function webpackContextKeys() {
313 | return Object.keys(map);
314 | };
315 | webpackContext.resolve = webpackContextResolve;
316 | module.exports = webpackContext;
317 | webpackContext.id = 3;
318 |
319 |
320 | /***/ },
321 | /* 4 */
322 | /*!**************************!*\
323 | !*** ./lib/game/main.js ***!
324 | \**************************/
325 | /***/ function(module, exports, __webpack_require__) {
326 |
327 | /* WEBPACK VAR INJECTION */(function(ig) {/*** IMPORTS FROM imports-loader ***/
328 | (function() {
329 |
330 | 'use strict';
331 |
332 | Object.defineProperty(exports, "__esModule", {
333 | value: true
334 | });
335 |
336 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
337 |
338 | var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };
339 |
340 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
341 |
342 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
343 |
344 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
345 |
346 | // Method to require an impact library
347 | // Once it is loaded, it doesn't need to require it again
348 | ig.require('impact.game');
349 | ig.require('impact.debug.debug');
350 |
351 | var MyGame = function (_ig$Game) {
352 | _inherits(MyGame, _ig$Game);
353 |
354 | function MyGame() {
355 | _classCallCheck(this, MyGame);
356 |
357 | return _possibleConstructorReturn(this, (MyGame.__proto__ || Object.getPrototypeOf(MyGame)).apply(this, arguments));
358 | }
359 |
360 | _createClass(MyGame, [{
361 | key: 'init',
362 | value: function init() {
363 | // Custom actions at initialization
364 | }
365 | }, {
366 | key: 'update',
367 | value: function update() {
368 | // Update all entities and backgroundMaps
369 | _get(MyGame.prototype.__proto__ || Object.getPrototypeOf(MyGame.prototype), 'update', this).call(this);
370 |
371 | // Add your own, additional update code here
372 | }
373 | }, {
374 | key: 'draw',
375 | value: function draw() {
376 | // Draw all entities and backgroundMaps
377 | _get(MyGame.prototype.__proto__ || Object.getPrototypeOf(MyGame.prototype), 'draw', this).call(this);
378 |
379 | // Add your own drawing code here
380 | var x = ig.system.width / 2,
381 | y = ig.system.height / 2;
382 |
383 | this.font.draw('It Works!', x, y, ig.Font.ALIGN.CENTER);
384 | }
385 | }]);
386 |
387 | return MyGame;
388 | }(ig.Game);
389 |
390 | // Declare properties
391 |
392 |
393 | exports.default = MyGame;
394 | ig.bindProperties(MyGame, {
395 | font: new ig.Font('media/04b03.font.png')
396 | });
397 |
398 | ig.main('#canvas', MyGame, 60, 320, 240, 2);
399 | }.call(window));
400 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(/*! ig */ 1)))
401 |
402 | /***/ },
403 | /* 5 */
404 | /*!*********************************!*\
405 | !*** ./lib/impact/animation.js ***!
406 | \*********************************/
407 | /***/ function(module, exports, __webpack_require__) {
408 |
409 | /* WEBPACK VAR INJECTION */(function(ig) {/*** IMPORTS FROM imports-loader ***/
410 | (function() {
411 |
412 | 'use strict';
413 |
414 | ig.module('impact.animation').requires('impact.timer', 'impact.image').defines(function () {
415 | "use strict";
416 |
417 | ig.AnimationSheet = ig.Class.extend({
418 | width: 8,
419 | height: 8,
420 | image: null,
421 |
422 | init: function init(path, width, height) {
423 | this.width = width;
424 | this.height = height;
425 |
426 | this.image = new ig.Image(path);
427 | }
428 | });
429 |
430 | ig.Animation = ig.Class.extend({
431 | sheet: null,
432 | timer: null,
433 |
434 | sequence: [],
435 | flip: { x: false, y: false },
436 | pivot: { x: 0, y: 0 },
437 |
438 | frame: 0,
439 | tile: 0,
440 | loopCount: 0,
441 | alpha: 1,
442 | angle: 0,
443 |
444 | init: function init(sheet, frameTime, sequence, stop) {
445 | this.sheet = sheet;
446 | this.pivot = { x: sheet.width / 2, y: sheet.height / 2 };
447 | this.timer = new ig.Timer();
448 |
449 | this.frameTime = frameTime;
450 | this.sequence = sequence;
451 | this.stop = !!stop;
452 | this.tile = this.sequence[0];
453 | },
454 |
455 | rewind: function rewind() {
456 | this.timer.set();
457 | this.loopCount = 0;
458 | this.frame = 0;
459 | this.tile = this.sequence[0];
460 | return this;
461 | },
462 |
463 | gotoFrame: function gotoFrame(f) {
464 | // Offset the timer by one tenth of a millisecond to make sure we
465 | // jump to the correct frame and circumvent rounding errors
466 | this.timer.set(this.frameTime * -f - 0.0001);
467 | this.update();
468 | },
469 |
470 | gotoRandomFrame: function gotoRandomFrame() {
471 | this.gotoFrame(Math.floor(Math.random() * this.sequence.length));
472 | },
473 |
474 | update: function update() {
475 | var frameTotal = Math.floor(this.timer.delta() / this.frameTime);
476 | this.loopCount = Math.floor(frameTotal / this.sequence.length);
477 | if (this.stop && this.loopCount > 0) {
478 | this.frame = this.sequence.length - 1;
479 | } else {
480 | this.frame = frameTotal % this.sequence.length;
481 | }
482 | this.tile = this.sequence[this.frame];
483 | },
484 |
485 | draw: function draw(targetX, targetY) {
486 | var bbsize = Math.max(this.sheet.width, this.sheet.height);
487 |
488 | // On screen?
489 | if (targetX > ig.system.width || targetY > ig.system.height || targetX + bbsize < 0 || targetY + bbsize < 0) {
490 | return;
491 | }
492 |
493 | if (this.alpha != 1) {
494 | ig.system.context.globalAlpha = this.alpha;
495 | }
496 |
497 | if (this.angle == 0) {
498 | this.sheet.image.drawTile(targetX, targetY, this.tile, this.sheet.width, this.sheet.height, this.flip.x, this.flip.y);
499 | } else {
500 | ig.system.context.save();
501 | ig.system.context.translate(ig.system.getDrawPos(targetX + this.pivot.x), ig.system.getDrawPos(targetY + this.pivot.y));
502 | ig.system.context.rotate(this.angle);
503 | this.sheet.image.drawTile(-this.pivot.x, -this.pivot.y, this.tile, this.sheet.width, this.sheet.height, this.flip.x, this.flip.y);
504 | ig.system.context.restore();
505 | }
506 |
507 | if (this.alpha != 1) {
508 | ig.system.context.globalAlpha = 1;
509 | }
510 | }
511 | });
512 | });
513 | }.call(window));
514 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(/*! ig */ 1)))
515 |
516 | /***/ },
517 | /* 6 */
518 | /*!**************************************!*\
519 | !*** ./lib/impact/background-map.js ***!
520 | \**************************************/
521 | /***/ function(module, exports, __webpack_require__) {
522 |
523 | /* WEBPACK VAR INJECTION */(function(ig) {/*** IMPORTS FROM imports-loader ***/
524 | (function() {
525 |
526 | 'use strict';
527 |
528 | ig.module('impact.background-map').requires('impact.map', 'impact.image').defines(function () {
529 | "use strict";
530 |
531 | ig.BackgroundMap = ig.Map.extend({
532 | tiles: null,
533 | scroll: { x: 0, y: 0 },
534 | distance: 1,
535 | repeat: false,
536 | tilesetName: '',
537 | foreground: false,
538 | enabled: true,
539 |
540 | preRender: false,
541 | preRenderedChunks: null,
542 | chunkSize: 512,
543 | debugChunks: false,
544 |
545 | anims: {},
546 |
547 | init: function init(tilesize, data, tileset) {
548 | this.parent(tilesize, data);
549 | this.setTileset(tileset);
550 | },
551 |
552 | setTileset: function setTileset(tileset) {
553 | this.tilesetName = tileset instanceof ig.Image ? tileset.path : tileset;
554 | this.tiles = new ig.Image(this.tilesetName);
555 | this.preRenderedChunks = null;
556 | },
557 |
558 | setScreenPos: function setScreenPos(x, y) {
559 | this.scroll.x = x / this.distance;
560 | this.scroll.y = y / this.distance;
561 | },
562 |
563 | preRenderMapToChunks: function preRenderMapToChunks() {
564 | var totalWidth = this.width * this.tilesize * ig.system.scale,
565 | totalHeight = this.height * this.tilesize * ig.system.scale;
566 |
567 | // If this layer is smaller than the chunkSize, adjust the chunkSize
568 | // accordingly, so we don't have as much overdraw
569 | this.chunkSize = Math.min(Math.max(totalWidth, totalHeight), this.chunkSize);
570 |
571 | var chunkCols = Math.ceil(totalWidth / this.chunkSize),
572 | chunkRows = Math.ceil(totalHeight / this.chunkSize);
573 |
574 | this.preRenderedChunks = [];
575 | for (var y = 0; y < chunkRows; y++) {
576 | this.preRenderedChunks[y] = [];
577 |
578 | for (var x = 0; x < chunkCols; x++) {
579 |
580 | var chunkWidth = x == chunkCols - 1 ? totalWidth - x * this.chunkSize : this.chunkSize;
581 |
582 | var chunkHeight = y == chunkRows - 1 ? totalHeight - y * this.chunkSize : this.chunkSize;
583 |
584 | this.preRenderedChunks[y][x] = this.preRenderChunk(x, y, chunkWidth, chunkHeight);
585 | }
586 | }
587 | },
588 |
589 | preRenderChunk: function preRenderChunk(cx, cy, w, h) {
590 | var tw = w / this.tilesize / ig.system.scale + 1,
591 | th = h / this.tilesize / ig.system.scale + 1;
592 |
593 | var nx = cx * this.chunkSize / ig.system.scale % this.tilesize,
594 | ny = cy * this.chunkSize / ig.system.scale % this.tilesize;
595 |
596 | var tx = Math.floor(cx * this.chunkSize / this.tilesize / ig.system.scale),
597 | ty = Math.floor(cy * this.chunkSize / this.tilesize / ig.system.scale);
598 |
599 | var chunk = ig.$new('canvas');
600 | chunk.width = w;
601 | chunk.height = h;
602 | chunk.retinaResolutionEnabled = false; // Opt out for Ejecta
603 |
604 | var chunkContext = chunk.getContext('2d');
605 | ig.System.scaleMode(chunk, chunkContext);
606 |
607 | var screenContext = ig.system.context;
608 | ig.system.context = chunkContext;
609 |
610 | for (var x = 0; x < tw; x++) {
611 | for (var y = 0; y < th; y++) {
612 | if (x + tx < this.width && y + ty < this.height) {
613 | var tile = this.data[y + ty][x + tx];
614 | if (tile) {
615 | this.tiles.drawTile(x * this.tilesize - nx, y * this.tilesize - ny, tile - 1, this.tilesize);
616 | }
617 | }
618 | }
619 | }
620 | ig.system.context = screenContext;
621 |
622 | return chunk;
623 | },
624 |
625 | draw: function draw() {
626 | if (!this.tiles.loaded || !this.enabled) {
627 | return;
628 | }
629 |
630 | if (this.preRender) {
631 | this.drawPreRendered();
632 | } else {
633 | this.drawTiled();
634 | }
635 | },
636 |
637 | drawPreRendered: function drawPreRendered() {
638 | if (!this.preRenderedChunks) {
639 | this.preRenderMapToChunks();
640 | }
641 |
642 | var dx = ig.system.getDrawPos(this.scroll.x),
643 | dy = ig.system.getDrawPos(this.scroll.y);
644 |
645 | if (this.repeat) {
646 | var w = this.width * this.tilesize * ig.system.scale;
647 | dx = (dx % w + w) % w;
648 |
649 | var h = this.height * this.tilesize * ig.system.scale;
650 | dy = (dy % h + h) % h;
651 | }
652 |
653 | var minChunkX = Math.max(Math.floor(dx / this.chunkSize), 0),
654 | minChunkY = Math.max(Math.floor(dy / this.chunkSize), 0),
655 | maxChunkX = Math.ceil((dx + ig.system.realWidth) / this.chunkSize),
656 | maxChunkY = Math.ceil((dy + ig.system.realHeight) / this.chunkSize),
657 | maxRealChunkX = this.preRenderedChunks[0].length,
658 | maxRealChunkY = this.preRenderedChunks.length;
659 |
660 | if (!this.repeat) {
661 | maxChunkX = Math.min(maxChunkX, maxRealChunkX);
662 | maxChunkY = Math.min(maxChunkY, maxRealChunkY);
663 | }
664 |
665 | var nudgeY = 0;
666 | for (var cy = minChunkY; cy < maxChunkY; cy++) {
667 |
668 | var nudgeX = 0;
669 | for (var cx = minChunkX; cx < maxChunkX; cx++) {
670 | var chunk = this.preRenderedChunks[cy % maxRealChunkY][cx % maxRealChunkX];
671 |
672 | var x = -dx + cx * this.chunkSize - nudgeX;
673 | var y = -dy + cy * this.chunkSize - nudgeY;
674 | ig.system.context.drawImage(chunk, x, y);
675 | ig.Image.drawCount++;
676 |
677 | if (this.debugChunks) {
678 | ig.system.context.strokeStyle = '#f0f';
679 | ig.system.context.strokeRect(x, y, this.chunkSize, this.chunkSize);
680 | }
681 |
682 | // If we repeat in X and this chunk's width wasn't the full chunk size
683 | // and the screen is not already filled, we need to draw anohter chunk
684 | // AND nudge it to be flush with the last chunk
685 | if (this.repeat && chunk.width < this.chunkSize && x + chunk.width < ig.system.realWidth) {
686 | nudgeX += this.chunkSize - chunk.width;
687 | maxChunkX++;
688 | }
689 | }
690 |
691 | // Same as above, but for Y
692 | if (this.repeat && chunk.height < this.chunkSize && y + chunk.height < ig.system.realHeight) {
693 | nudgeY += this.chunkSize - chunk.height;
694 | maxChunkY++;
695 | }
696 | }
697 | },
698 |
699 | drawTiled: function drawTiled() {
700 | var tile = 0,
701 | anim = null,
702 | tileOffsetX = (this.scroll.x / this.tilesize).toInt(),
703 | tileOffsetY = (this.scroll.y / this.tilesize).toInt(),
704 | pxOffsetX = this.scroll.x % this.tilesize,
705 | pxOffsetY = this.scroll.y % this.tilesize,
706 | pxMinX = -pxOffsetX - this.tilesize,
707 | pxMinY = -pxOffsetY - this.tilesize,
708 | pxMaxX = ig.system.width + this.tilesize - pxOffsetX,
709 | pxMaxY = ig.system.height + this.tilesize - pxOffsetY;
710 |
711 | // FIXME: could be sped up for non-repeated maps: restrict the for loops
712 | // to the map size instead of to the screen size and skip the 'repeat'
713 | // checks inside the loop.
714 |
715 | for (var mapY = -1, pxY = pxMinY; pxY < pxMaxY; mapY++, pxY += this.tilesize) {
716 | var tileY = mapY + tileOffsetY;
717 |
718 | // Repeat Y?
719 | if (tileY >= this.height || tileY < 0) {
720 | if (!this.repeat) {
721 | continue;
722 | }
723 | tileY = (tileY % this.height + this.height) % this.height;
724 | }
725 |
726 | for (var mapX = -1, pxX = pxMinX; pxX < pxMaxX; mapX++, pxX += this.tilesize) {
727 | var tileX = mapX + tileOffsetX;
728 |
729 | // Repeat X?
730 | if (tileX >= this.width || tileX < 0) {
731 | if (!this.repeat) {
732 | continue;
733 | }
734 | tileX = (tileX % this.width + this.width) % this.width;
735 | }
736 |
737 | // Draw!
738 | if (tile = this.data[tileY][tileX]) {
739 | if (anim = this.anims[tile - 1]) {
740 | anim.draw(pxX, pxY);
741 | } else {
742 | this.tiles.drawTile(pxX, pxY, tile - 1, this.tilesize);
743 | }
744 | }
745 | } // end for x
746 | } // end for y
747 | }
748 | });
749 | });
750 | }.call(window));
751 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(/*! ig */ 1)))
752 |
753 | /***/ },
754 | /* 7 */
755 | /*!*************************************!*\
756 | !*** ./lib/impact/collision-map.js ***!
757 | \*************************************/
758 | /***/ function(module, exports, __webpack_require__) {
759 |
760 | /* WEBPACK VAR INJECTION */(function(ig) {/*** IMPORTS FROM imports-loader ***/
761 | (function() {
762 |
763 | 'use strict';
764 |
765 | ig.module('impact.collision-map').requires('impact.map').defines(function () {
766 | "use strict";
767 |
768 | ig.CollisionMap = ig.Map.extend({
769 |
770 | lastSlope: 1,
771 | tiledef: null,
772 |
773 | init: function init(tilesize, data, tiledef) {
774 | this.parent(tilesize, data);
775 | this.tiledef = tiledef || ig.CollisionMap.defaultTileDef;
776 |
777 | for (var t in this.tiledef) {
778 | if (t | 0 > this.lastSlope) {
779 | this.lastSlope = t | 0;
780 | }
781 | }
782 | },
783 |
784 | trace: function trace(x, y, vx, vy, objectWidth, objectHeight) {
785 | // Set up the trace-result
786 | var res = {
787 | collision: { x: false, y: false, slope: false },
788 | pos: { x: x, y: y },
789 | tile: { x: 0, y: 0 }
790 | };
791 |
792 | // Break the trace down into smaller steps if necessary
793 | var steps = Math.ceil(Math.max(Math.abs(vx), Math.abs(vy)) / this.tilesize);
794 | if (steps > 1) {
795 | var sx = vx / steps;
796 | var sy = vy / steps;
797 |
798 | for (var i = 0; i < steps && (sx || sy); i++) {
799 | this._traceStep(res, x, y, sx, sy, objectWidth, objectHeight, vx, vy, i);
800 |
801 | x = res.pos.x;
802 | y = res.pos.y;
803 | if (res.collision.x) {
804 | sx = 0;vx = 0;
805 | }
806 | if (res.collision.y) {
807 | sy = 0;vy = 0;
808 | }
809 | if (res.collision.slope) {
810 | break;
811 | }
812 | }
813 | }
814 |
815 | // Just one step
816 | else {
817 | this._traceStep(res, x, y, vx, vy, objectWidth, objectHeight, vx, vy, 0);
818 | }
819 |
820 | return res;
821 | },
822 |
823 | _traceStep: function _traceStep(res, x, y, vx, vy, width, height, rvx, rvy, step) {
824 |
825 | res.pos.x += vx;
826 | res.pos.y += vy;
827 |
828 | var t = 0;
829 |
830 | // Horizontal collision (walls)
831 | if (vx) {
832 | var pxOffsetX = vx > 0 ? width : 0;
833 | var tileOffsetX = vx < 0 ? this.tilesize : 0;
834 |
835 | var firstTileY = Math.max(Math.floor(y / this.tilesize), 0);
836 | var lastTileY = Math.min(Math.ceil((y + height) / this.tilesize), this.height);
837 | var tileX = Math.floor((res.pos.x + pxOffsetX) / this.tilesize);
838 |
839 | // We need to test the new tile position as well as the current one, as we
840 | // could still collide with the current tile if it's a line def.
841 | // We can skip this test if this is not the first step or the new tile position
842 | // is the same as the current one.
843 | var prevTileX = Math.floor((x + pxOffsetX) / this.tilesize);
844 | if (step > 0 || tileX == prevTileX || prevTileX < 0 || prevTileX >= this.width) {
845 | prevTileX = -1;
846 | }
847 |
848 | // Still inside this collision map?
849 | if (tileX >= 0 && tileX < this.width) {
850 | for (var tileY = firstTileY; tileY < lastTileY; tileY++) {
851 | if (prevTileX != -1) {
852 | t = this.data[tileY][prevTileX];
853 | if (t > 1 && t <= this.lastSlope && this._checkTileDef(res, t, x, y, rvx, rvy, width, height, prevTileX, tileY)) {
854 | break;
855 | }
856 | }
857 |
858 | t = this.data[tileY][tileX];
859 | if (t == 1 || t > this.lastSlope || // fully solid tile?
860 | t > 1 && this._checkTileDef(res, t, x, y, rvx, rvy, width, height, tileX, tileY) // slope?
861 | ) {
862 | if (t > 1 && t <= this.lastSlope && res.collision.slope) {
863 | break;
864 | }
865 |
866 | // full tile collision!
867 | res.collision.x = true;
868 | res.tile.x = t;
869 | x = res.pos.x = tileX * this.tilesize - pxOffsetX + tileOffsetX;
870 | rvx = 0;
871 | break;
872 | }
873 | }
874 | }
875 | }
876 |
877 | // Vertical collision (floor, ceiling)
878 | if (vy) {
879 | var pxOffsetY = vy > 0 ? height : 0;
880 | var tileOffsetY = vy < 0 ? this.tilesize : 0;
881 |
882 | var firstTileX = Math.max(Math.floor(res.pos.x / this.tilesize), 0);
883 | var lastTileX = Math.min(Math.ceil((res.pos.x + width) / this.tilesize), this.width);
884 | var tileY = Math.floor((res.pos.y + pxOffsetY) / this.tilesize);
885 |
886 | var prevTileY = Math.floor((y + pxOffsetY) / this.tilesize);
887 | if (step > 0 || tileY == prevTileY || prevTileY < 0 || prevTileY >= this.height) {
888 | prevTileY = -1;
889 | }
890 |
891 | // Still inside this collision map?
892 | if (tileY >= 0 && tileY < this.height) {
893 | for (var tileX = firstTileX; tileX < lastTileX; tileX++) {
894 | if (prevTileY != -1) {
895 | t = this.data[prevTileY][tileX];
896 | if (t > 1 && t <= this.lastSlope && this._checkTileDef(res, t, x, y, rvx, rvy, width, height, tileX, prevTileY)) {
897 | break;
898 | }
899 | }
900 |
901 | t = this.data[tileY][tileX];
902 | if (t == 1 || t > this.lastSlope || // fully solid tile?
903 | t > 1 && this._checkTileDef(res, t, x, y, rvx, rvy, width, height, tileX, tileY) // slope?
904 | ) {
905 | if (t > 1 && t <= this.lastSlope && res.collision.slope) {
906 | break;
907 | }
908 |
909 | // full tile collision!
910 | res.collision.y = true;
911 | res.tile.y = t;
912 | res.pos.y = tileY * this.tilesize - pxOffsetY + tileOffsetY;
913 | break;
914 | }
915 | }
916 | }
917 | }
918 |
919 | // res is changed in place, nothing to return
920 | },
921 |
922 | _checkTileDef: function _checkTileDef(res, t, x, y, vx, vy, width, height, tileX, tileY) {
923 | var def = this.tiledef[t];
924 | if (!def) {
925 | return false;
926 | }
927 |
928 | var lx = (tileX + def[0]) * this.tilesize,
929 | ly = (tileY + def[1]) * this.tilesize,
930 | lvx = (def[2] - def[0]) * this.tilesize,
931 | lvy = (def[3] - def[1]) * this.tilesize,
932 | solid = def[4];
933 |
934 | // Find the box corner to test, relative to the line
935 | var tx = x + vx + (lvy < 0 ? width : 0) - lx,
936 | ty = y + vy + (lvx > 0 ? height : 0) - ly;
937 |
938 | // Is the box corner behind the line?
939 | if (lvx * ty - lvy * tx > 0) {
940 |
941 | // Lines are only solid from one side - find the dot product of
942 | // line normal and movement vector and dismiss if wrong side
943 | if (vx * -lvy + vy * lvx < 0) {
944 | return solid;
945 | }
946 |
947 | // Find the line normal
948 | var length = Math.sqrt(lvx * lvx + lvy * lvy);
949 | var nx = lvy / length,
950 | ny = -lvx / length;
951 |
952 | // Project out of the line
953 | var proj = tx * nx + ty * ny;
954 | var px = nx * proj,
955 | py = ny * proj;
956 |
957 | // If we project further out than we moved in, then this is a full
958 | // tile collision for solid tiles.
959 | // For non-solid tiles, make sure we were in front of the line.
960 | if (px * px + py * py >= vx * vx + vy * vy) {
961 | return solid || lvx * (ty - vy) - lvy * (tx - vx) < 0.5;
962 | }
963 |
964 | res.pos.x = x + vx - px;
965 | res.pos.y = y + vy - py;
966 | res.collision.slope = { x: lvx, y: lvy, nx: nx, ny: ny };
967 | return true;
968 | }
969 |
970 | return false;
971 | }
972 | });
973 |
974 | // Default Slope Tile definition. Each tile is defined by an array of 5 vars:
975 | // - 4 for the line in tile coordinates (0 -- 1)
976 | // - 1 specifing whether the tile is 'filled' behind the line or not
977 | // [ x1, y1, x2, y2, solid ]
978 |
979 | // Defining 'half', 'one third' and 'two thirds' as vars makes it a bit
980 | // easier to read... I hope.
981 | var H = 1 / 2,
982 | N = 1 / 3,
983 | M = 2 / 3,
984 | SOLID = true,
985 | NON_SOLID = false;
986 |
987 | ig.CollisionMap.defaultTileDef = {
988 | /* 15 NE */5: [0, 1, 1, M, SOLID], 6: [0, M, 1, N, SOLID], 7: [0, N, 1, 0, SOLID],
989 | /* 22 NE */3: [0, 1, 1, H, SOLID], 4: [0, H, 1, 0, SOLID],
990 | /* 45 NE */2: [0, 1, 1, 0, SOLID],
991 | /* 67 NE */10: [H, 1, 1, 0, SOLID], 21: [0, 1, H, 0, SOLID],
992 | /* 75 NE */32: [M, 1, 1, 0, SOLID], 43: [N, 1, M, 0, SOLID], 54: [0, 1, N, 0, SOLID],
993 |
994 | /* 15 SE */27: [0, 0, 1, N, SOLID], 28: [0, N, 1, M, SOLID], 29: [0, M, 1, 1, SOLID],
995 | /* 22 SE */25: [0, 0, 1, H, SOLID], 26: [0, H, 1, 1, SOLID],
996 | /* 45 SE */24: [0, 0, 1, 1, SOLID],
997 | /* 67 SE */11: [0, 0, H, 1, SOLID], 22: [H, 0, 1, 1, SOLID],
998 | /* 75 SE */33: [0, 0, N, 1, SOLID], 44: [N, 0, M, 1, SOLID], 55: [M, 0, 1, 1, SOLID],
999 |
1000 | /* 15 NW */16: [1, N, 0, 0, SOLID], 17: [1, M, 0, N, SOLID], 18: [1, 1, 0, M, SOLID],
1001 | /* 22 NW */14: [1, H, 0, 0, SOLID], 15: [1, 1, 0, H, SOLID],
1002 | /* 45 NW */13: [1, 1, 0, 0, SOLID],
1003 | /* 67 NW */8: [H, 1, 0, 0, SOLID], 19: [1, 1, H, 0, SOLID],
1004 | /* 75 NW */30: [N, 1, 0, 0, SOLID], 41: [M, 1, N, 0, SOLID], 52: [1, 1, M, 0, SOLID],
1005 |
1006 | /* 15 SW */38: [1, M, 0, 1, SOLID], 39: [1, N, 0, M, SOLID], 40: [1, 0, 0, N, SOLID],
1007 | /* 22 SW */36: [1, H, 0, 1, SOLID], 37: [1, 0, 0, H, SOLID],
1008 | /* 45 SW */35: [1, 0, 0, 1, SOLID],
1009 | /* 67 SW */9: [1, 0, H, 1, SOLID], 20: [H, 0, 0, 1, SOLID],
1010 | /* 75 SW */31: [1, 0, M, 1, SOLID], 42: [M, 0, N, 1, SOLID], 53: [N, 0, 0, 1, SOLID],
1011 |
1012 | /* Go N */12: [0, 0, 1, 0, NON_SOLID],
1013 | /* Go S */23: [1, 1, 0, 1, NON_SOLID],
1014 | /* Go E */34: [1, 0, 1, 1, NON_SOLID],
1015 | /* Go W */45: [0, 1, 0, 0, NON_SOLID]
1016 |
1017 | // Now that was fun!
1018 | };
1019 |
1020 | // Static Dummy CollisionMap; never collides
1021 | ig.CollisionMap.staticNoCollision = { trace: function trace(x, y, vx, vy) {
1022 | return {
1023 | collision: { x: false, y: false, slope: false },
1024 | pos: { x: x + vx, y: y + vy },
1025 | tile: { x: 0, y: 0 }
1026 | };
1027 | } };
1028 | });
1029 | }.call(window));
1030 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(/*! ig */ 1)))
1031 |
1032 | /***/ },
1033 | /* 8 */
1034 | /*!***********************************!*\
1035 | !*** ./lib/impact/debug/debug.js ***!
1036 | \***********************************/
1037 | /***/ function(module, exports, __webpack_require__) {
1038 |
1039 | /* WEBPACK VAR INJECTION */(function(ig) {/*** IMPORTS FROM imports-loader ***/
1040 | (function() {
1041 |
1042 | 'use strict';
1043 |
1044 | ig.module('impact.debug.debug').requires('impact.debug.entities-panel', 'impact.debug.maps-panel', 'impact.debug.graph-panel').defines(function () {});
1045 | }.call(window));
1046 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(/*! ig */ 1)))
1047 |
1048 | /***/ },
1049 | /* 9 */
1050 | /*!********************************************!*\
1051 | !*** ./lib/impact/debug/entities-panel.js ***!
1052 | \********************************************/
1053 | /***/ function(module, exports, __webpack_require__) {
1054 |
1055 | /* WEBPACK VAR INJECTION */(function(ig) {/*** IMPORTS FROM imports-loader ***/
1056 | (function() {
1057 |
1058 | 'use strict';
1059 |
1060 | var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
1061 |
1062 | ig.module('impact.debug.entities-panel').requires('impact.debug.menu', 'impact.entity').defines(function () {
1063 | "use strict";
1064 |
1065 | ig.Entity.inject({
1066 | colors: {
1067 | names: '#fff',
1068 | velocities: '#0f0',
1069 | boxes: '#f00'
1070 | },
1071 |
1072 | draw: function draw() {
1073 | this.parent();
1074 |
1075 | // Collision Boxes
1076 | if (ig.Entity._debugShowBoxes) {
1077 | ig.system.context.strokeStyle = this.colors.boxes;
1078 | ig.system.context.lineWidth = 1.0;
1079 | ig.system.context.strokeRect(ig.system.getDrawPos(this.pos.x.round() - ig.game.screen.x) - 0.5, ig.system.getDrawPos(this.pos.y.round() - ig.game.screen.y) - 0.5, this.size.x * ig.system.scale, this.size.y * ig.system.scale);
1080 | }
1081 |
1082 | // Velocities
1083 | if (ig.Entity._debugShowVelocities) {
1084 | var x = this.pos.x + this.size.x / 2;
1085 | var y = this.pos.y + this.size.y / 2;
1086 |
1087 | this._debugDrawLine(this.colors.velocities, x, y, x + this.vel.x, y + this.vel.y);
1088 | }
1089 |
1090 | // Names & Targets
1091 | if (ig.Entity._debugShowNames) {
1092 | if (this.name) {
1093 | ig.system.context.fillStyle = this.colors.names;
1094 | ig.system.context.fillText(this.name, ig.system.getDrawPos(this.pos.x - ig.game.screen.x), ig.system.getDrawPos(this.pos.y - ig.game.screen.y));
1095 | }
1096 |
1097 | if (_typeof(this.target) == 'object') {
1098 | for (var t in this.target) {
1099 | var ent = ig.game.getEntityByName(this.target[t]);
1100 | if (ent) {
1101 | this._debugDrawLine(this.colors.names, this.pos.x + this.size.x / 2, this.pos.y + this.size.y / 2, ent.pos.x + ent.size.x / 2, ent.pos.y + ent.size.y / 2);
1102 | }
1103 | }
1104 | }
1105 | }
1106 | },
1107 |
1108 | _debugDrawLine: function _debugDrawLine(color, sx, sy, dx, dy) {
1109 | ig.system.context.strokeStyle = color;
1110 | ig.system.context.lineWidth = 1.0;
1111 |
1112 | ig.system.context.beginPath();
1113 | ig.system.context.moveTo(ig.system.getDrawPos(sx - ig.game.screen.x), ig.system.getDrawPos(sy - ig.game.screen.y));
1114 | ig.system.context.lineTo(ig.system.getDrawPos(dx - ig.game.screen.x), ig.system.getDrawPos(dy - ig.game.screen.y));
1115 | ig.system.context.stroke();
1116 | ig.system.context.closePath();
1117 | }
1118 | });
1119 |
1120 | ig.Entity._debugEnableChecks = true;
1121 | ig.Entity._debugShowBoxes = false;
1122 | ig.Entity._debugShowVelocities = false;
1123 | ig.Entity._debugShowNames = false;
1124 |
1125 | ig.Entity.oldCheckPair = ig.Entity.checkPair;
1126 | ig.Entity.checkPair = function (a, b) {
1127 | if (!ig.Entity._debugEnableChecks) {
1128 | return;
1129 | }
1130 | ig.Entity.oldCheckPair(a, b);
1131 | };
1132 |
1133 | ig.debug.addPanel({
1134 | type: ig.DebugPanel,
1135 | name: 'entities',
1136 | label: 'Entities',
1137 | options: [{
1138 | name: 'Checks & Collisions',
1139 | object: ig.Entity,
1140 | property: '_debugEnableChecks'
1141 | }, {
1142 | name: 'Show Collision Boxes',
1143 | object: ig.Entity,
1144 | property: '_debugShowBoxes'
1145 | }, {
1146 | name: 'Show Velocities',
1147 | object: ig.Entity,
1148 | property: '_debugShowVelocities'
1149 | }, {
1150 | name: 'Show Names & Targets',
1151 | object: ig.Entity,
1152 | property: '_debugShowNames'
1153 | }]
1154 | });
1155 | });
1156 | }.call(window));
1157 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(/*! ig */ 1)))
1158 |
1159 | /***/ },
1160 | /* 10 */
1161 | /*!*****************************************!*\
1162 | !*** ./lib/impact/debug/graph-panel.js ***!
1163 | \*****************************************/
1164 | /***/ function(module, exports, __webpack_require__) {
1165 |
1166 | /* WEBPACK VAR INJECTION */(function(ig) {/*** IMPORTS FROM imports-loader ***/
1167 | (function() {
1168 |
1169 | 'use strict';
1170 |
1171 | ig.module('impact.debug.graph-panel').requires('impact.debug.menu', 'impact.system', 'impact.game', 'impact.image').defines(function () {
1172 | "use strict";
1173 |
1174 | ig.Game.inject({
1175 | draw: function draw() {
1176 | ig.graph.beginClock('draw');
1177 | this.parent();
1178 | ig.graph.endClock('draw');
1179 | },
1180 |
1181 | update: function update() {
1182 | ig.graph.beginClock('update');
1183 | this.parent();
1184 | ig.graph.endClock('update');
1185 | },
1186 |
1187 | checkEntities: function checkEntities() {
1188 | ig.graph.beginClock('checks');
1189 | this.parent();
1190 | ig.graph.endClock('checks');
1191 | }
1192 | });
1193 |
1194 | ig.DebugGraphPanel = ig.DebugPanel.extend({
1195 | clocks: {},
1196 | marks: [],
1197 | textY: 0,
1198 | height: 128,
1199 | ms: 64,
1200 | timeBeforeRun: 0,
1201 |
1202 | init: function init(name, label) {
1203 | this.parent(name, label);
1204 |
1205 | this.mark16ms = (this.height - this.height / this.ms * 16).round();
1206 | this.mark33ms = (this.height - this.height / this.ms * 33).round();
1207 | this.msHeight = this.height / this.ms;
1208 |
1209 | this.graph = ig.$new('canvas');
1210 | this.graph.width = window.innerWidth;
1211 | this.graph.height = this.height;
1212 | this.container.appendChild(this.graph);
1213 | this.ctx = this.graph.getContext('2d');
1214 |
1215 | this.ctx.fillStyle = '#444';
1216 | this.ctx.fillRect(0, this.mark16ms, this.graph.width, 1);
1217 | this.ctx.fillRect(0, this.mark33ms, this.graph.width, 1);
1218 |
1219 | this.addGraphMark('16ms', this.mark16ms);
1220 | this.addGraphMark('33ms', this.mark33ms);
1221 |
1222 | this.addClock('draw', 'Draw', '#13baff');
1223 | this.addClock('update', 'Entity Update', '#bb0fff');
1224 | this.addClock('checks', 'Entity Checks & Collisions', '#a2e908');
1225 | this.addClock('lag', 'System Lag', '#f26900');
1226 |
1227 | ig.mark = this.mark.bind(this);
1228 | ig.graph = this;
1229 | },
1230 |
1231 | addGraphMark: function addGraphMark(name, height) {
1232 | var span = ig.$new('span');
1233 | span.className = 'ig_debug_graph_mark';
1234 | span.textContent = name;
1235 | span.style.top = height.round() + 'px';
1236 | this.container.appendChild(span);
1237 | },
1238 |
1239 | addClock: function addClock(name, description, color) {
1240 | var mark = ig.$new('span');
1241 | mark.className = 'ig_debug_legend_color';
1242 | mark.style.backgroundColor = color;
1243 |
1244 | var number = ig.$new('span');
1245 | number.className = 'ig_debug_legend_number';
1246 | number.appendChild(document.createTextNode('0'));
1247 |
1248 | var legend = ig.$new('span');
1249 | legend.className = 'ig_debug_legend';
1250 | legend.appendChild(mark);
1251 | legend.appendChild(document.createTextNode(description + ' ('));
1252 | legend.appendChild(number);
1253 | legend.appendChild(document.createTextNode('ms)'));
1254 |
1255 | this.container.appendChild(legend);
1256 |
1257 | this.clocks[name] = {
1258 | description: description,
1259 | color: color,
1260 | current: 0,
1261 | start: Date.now(),
1262 | avg: 0,
1263 | html: number
1264 | };
1265 | },
1266 |
1267 | beginClock: function beginClock(name, offset) {
1268 | this.clocks[name].start = Date.now() + (offset || 0);
1269 | },
1270 |
1271 | endClock: function endClock(name) {
1272 | var c = this.clocks[name];
1273 | c.current = Math.round(Date.now() - c.start);
1274 | c.avg = c.avg * 0.8 + c.current * 0.2;
1275 | },
1276 |
1277 | mark: function mark(msg, color) {
1278 | if (this.active) {
1279 | this.marks.push({ msg: msg, color: color || '#fff' });
1280 | }
1281 | },
1282 |
1283 | beforeRun: function beforeRun() {
1284 | this.endClock('lag');
1285 | this.timeBeforeRun = Date.now();
1286 | },
1287 |
1288 | afterRun: function afterRun() {
1289 | var frameTime = Date.now() - this.timeBeforeRun;
1290 | var nextFrameDue = 1000 / ig.system.fps - frameTime;
1291 | this.beginClock('lag', Math.max(nextFrameDue, 0));
1292 |
1293 | var x = this.graph.width - 1;
1294 | var y = this.height;
1295 |
1296 | this.ctx.drawImage(this.graph, -1, 0);
1297 |
1298 | this.ctx.fillStyle = '#000';
1299 | this.ctx.fillRect(x, 0, 1, this.height);
1300 |
1301 | this.ctx.fillStyle = '#444';
1302 | this.ctx.fillRect(x, this.mark16ms, 1, 1);
1303 |
1304 | this.ctx.fillStyle = '#444';
1305 | this.ctx.fillRect(x, this.mark33ms, 1, 1);
1306 |
1307 | for (var ci in this.clocks) {
1308 | var c = this.clocks[ci];
1309 | c.html.textContent = c.avg.toFixed(2);
1310 |
1311 | if (c.color && c.current > 0) {
1312 | this.ctx.fillStyle = c.color;
1313 | var h = c.current * this.msHeight;
1314 | y -= h;
1315 | this.ctx.fillRect(x, y, 1, h);
1316 | c.current = 0;
1317 | }
1318 | }
1319 |
1320 | this.ctx.textAlign = 'right';
1321 | this.ctx.textBaseline = 'top';
1322 | this.ctx.globalAlpha = 0.5;
1323 |
1324 | for (var i = 0; i < this.marks.length; i++) {
1325 | var m = this.marks[i];
1326 | this.ctx.fillStyle = m.color;
1327 | this.ctx.fillRect(x, 0, 1, this.height);
1328 | if (m.msg) {
1329 | this.ctx.fillText(m.msg, x - 1, this.textY);
1330 | this.textY = (this.textY + 8) % 32;
1331 | }
1332 | }
1333 | this.ctx.globalAlpha = 1;
1334 | this.marks = [];
1335 | }
1336 | });
1337 |
1338 | ig.debug.addPanel({
1339 | type: ig.DebugGraphPanel,
1340 | name: 'graph',
1341 | label: 'Performance'
1342 | });
1343 | });
1344 | }.call(window));
1345 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(/*! ig */ 1)))
1346 |
1347 | /***/ },
1348 | /* 11 */
1349 | /*!****************************************!*\
1350 | !*** ./lib/impact/debug/maps-panel.js ***!
1351 | \****************************************/
1352 | /***/ function(module, exports, __webpack_require__) {
1353 |
1354 | /* WEBPACK VAR INJECTION */(function(ig) {/*** IMPORTS FROM imports-loader ***/
1355 | (function() {
1356 |
1357 | 'use strict';
1358 |
1359 | ig.module('impact.debug.maps-panel').requires('impact.debug.menu', 'impact.game', 'impact.background-map').defines(function () {
1360 | "use strict";
1361 |
1362 | ig.Game.inject({
1363 | loadLevel: function loadLevel(data) {
1364 | this.parent(data);
1365 | ig.debug.panels.maps.load(this);
1366 | }
1367 | });
1368 |
1369 | ig.DebugMapsPanel = ig.DebugPanel.extend({
1370 | maps: [],
1371 | mapScreens: [],
1372 |
1373 | init: function init(name, label) {
1374 | this.parent(name, label);
1375 | this.load();
1376 | },
1377 |
1378 | load: function load(game) {
1379 | this.options = [];
1380 | this.panels = [];
1381 |
1382 | if (!game || !game.backgroundMaps.length) {
1383 | this.container.innerHTML = 'No Maps Loaded';
1384 | return;
1385 | }
1386 |
1387 | this.maps = game.backgroundMaps;
1388 | this.mapScreens = [];
1389 | this.container.innerHTML = '';
1390 |
1391 | for (var m = 0; m < this.maps.length; m++) {
1392 | var map = this.maps[m];
1393 |
1394 | var subPanel = new ig.DebugPanel(m, 'Layer ' + m);
1395 |
1396 | var head = new ig.$new('strong');
1397 | head.textContent = m + ': ' + map.tiles.path;
1398 | subPanel.container.appendChild(head);
1399 |
1400 | subPanel.addOption(new ig.DebugOption('Enabled', map, 'enabled'));
1401 | subPanel.addOption(new ig.DebugOption('Pre Rendered', map, 'preRender'));
1402 | subPanel.addOption(new ig.DebugOption('Show Chunks', map, 'debugChunks'));
1403 |
1404 | this.generateMiniMap(subPanel, map, m);
1405 | this.addPanel(subPanel);
1406 | }
1407 | },
1408 |
1409 | generateMiniMap: function generateMiniMap(panel, map, id) {
1410 | var s = ig.system.scale; // we'll need this a lot
1411 |
1412 | // resize the tileset, so that one tile is 's' pixels wide and high
1413 | var ts = ig.$new('canvas');
1414 | var tsctx = ts.getContext('2d');
1415 |
1416 | var w = map.tiles.width * s;
1417 | var h = map.tiles.height * s;
1418 | var ws = w / map.tilesize;
1419 | var hs = h / map.tilesize;
1420 | ts.width = ws;
1421 | ts.height = hs;
1422 | tsctx.drawImage(map.tiles.data, 0, 0, w, h, 0, 0, ws, hs);
1423 |
1424 | // create the minimap canvas
1425 | var mapCanvas = ig.$new('canvas');
1426 | mapCanvas.width = map.width * s;
1427 | mapCanvas.height = map.height * s;
1428 | var ctx = mapCanvas.getContext('2d');
1429 |
1430 | if (ig.game.clearColor) {
1431 | ctx.fillStyle = ig.game.clearColor;
1432 | ctx.fillRect(0, 0, w, h);
1433 | }
1434 |
1435 | // draw the map
1436 | var tile = 0;
1437 | for (var x = 0; x < map.width; x++) {
1438 | for (var y = 0; y < map.height; y++) {
1439 | if (tile = map.data[y][x]) {
1440 | ctx.drawImage(ts, Math.floor((tile - 1) * s % ws), Math.floor((tile - 1) * s / ws) * s, s, s, x * s, y * s, s, s);
1441 | }
1442 | }
1443 | }
1444 |
1445 | var mapContainer = ig.$new('div');
1446 | mapContainer.className = 'ig_debug_map_container';
1447 | mapContainer.style.width = map.width * s + 'px';
1448 | mapContainer.style.height = map.height * s + 'px';
1449 |
1450 | var mapScreen = ig.$new('div');
1451 | mapScreen.className = 'ig_debug_map_screen';
1452 | mapScreen.style.width = ig.system.width / map.tilesize * s - 2 + 'px';
1453 | mapScreen.style.height = ig.system.height / map.tilesize * s - 2 + 'px';
1454 | this.mapScreens[id] = mapScreen;
1455 |
1456 | mapContainer.appendChild(mapCanvas);
1457 | mapContainer.appendChild(mapScreen);
1458 | panel.container.appendChild(mapContainer);
1459 | },
1460 |
1461 | afterRun: function afterRun() {
1462 | // Update the screen position DIV for each mini-map
1463 | var s = ig.system.scale;
1464 | for (var m = 0; m < this.maps.length; m++) {
1465 | var map = this.maps[m];
1466 | var screen = this.mapScreens[m];
1467 |
1468 | if (!map || !screen) {
1469 | // Quick sanity check
1470 | continue;
1471 | }
1472 |
1473 | var x = map.scroll.x / map.tilesize;
1474 | var y = map.scroll.y / map.tilesize;
1475 |
1476 | if (map.repeat) {
1477 | x %= map.width;
1478 | y %= map.height;
1479 | }
1480 |
1481 | screen.style.left = x * s + 'px';
1482 | screen.style.top = y * s + 'px';
1483 | }
1484 | }
1485 | });
1486 |
1487 | ig.debug.addPanel({
1488 | type: ig.DebugMapsPanel,
1489 | name: 'maps',
1490 | label: 'Background Maps'
1491 | });
1492 | });
1493 | }.call(window));
1494 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(/*! ig */ 1)))
1495 |
1496 | /***/ },
1497 | /* 12 */
1498 | /*!**********************************!*\
1499 | !*** ./lib/impact/debug/menu.js ***!
1500 | \**********************************/
1501 | /***/ function(module, exports, __webpack_require__) {
1502 |
1503 | /* WEBPACK VAR INJECTION */(function(ig) {/*** IMPORTS FROM imports-loader ***/
1504 | (function() {
1505 |
1506 | 'use strict';
1507 |
1508 | ig.module('impact.debug.menu').requires('dom.ready', 'impact.system').defines(function () {
1509 | "use strict";
1510 |
1511 | ig.System.inject({
1512 | run: function run() {
1513 | ig.debug.beforeRun();
1514 | this.parent();
1515 | ig.debug.afterRun();
1516 | },
1517 |
1518 | setGameNow: function setGameNow(gameClass) {
1519 | this.parent(gameClass);
1520 | ig.debug.ready();
1521 | }
1522 | });
1523 |
1524 | ig.Debug = ig.Class.extend({
1525 | options: {},
1526 | panels: {},
1527 | numbers: {},
1528 | container: null,
1529 | panelMenu: null,
1530 | activePanel: null,
1531 |
1532 | debugTime: 0,
1533 | debugTickAvg: 0.016,
1534 | debugRealTime: Date.now(),
1535 |
1536 | init: function init() {
1537 | // Inject the Stylesheet
1538 | var style = ig.$new('link');
1539 | style.rel = 'stylesheet';
1540 | style.type = 'text/css';
1541 | style.href = ig.prefix + 'lib/impact/debug/debug.css';
1542 | ig.$('body')[0].appendChild(style);
1543 |
1544 | // Create the Debug Container
1545 | this.container = ig.$new('div');
1546 | this.container.className = 'ig_debug';
1547 | ig.$('body')[0].appendChild(this.container);
1548 |
1549 | // Create and add the Menu Container
1550 | this.panelMenu = ig.$new('div');
1551 | this.panelMenu.innerHTML = 'Impact.Debug:
';
1552 | this.panelMenu.className = 'ig_debug_panel_menu';
1553 |
1554 | this.container.appendChild(this.panelMenu);
1555 |
1556 | // Create and add the Stats Container
1557 | this.numberContainer = ig.$new('div');
1558 | this.numberContainer.className = 'ig_debug_stats';
1559 | this.panelMenu.appendChild(this.numberContainer);
1560 |
1561 | // Set ig.log(), ig.assert() and ig.show()
1562 | if (window.console && window.console.log && window.console.assert) {
1563 | // Can't use .bind() on native functions in IE9 :/
1564 | ig.log = console.log.bind ? console.log.bind(console) : console.log;
1565 | ig.assert = console.assert.bind ? console.assert.bind(console) : console.assert;
1566 | }
1567 | ig.show = this.showNumber.bind(this);
1568 | },
1569 |
1570 | addNumber: function addNumber(name, width) {
1571 | var number = ig.$new('span');
1572 | this.numberContainer.appendChild(number);
1573 | this.numberContainer.appendChild(document.createTextNode(name));
1574 |
1575 | this.numbers[name] = number;
1576 | },
1577 |
1578 | showNumber: function showNumber(name, number, width) {
1579 | if (!this.numbers[name]) {
1580 | this.addNumber(name, width);
1581 | }
1582 | this.numbers[name].textContent = number;
1583 | },
1584 |
1585 | addPanel: function addPanel(panelDef) {
1586 | // Create the panel and options
1587 | var panel = new panelDef.type(panelDef.name, panelDef.label);
1588 | if (panelDef.options) {
1589 | for (var i = 0; i < panelDef.options.length; i++) {
1590 | var opt = panelDef.options[i];
1591 | panel.addOption(new ig.DebugOption(opt.name, opt.object, opt.property));
1592 | }
1593 | }
1594 |
1595 | this.panels[panel.name] = panel;
1596 | panel.container.style.display = 'none';
1597 | this.container.appendChild(panel.container);
1598 |
1599 | // Create the menu item
1600 | var menuItem = ig.$new('div');
1601 | menuItem.className = 'ig_debug_menu_item';
1602 | menuItem.textContent = panel.label;
1603 | menuItem.addEventListener('click', function (ev) {
1604 | this.togglePanel(panel);
1605 | }.bind(this), false);
1606 | panel.menuItem = menuItem;
1607 |
1608 | // Insert menu item in alphabetical order into the menu
1609 | var inserted = false;
1610 | for (var i = 1; i < this.panelMenu.childNodes.length; i++) {
1611 | var cn = this.panelMenu.childNodes[i];
1612 | if (cn.textContent > panel.label) {
1613 | this.panelMenu.insertBefore(menuItem, cn);
1614 | inserted = true;
1615 | break;
1616 | }
1617 | }
1618 | if (!inserted) {
1619 | // Not inserted? Append at the end!
1620 | this.panelMenu.appendChild(menuItem);
1621 | }
1622 | },
1623 |
1624 | showPanel: function showPanel(name) {
1625 | this.togglePanel(this.panels[name]);
1626 | },
1627 |
1628 | togglePanel: function togglePanel(panel) {
1629 | if (panel != this.activePanel && this.activePanel) {
1630 | this.activePanel.toggle(false);
1631 | this.activePanel.menuItem.className = 'ig_debug_menu_item';
1632 | this.activePanel = null;
1633 | }
1634 |
1635 | var dsp = panel.container.style.display;
1636 | var active = dsp != 'block';
1637 | panel.toggle(active);
1638 | panel.menuItem.className = 'ig_debug_menu_item' + (active ? ' active' : '');
1639 |
1640 | if (active) {
1641 | this.activePanel = panel;
1642 | }
1643 | },
1644 |
1645 | ready: function ready() {
1646 | for (var p in this.panels) {
1647 | this.panels[p].ready();
1648 | }
1649 | },
1650 |
1651 | beforeRun: function beforeRun() {
1652 | var timeBeforeRun = Date.now();
1653 | this.debugTickAvg = this.debugTickAvg * 0.8 + (timeBeforeRun - this.debugRealTime) * 0.2;
1654 | this.debugRealTime = timeBeforeRun;
1655 |
1656 | if (this.activePanel) {
1657 | this.activePanel.beforeRun();
1658 | }
1659 | },
1660 |
1661 | afterRun: function afterRun() {
1662 | var frameTime = Date.now() - this.debugRealTime;
1663 | var nextFrameDue = 1000 / ig.system.fps - frameTime;
1664 |
1665 | this.debugTime = this.debugTime * 0.8 + frameTime * 0.2;
1666 |
1667 | if (this.activePanel) {
1668 | this.activePanel.afterRun();
1669 | }
1670 |
1671 | this.showNumber('ms', this.debugTime.toFixed(2));
1672 | this.showNumber('fps', Math.round(1000 / this.debugTickAvg));
1673 | this.showNumber('draws', ig.Image.drawCount);
1674 | if (ig.game && ig.game.entities) {
1675 | this.showNumber('entities', ig.game.entities.length);
1676 | }
1677 | ig.Image.drawCount = 0;
1678 | }
1679 | });
1680 |
1681 | ig.DebugPanel = ig.Class.extend({
1682 | active: false,
1683 | container: null,
1684 | options: [],
1685 | panels: [],
1686 | label: '',
1687 | name: '',
1688 |
1689 | init: function init(name, label) {
1690 | this.name = name;
1691 | this.label = label;
1692 | this.container = ig.$new('div');
1693 | this.container.className = 'ig_debug_panel ' + this.name;
1694 | },
1695 |
1696 | toggle: function toggle(active) {
1697 | this.active = active;
1698 | this.container.style.display = active ? 'block' : 'none';
1699 | },
1700 |
1701 | addPanel: function addPanel(panel) {
1702 | this.panels.push(panel);
1703 | this.container.appendChild(panel.container);
1704 | },
1705 |
1706 | addOption: function addOption(option) {
1707 | this.options.push(option);
1708 | this.container.appendChild(option.container);
1709 | },
1710 |
1711 | ready: function ready() {},
1712 | beforeRun: function beforeRun() {},
1713 | afterRun: function afterRun() {}
1714 | });
1715 |
1716 | ig.DebugOption = ig.Class.extend({
1717 | name: '',
1718 | labelName: '',
1719 | className: 'ig_debug_option',
1720 | label: null,
1721 | mark: null,
1722 | container: null,
1723 | active: false,
1724 |
1725 | colors: {
1726 | enabled: '#fff',
1727 | disabled: '#444'
1728 | },
1729 |
1730 | init: function init(name, object, property) {
1731 | this.name = name;
1732 | this.object = object;
1733 | this.property = property;
1734 |
1735 | this.active = this.object[this.property];
1736 |
1737 | this.container = ig.$new('div');
1738 | this.container.className = 'ig_debug_option';
1739 |
1740 | this.label = ig.$new('span');
1741 | this.label.className = 'ig_debug_label';
1742 | this.label.textContent = this.name;
1743 |
1744 | this.mark = ig.$new('span');
1745 | this.mark.className = 'ig_debug_label_mark';
1746 |
1747 | this.container.appendChild(this.mark);
1748 | this.container.appendChild(this.label);
1749 | this.container.addEventListener('click', this.click.bind(this), false);
1750 |
1751 | this.setLabel();
1752 | },
1753 |
1754 | setLabel: function setLabel() {
1755 | this.mark.style.backgroundColor = this.active ? this.colors.enabled : this.colors.disabled;
1756 | },
1757 |
1758 | click: function click(ev) {
1759 | this.active = !this.active;
1760 | this.object[this.property] = this.active;
1761 | this.setLabel();
1762 |
1763 | ev.stopPropagation();
1764 | ev.preventDefault();
1765 | return false;
1766 | }
1767 | });
1768 |
1769 | // Create the debug instance!
1770 | ig.debug = new ig.Debug();
1771 | });
1772 | }.call(window));
1773 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(/*! ig */ 1)))
1774 |
1775 | /***/ },
1776 | /* 13 */
1777 | /*!***********************************!*\
1778 | !*** ./lib/impact/entity-pool.js ***!
1779 | \***********************************/
1780 | /***/ function(module, exports, __webpack_require__) {
1781 |
1782 | /* WEBPACK VAR INJECTION */(function(ig) {/*** IMPORTS FROM imports-loader ***/
1783 | (function() {
1784 |
1785 | 'use strict';
1786 |
1787 | ig.module('impact.entity-pool').requires('impact.game').defines(function () {
1788 | "use strict";
1789 |
1790 | ig.EntityPool = {
1791 | pools: {},
1792 |
1793 | mixin: {
1794 | staticInstantiate: function staticInstantiate(x, y, settings) {
1795 | return ig.EntityPool.getFromPool(this.classId, x, y, settings);
1796 | },
1797 |
1798 | erase: function erase() {
1799 | ig.EntityPool.putInPool(this);
1800 | }
1801 | },
1802 |
1803 | enableFor: function enableFor(Class) {
1804 | Class.inject(this.mixin);
1805 | },
1806 |
1807 | getFromPool: function getFromPool(classId, x, y, settings) {
1808 | var pool = this.pools[classId];
1809 | if (!pool || !pool.length) {
1810 | return null;
1811 | }
1812 |
1813 | var instance = pool.pop();
1814 | instance.reset(x, y, settings);
1815 | return instance;
1816 | },
1817 |
1818 | putInPool: function putInPool(instance) {
1819 | if (!this.pools[instance.classId]) {
1820 | this.pools[instance.classId] = [instance];
1821 | } else {
1822 | this.pools[instance.classId].push(instance);
1823 | }
1824 | },
1825 |
1826 | drainPool: function drainPool(classId) {
1827 | delete this.pools[classId];
1828 | },
1829 |
1830 | drainAllPools: function drainAllPools() {
1831 | this.pools = {};
1832 | }
1833 | };
1834 |
1835 | ig.Game.inject({
1836 | loadLevel: function loadLevel(data) {
1837 | ig.EntityPool.drainAllPools();
1838 | this.parent(data);
1839 | }
1840 | });
1841 | });
1842 | }.call(window));
1843 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(/*! ig */ 1)))
1844 |
1845 | /***/ },
1846 | /* 14 */
1847 | /*!******************************!*\
1848 | !*** ./lib/impact/entity.js ***!
1849 | \******************************/
1850 | /***/ function(module, exports, __webpack_require__) {
1851 |
1852 | /* WEBPACK VAR INJECTION */(function(ig) {/*** IMPORTS FROM imports-loader ***/
1853 | (function() {
1854 |
1855 | 'use strict';
1856 |
1857 | ig.module('impact.entity').requires('impact.animation', 'impact.impact').defines(function () {
1858 | "use strict";
1859 |
1860 | ig.Entity = ig.Class.extend({
1861 | id: 0,
1862 | settings: {},
1863 |
1864 | size: { x: 16, y: 16 },
1865 | offset: { x: 0, y: 0 },
1866 |
1867 | pos: { x: 0, y: 0 },
1868 | last: { x: 0, y: 0 },
1869 | vel: { x: 0, y: 0 },
1870 | accel: { x: 0, y: 0 },
1871 | friction: { x: 0, y: 0 },
1872 | maxVel: { x: 100, y: 100 },
1873 | zIndex: 0,
1874 | gravityFactor: 1,
1875 | standing: false,
1876 | bounciness: 0,
1877 | minBounceVelocity: 40,
1878 | __id: null,
1879 |
1880 | anims: {},
1881 | animSheet: null,
1882 | currentAnim: null,
1883 | health: 10,
1884 |
1885 | type: 0, // TYPE.NONE
1886 | checkAgainst: 0, // TYPE.NONE
1887 | collides: 0, // COLLIDES.NEVER
1888 |
1889 | _killed: false,
1890 |
1891 | slopeStanding: { min: 44 .toRad(), max: 136 .toRad() },
1892 |
1893 | init: function init(x, y, settings) {
1894 | ;
1895 | this.id = ++ig.Entity._lastId;
1896 | this.pos.x = this.last.x = x;
1897 | this.pos.y = this.last.y = y;
1898 |
1899 | ig.merge(this, settings);
1900 | },
1901 |
1902 | reset: function reset(x, y, settings) {
1903 | var proto = this.constructor.prototype;
1904 | this.pos.x = x;
1905 | this.pos.y = y;
1906 | this.last.x = x;
1907 | this.last.y = y;
1908 | this.vel.x = proto.vel.x;
1909 | this.vel.y = proto.vel.y;
1910 | this.accel.x = proto.accel.x;
1911 | this.accel.y = proto.accel.y;
1912 | this.health = proto.health;
1913 | this._killed = proto._killed;
1914 | this.standing = proto.standing;
1915 |
1916 | this.type = proto.type;
1917 | this.checkAgainst = proto.checkAgainst;
1918 | this.collides = proto.collides;
1919 |
1920 | ig.merge(this, settings);
1921 | },
1922 |
1923 | addAnim: function addAnim(name, frameTime, sequence, stop) {
1924 | if (!this.animSheet) {
1925 | throw 'No animSheet to add the animation ' + name + ' to.';
1926 | }
1927 | var a = new ig.Animation(this.animSheet, frameTime, sequence, stop);
1928 | this.anims[name] = a;
1929 | if (!this.currentAnim) {
1930 | this.currentAnim = a;
1931 | }
1932 |
1933 | return a;
1934 | },
1935 |
1936 | update: function update() {
1937 | this.last.x = this.pos.x;
1938 | this.last.y = this.pos.y;
1939 | this.vel.y += ig.game.gravity * ig.system.tick * this.gravityFactor;
1940 |
1941 | this.vel.x = this.getNewVelocity(this.vel.x, this.accel.x, this.friction.x, this.maxVel.x);
1942 | this.vel.y = this.getNewVelocity(this.vel.y, this.accel.y, this.friction.y, this.maxVel.y);
1943 | //console.log(this.__id, this.vel);
1944 | // movement & collision
1945 | var mx = this.vel.x * ig.system.tick;
1946 | var my = this.vel.y * ig.system.tick;
1947 | var res = ig.game.collisionMap.trace(this.pos.x, this.pos.y, mx, my, this.size.x, this.size.y);
1948 | //console.log(this.__id, mx, my);
1949 | this.handleMovementTrace(res);
1950 |
1951 | if (this.currentAnim) {
1952 | this.currentAnim.update();
1953 | }
1954 | },
1955 |
1956 | getNewVelocity: function getNewVelocity(vel, accel, friction, max) {
1957 | if (accel) {
1958 | return (vel + accel * ig.system.tick).limit(-max, max);
1959 | } else if (friction) {
1960 | var delta = friction * ig.system.tick;
1961 |
1962 | if (vel - delta > 0) {
1963 | return vel - delta;
1964 | } else if (vel + delta < 0) {
1965 | return vel + delta;
1966 | } else {
1967 | return 0;
1968 | }
1969 | }
1970 |
1971 | return vel.limit(-max, max);
1972 | },
1973 |
1974 | handleMovementTrace: function handleMovementTrace(res) {
1975 | this.standing = false;
1976 |
1977 | if (res.collision.y) {
1978 | if (this.bounciness > 0 && Math.abs(this.vel.y) > this.minBounceVelocity) {
1979 | this.vel.y *= -this.bounciness;
1980 | } else {
1981 | if (this.vel.y > 0) {
1982 | this.standing = true;
1983 | }
1984 | this.vel.y = 0;
1985 | }
1986 | }
1987 | if (res.collision.x) {
1988 | if (this.bounciness > 0 && Math.abs(this.vel.x) > this.minBounceVelocity) {
1989 | this.vel.x *= -this.bounciness;
1990 | } else {
1991 | this.vel.x = 0;
1992 | }
1993 | }
1994 | if (res.collision.slope) {
1995 | var s = res.collision.slope;
1996 |
1997 | if (this.bounciness > 0) {
1998 | var proj = this.vel.x * s.nx + this.vel.y * s.ny;
1999 |
2000 | this.vel.x = (this.vel.x - s.nx * proj * 2) * this.bounciness;
2001 | this.vel.y = (this.vel.y - s.ny * proj * 2) * this.bounciness;
2002 | } else {
2003 | var lengthSquared = s.x * s.x + s.y * s.y;
2004 | var dot = (this.vel.x * s.x + this.vel.y * s.y) / lengthSquared;
2005 |
2006 | this.vel.x = s.x * dot;
2007 | this.vel.y = s.y * dot;
2008 |
2009 | var angle = Math.atan2(s.x, s.y);
2010 | if (angle > this.slopeStanding.min && angle < this.slopeStanding.max) {
2011 | this.standing = true;
2012 | }
2013 | }
2014 | }
2015 |
2016 | this.pos = res.pos;
2017 | },
2018 |
2019 | draw: function draw() {
2020 | if (this.currentAnim) {
2021 | this.currentAnim.draw(this.pos.x - this.offset.x - ig.game._rscreen.x, this.pos.y - this.offset.y - ig.game._rscreen.y);
2022 | }
2023 | },
2024 |
2025 | kill: function kill() {
2026 | ig.game.removeEntity(this);
2027 | },
2028 |
2029 | receiveDamage: function receiveDamage(amount, from) {
2030 | this.health -= amount;
2031 | if (this.health <= 0) {
2032 | this.kill();
2033 | }
2034 | },
2035 |
2036 | touches: function touches(other) {
2037 | return !(this.pos.x >= other.pos.x + other.size.x || this.pos.x + this.size.x <= other.pos.x || this.pos.y >= other.pos.y + other.size.y || this.pos.y + this.size.y <= other.pos.y);
2038 | },
2039 |
2040 | distanceTo: function distanceTo(other) {
2041 | var xd = this.pos.x + this.size.x / 2 - (other.pos.x + other.size.x / 2);
2042 | var yd = this.pos.y + this.size.y / 2 - (other.pos.y + other.size.y / 2);
2043 | return Math.sqrt(xd * xd + yd * yd);
2044 | },
2045 |
2046 | angleTo: function angleTo(other) {
2047 | return Math.atan2(other.pos.y + other.size.y / 2 - (this.pos.y + this.size.y / 2), other.pos.x + other.size.x / 2 - (this.pos.x + this.size.x / 2));
2048 | },
2049 |
2050 | check: function check(other) {},
2051 | collideWith: function collideWith(other, axis) {},
2052 | ready: function ready() {},
2053 | erase: function erase() {}
2054 | });
2055 |
2056 | // Last used entity id; incremented with each spawned entity
2057 |
2058 | ig.Entity._lastId = 0;
2059 |
2060 | // Collision Types - Determine if and how entities collide with each other
2061 |
2062 | // In ACTIVE vs. LITE or FIXED vs. ANY collisions, only the "weak" entity moves,
2063 | // while the other one stays fixed. In ACTIVE vs. ACTIVE and ACTIVE vs. PASSIVE
2064 | // collisions, both entities are moved. LITE or PASSIVE entities don't collide
2065 | // with other LITE or PASSIVE entities at all. The behaiviour for FIXED vs.
2066 | // FIXED collisions is undefined.
2067 |
2068 | ig.Entity.COLLIDES = {
2069 | NEVER: 0,
2070 | LITE: 1,
2071 | PASSIVE: 2,
2072 | ACTIVE: 4,
2073 | FIXED: 8
2074 | };
2075 |
2076 | // Entity Types - used for checks
2077 |
2078 | ig.Entity.TYPE = {
2079 | NONE: 0,
2080 | A: 1,
2081 | B: 2,
2082 | BOTH: 3
2083 | };
2084 |
2085 | ig.Entity.checkPair = function (a, b) {
2086 |
2087 | // Do these entities want checks?
2088 | if (a.checkAgainst & b.type) {
2089 | a.check(b);
2090 | }
2091 |
2092 | if (b.checkAgainst & a.type) {
2093 | b.check(a);
2094 | }
2095 |
2096 | // If this pair allows collision, solve it! At least one entity must
2097 | // collide ACTIVE or FIXED, while the other one must not collide NEVER.
2098 | if (a.collides && b.collides && a.collides + b.collides > ig.Entity.COLLIDES.ACTIVE) {
2099 | ig.Entity.solveCollision(a, b);
2100 | }
2101 | };
2102 |
2103 | ig.Entity.solveCollision = function (a, b) {
2104 |
2105 | // If one entity is FIXED, or the other entity is LITE, the weak
2106 | // (FIXED/NON-LITE) entity won't move in collision response
2107 | var weak = null;
2108 | if (a.collides == ig.Entity.COLLIDES.LITE || b.collides == ig.Entity.COLLIDES.FIXED) {
2109 | weak = a;
2110 | } else if (b.collides == ig.Entity.COLLIDES.LITE || a.collides == ig.Entity.COLLIDES.FIXED) {
2111 | weak = b;
2112 | }
2113 |
2114 | // Did they already overlap on the X-axis in the last frame? If so,
2115 | // this must be a vertical collision!
2116 | if (a.last.x + a.size.x > b.last.x && a.last.x < b.last.x + b.size.x) {
2117 | // Which one is on top?
2118 | if (a.last.y < b.last.y) {
2119 | ig.Entity.seperateOnYAxis(a, b, weak);
2120 | } else {
2121 | ig.Entity.seperateOnYAxis(b, a, weak);
2122 | }
2123 | a.collideWith(b, 'y');
2124 | b.collideWith(a, 'y');
2125 | }
2126 |
2127 | // Horizontal collision
2128 | else if (a.last.y + a.size.y > b.last.y && a.last.y < b.last.y + b.size.y) {
2129 | // Which one is on the left?
2130 | if (a.last.x < b.last.x) {
2131 | ig.Entity.seperateOnXAxis(a, b, weak);
2132 | } else {
2133 | ig.Entity.seperateOnXAxis(b, a, weak);
2134 | }
2135 | a.collideWith(b, 'x');
2136 | b.collideWith(a, 'x');
2137 | }
2138 | };
2139 |
2140 | // FIXME: This is a mess. Instead of doing all the movements here, the entities
2141 | // should get notified of the collision (with all details) and resolve it
2142 | // themselfs.
2143 |
2144 | ig.Entity.seperateOnXAxis = function (left, right, weak) {
2145 | var nudge = left.pos.x + left.size.x - right.pos.x;
2146 |
2147 | // We have a weak entity, so just move this one
2148 | if (weak) {
2149 | var strong = left === weak ? right : left;
2150 | weak.vel.x = -weak.vel.x * weak.bounciness + strong.vel.x;
2151 |
2152 | var resWeak = ig.game.collisionMap.trace(weak.pos.x, weak.pos.y, weak == left ? -nudge : nudge, 0, weak.size.x, weak.size.y);
2153 | weak.pos.x = resWeak.pos.x;
2154 | }
2155 |
2156 | // Normal collision - both move
2157 | else {
2158 | var v2 = (left.vel.x - right.vel.x) / 2;
2159 | left.vel.x = -v2;
2160 | right.vel.x = v2;
2161 |
2162 | var resLeft = ig.game.collisionMap.trace(left.pos.x, left.pos.y, -nudge / 2, 0, left.size.x, left.size.y);
2163 | left.pos.x = Math.floor(resLeft.pos.x);
2164 |
2165 | var resRight = ig.game.collisionMap.trace(right.pos.x, right.pos.y, nudge / 2, 0, right.size.x, right.size.y);
2166 | right.pos.x = Math.ceil(resRight.pos.x);
2167 | }
2168 | };
2169 |
2170 | ig.Entity.seperateOnYAxis = function (top, bottom, weak) {
2171 | var nudge = top.pos.y + top.size.y - bottom.pos.y;
2172 |
2173 | // We have a weak entity, so just move this one
2174 | if (weak) {
2175 | var strong = top === weak ? bottom : top;
2176 | weak.vel.y = -weak.vel.y * weak.bounciness + strong.vel.y;
2177 |
2178 | // Riding on a platform?
2179 | var nudgeX = 0;
2180 | if (weak == top && Math.abs(weak.vel.y - strong.vel.y) < weak.minBounceVelocity) {
2181 | weak.standing = true;
2182 | nudgeX = strong.vel.x * ig.system.tick;
2183 | }
2184 |
2185 | var resWeak = ig.game.collisionMap.trace(weak.pos.x, weak.pos.y, nudgeX, weak == top ? -nudge : nudge, weak.size.x, weak.size.y);
2186 | weak.pos.y = resWeak.pos.y;
2187 | weak.pos.x = resWeak.pos.x;
2188 | }
2189 |
2190 | // Bottom entity is standing - just bounce the top one
2191 | else if (ig.game.gravity && (bottom.standing || top.vel.y > 0)) {
2192 | var resTop = ig.game.collisionMap.trace(top.pos.x, top.pos.y, 0, -(top.pos.y + top.size.y - bottom.pos.y), top.size.x, top.size.y);
2193 | top.pos.y = resTop.pos.y;
2194 |
2195 | if (top.bounciness > 0 && top.vel.y > top.minBounceVelocity) {
2196 | top.vel.y *= -top.bounciness;
2197 | } else {
2198 | top.standing = true;
2199 | top.vel.y = 0;
2200 | }
2201 | }
2202 |
2203 | // Normal collision - both move
2204 | else {
2205 | var v2 = (top.vel.y - bottom.vel.y) / 2;
2206 | top.vel.y = -v2;
2207 | bottom.vel.y = v2;
2208 |
2209 | var nudgeX = bottom.vel.x * ig.system.tick;
2210 | var resTop = ig.game.collisionMap.trace(top.pos.x, top.pos.y, nudgeX, -nudge / 2, top.size.x, top.size.y);
2211 | top.pos.y = resTop.pos.y;
2212 |
2213 | var resBottom = ig.game.collisionMap.trace(bottom.pos.x, bottom.pos.y, 0, nudge / 2, bottom.size.x, bottom.size.y);
2214 | bottom.pos.y = resBottom.pos.y;
2215 | }
2216 | };
2217 | });
2218 | }.call(window));
2219 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(/*! ig */ 1)))
2220 |
2221 | /***/ },
2222 | /* 15 */
2223 | /*!****************************!*\
2224 | !*** ./lib/impact/font.js ***!
2225 | \****************************/
2226 | /***/ function(module, exports, __webpack_require__) {
2227 |
2228 | /* WEBPACK VAR INJECTION */(function(ig) {/*** IMPORTS FROM imports-loader ***/
2229 | (function() {
2230 |
2231 | 'use strict';
2232 |
2233 | ig.module('impact.font').requires('impact.image').defines(function () {
2234 | "use strict";
2235 |
2236 | ig.Font = ig.Image.extend({
2237 | widthMap: [],
2238 | indices: [],
2239 | firstChar: 32,
2240 | alpha: 1,
2241 | letterSpacing: 1,
2242 | lineSpacing: 0,
2243 |
2244 | onload: function onload(ev) {
2245 | this._loadMetrics(this.data);
2246 | this.parent(ev);
2247 | },
2248 |
2249 | widthForString: function widthForString(text) {
2250 | // Multiline?
2251 | if (text.indexOf('\n') !== -1) {
2252 | var lines = text.split('\n');
2253 | var width = 0;
2254 | for (var i = 0; i < lines.length; i++) {
2255 | width = Math.max(width, this._widthForLine(lines[i]));
2256 | }
2257 | return width;
2258 | } else {
2259 | return this._widthForLine(text);
2260 | }
2261 | },
2262 |
2263 | _widthForLine: function _widthForLine(text) {
2264 | var width = 0;
2265 | for (var i = 0; i < text.length; i++) {
2266 | width += this.widthMap[text.charCodeAt(i) - this.firstChar] + this.letterSpacing;
2267 | }
2268 | return width;
2269 | },
2270 |
2271 | heightForString: function heightForString(text) {
2272 | return text.split('\n').length * (this.height + this.lineSpacing);
2273 | },
2274 |
2275 | draw: function draw(text, x, y, align) {
2276 | if (typeof text != 'string') {
2277 | text = text.toString();
2278 | }
2279 |
2280 | // Multiline?
2281 | if (text.indexOf('\n') !== -1) {
2282 | var lines = text.split('\n');
2283 | var lineHeight = this.height + this.lineSpacing;
2284 | for (var i = 0; i < lines.length; i++) {
2285 | this.draw(lines[i], x, y + i * lineHeight, align);
2286 | }
2287 | return;
2288 | }
2289 |
2290 | if (align == ig.Font.ALIGN.RIGHT || align == ig.Font.ALIGN.CENTER) {
2291 | var width = this._widthForLine(text);
2292 | x -= align == ig.Font.ALIGN.CENTER ? width / 2 : width;
2293 | }
2294 |
2295 | if (this.alpha !== 1) {
2296 | ig.system.context.globalAlpha = this.alpha;
2297 | }
2298 |
2299 | for (var i = 0; i < text.length; i++) {
2300 | var c = text.charCodeAt(i);
2301 | x += this._drawChar(c - this.firstChar, x, y);
2302 | }
2303 |
2304 | if (this.alpha !== 1) {
2305 | ig.system.context.globalAlpha = 1;
2306 | }
2307 | ig.Image.drawCount += text.length;
2308 | },
2309 |
2310 | _drawChar: function _drawChar(c, targetX, targetY) {
2311 | if (!this.loaded || c < 0 || c >= this.indices.length) {
2312 | return 0;
2313 | }
2314 |
2315 | var scale = ig.system.scale;
2316 |
2317 | var charX = this.indices[c] * scale;
2318 | var charY = 0;
2319 | var charWidth = this.widthMap[c] * scale;
2320 | var charHeight = (this.height - 2) * scale;
2321 |
2322 | ig.system.context.drawImage(this.data, charX, charY, charWidth, charHeight, ig.system.getDrawPos(targetX), ig.system.getDrawPos(targetY), charWidth, charHeight);
2323 |
2324 | return this.widthMap[c] + this.letterSpacing;
2325 | },
2326 |
2327 | _loadMetrics: function _loadMetrics(image) {
2328 | // Draw the bottommost line of this font image into an offscreen canvas
2329 | // and analyze it pixel by pixel.
2330 | // A run of non-transparent pixels represents a character and its width
2331 |
2332 | this.height = image.height - 1;
2333 | this.widthMap = [];
2334 | this.indices = [];
2335 |
2336 | var px = ig.getImagePixels(image, 0, image.height - 1, image.width, 1);
2337 |
2338 | var currentChar = 0;
2339 | var currentWidth = 0;
2340 | for (var x = 0; x < image.width; x++) {
2341 | var index = x * 4 + 3; // alpha component of this pixel
2342 | if (px.data[index] > 127) {
2343 | currentWidth++;
2344 | } else if (px.data[index] < 128 && currentWidth) {
2345 | this.widthMap.push(currentWidth);
2346 | this.indices.push(x - currentWidth);
2347 | currentChar++;
2348 | currentWidth = 0;
2349 | }
2350 | }
2351 | this.widthMap.push(currentWidth);
2352 | this.indices.push(x - currentWidth);
2353 | }
2354 | });
2355 |
2356 | ig.Font.ALIGN = {
2357 | LEFT: 0,
2358 | RIGHT: 1,
2359 | CENTER: 2
2360 | };
2361 | });
2362 | }.call(window));
2363 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(/*! ig */ 1)))
2364 |
2365 | /***/ },
2366 | /* 16 */
2367 | /*!****************************!*\
2368 | !*** ./lib/impact/game.js ***!
2369 | \****************************/
2370 | /***/ function(module, exports, __webpack_require__) {
2371 |
2372 | /* WEBPACK VAR INJECTION */(function(ig) {/*** IMPORTS FROM imports-loader ***/
2373 | (function() {
2374 |
2375 | 'use strict';
2376 |
2377 | ig.module('impact.game').requires('impact.impact', 'impact.entity', 'impact.collision-map', 'impact.background-map').defines(function () {
2378 | "use strict";
2379 |
2380 | ig.Game = ig.Class.extend({
2381 |
2382 | clearColor: '#000000',
2383 | gravity: 0,
2384 | screen: { x: 0, y: 0 },
2385 | _rscreen: { x: 0, y: 0 },
2386 |
2387 | entities: [],
2388 |
2389 | namedEntities: {},
2390 | collisionMap: ig.CollisionMap.staticNoCollision,
2391 | backgroundMaps: [],
2392 | backgroundAnims: {},
2393 |
2394 | autoSort: false,
2395 | sortBy: null,
2396 |
2397 | cellSize: 64,
2398 |
2399 | _deferredKill: [],
2400 | _levelToLoad: null,
2401 | _doSortEntities: false,
2402 |
2403 | staticInstantiate: function staticInstantiate() {
2404 | this.sortBy = this.sortBy || ig.Game.SORT.Z_INDEX;
2405 | ig.game = this;
2406 | return null;
2407 | },
2408 |
2409 | loadLevel: function loadLevel(data) {
2410 | this.screen = { x: 0, y: 0 };
2411 |
2412 | // Entities
2413 | this.entities = [];
2414 | this.namedEntities = {};
2415 | for (var i = 0; i < data.entities.length; i++) {
2416 | var ent = data.entities[i];
2417 | this.spawnEntity(ent.type, ent.x, ent.y, ent.settings);
2418 | }
2419 | this.sortEntities();
2420 |
2421 | // Map Layer
2422 | this.collisionMap = ig.CollisionMap.staticNoCollision;
2423 | this.backgroundMaps = [];
2424 | for (var i = 0; i < data.layer.length; i++) {
2425 | var ld = data.layer[i];
2426 | if (ld.name == 'collision') {
2427 | this.collisionMap = new ig.CollisionMap(ld.tilesize, ld.data);
2428 | } else {
2429 | var newMap = new ig.BackgroundMap(ld.tilesize, ld.data, ld.tilesetName);
2430 | newMap.anims = this.backgroundAnims[ld.tilesetName] || {};
2431 | newMap.repeat = ld.repeat;
2432 | newMap.distance = ld.distance;
2433 | newMap.foreground = !!ld.foreground;
2434 | newMap.preRender = !!ld.preRender;
2435 | newMap.name = ld.name;
2436 | this.backgroundMaps.push(newMap);
2437 | }
2438 | }
2439 |
2440 | // Call post-init ready function on all entities
2441 | for (var i = 0; i < this.entities.length; i++) {
2442 | this.entities[i].ready();
2443 | }
2444 | },
2445 |
2446 | loadLevelDeferred: function loadLevelDeferred(data) {
2447 | this._levelToLoad = data;
2448 | },
2449 |
2450 | getMapByName: function getMapByName(name) {
2451 | if (name == 'collision') {
2452 | return this.collisionMap;
2453 | }
2454 |
2455 | for (var i = 0; i < this.backgroundMaps.length; i++) {
2456 | if (this.backgroundMaps[i].name == name) {
2457 | return this.backgroundMaps[i];
2458 | }
2459 | }
2460 |
2461 | return null;
2462 | },
2463 |
2464 | getEntityByName: function getEntityByName(name) {
2465 | return this.namedEntities[name];
2466 | },
2467 |
2468 | getEntitiesByType: function getEntitiesByType(type) {
2469 | var entityClass = typeof type === 'string' ? ig.global[type] : type;
2470 |
2471 | var a = [];
2472 | for (var i = 0; i < this.entities.length; i++) {
2473 | var ent = this.entities[i];
2474 | if (ent instanceof entityClass && !ent._killed) {
2475 | a.push(ent);
2476 | }
2477 | }
2478 | return a;
2479 | },
2480 |
2481 | spawnEntity: function spawnEntity(type, x, y, settings) {
2482 | var entityClass = typeof type === 'string' ? ig.global[type] : type;
2483 |
2484 | if (!entityClass) {
2485 | throw "Can't spawn entity of type " + type;
2486 | }
2487 | var ent = new entityClass(x, y, settings || {});
2488 | this.entities.push(ent);
2489 | if (ent.name) {
2490 | this.namedEntities[ent.name] = ent;
2491 | }
2492 |
2493 | return ent;
2494 | },
2495 |
2496 | sortEntities: function sortEntities() {
2497 | this.entities.sort(this.sortBy);
2498 | },
2499 |
2500 | sortEntitiesDeferred: function sortEntitiesDeferred() {
2501 | this._doSortEntities = true;
2502 | },
2503 |
2504 | removeEntity: function removeEntity(ent) {
2505 | // Remove this entity from the named entities
2506 | if (ent.name) {
2507 | delete this.namedEntities[ent.name];
2508 | }
2509 |
2510 | // We can not remove the entity from the entities[] array in the midst
2511 | // of an update cycle, so remember all killed entities and remove
2512 | // them later.
2513 | // Also make sure this entity doesn't collide anymore and won't get
2514 | // updated or checked
2515 | ent._killed = true;
2516 | ent.type = ig.Entity.TYPE.NONE;
2517 | ent.checkAgainst = ig.Entity.TYPE.NONE;
2518 | ent.collides = ig.Entity.COLLIDES.NEVER;
2519 | this._deferredKill.push(ent);
2520 | },
2521 |
2522 | run: function run() {
2523 | this.update();
2524 | this.draw();
2525 | },
2526 |
2527 | update: function update() {
2528 | // load new level?
2529 | if (this._levelToLoad) {
2530 | this.loadLevel(this._levelToLoad);
2531 | this._levelToLoad = null;
2532 | }
2533 |
2534 | // update entities
2535 | this.updateEntities();
2536 | this.checkEntities();
2537 |
2538 | // remove all killed entities
2539 | for (var i = 0; i < this._deferredKill.length; i++) {
2540 | this._deferredKill[i].erase();
2541 | this.entities.erase(this._deferredKill[i]);
2542 | }
2543 | this._deferredKill = [];
2544 |
2545 | // sort entities?
2546 | if (this._doSortEntities || this.autoSort) {
2547 | this.sortEntities();
2548 | this._doSortEntities = false;
2549 | }
2550 |
2551 | // update background animations
2552 | for (var tileset in this.backgroundAnims) {
2553 | var anims = this.backgroundAnims[tileset];
2554 | for (var a in anims) {
2555 | anims[a].update();
2556 | }
2557 | }
2558 | },
2559 |
2560 | updateEntities: function updateEntities() {
2561 | for (var i = 0; i < this.entities.length; i++) {
2562 | var ent = this.entities[i];
2563 | if (!ent._killed) {
2564 | ent.update();
2565 | }
2566 | }
2567 | },
2568 |
2569 | draw: function draw() {
2570 | if (this.clearColor) {
2571 | ig.system.clear(this.clearColor);
2572 | }
2573 |
2574 | // This is a bit of a circle jerk. Entities reference game._rscreen
2575 | // instead of game.screen when drawing themselfs in order to be
2576 | // "synchronized" to the rounded(?) screen position
2577 | this._rscreen.x = ig.system.getDrawPos(this.screen.x) / ig.system.scale;
2578 | this._rscreen.y = ig.system.getDrawPos(this.screen.y) / ig.system.scale;
2579 |
2580 | var mapIndex;
2581 | for (mapIndex = 0; mapIndex < this.backgroundMaps.length; mapIndex++) {
2582 | var map = this.backgroundMaps[mapIndex];
2583 | if (map.foreground) {
2584 | // All foreground layers are drawn after the entities
2585 | break;
2586 | }
2587 | map.setScreenPos(this.screen.x, this.screen.y);
2588 | map.draw();
2589 | }
2590 |
2591 | this.drawEntities();
2592 |
2593 | for (mapIndex; mapIndex < this.backgroundMaps.length; mapIndex++) {
2594 | var map = this.backgroundMaps[mapIndex];
2595 | map.setScreenPos(this.screen.x, this.screen.y);
2596 | map.draw();
2597 | }
2598 | },
2599 |
2600 | drawEntities: function drawEntities() {
2601 | for (var i = 0; i < this.entities.length; i++) {
2602 | this.entities[i].draw();
2603 | }
2604 | },
2605 |
2606 | checkEntities: function checkEntities() {
2607 | // Insert all entities into a spatial hash and check them against any
2608 | // other entity that already resides in the same cell. Entities that are
2609 | // bigger than a single cell, are inserted into each one they intersect
2610 | // with.
2611 |
2612 | // A list of entities, which the current one was already checked with,
2613 | // is maintained for each entity.
2614 |
2615 | var hash = {};
2616 | for (var e = 0; e < this.entities.length; e++) {
2617 | var entity = this.entities[e];
2618 |
2619 | // Skip entities that don't check, don't get checked and don't collide
2620 | if (entity.type == ig.Entity.TYPE.NONE && entity.checkAgainst == ig.Entity.TYPE.NONE && entity.collides == ig.Entity.COLLIDES.NEVER) {
2621 | continue;
2622 | }
2623 |
2624 | var checked = {},
2625 | xmin = Math.floor(entity.pos.x / this.cellSize),
2626 | ymin = Math.floor(entity.pos.y / this.cellSize),
2627 | xmax = Math.floor((entity.pos.x + entity.size.x) / this.cellSize) + 1,
2628 | ymax = Math.floor((entity.pos.y + entity.size.y) / this.cellSize) + 1;
2629 |
2630 | for (var x = xmin; x < xmax; x++) {
2631 | for (var y = ymin; y < ymax; y++) {
2632 |
2633 | // Current cell is empty - create it and insert!
2634 | if (!hash[x]) {
2635 | hash[x] = {};
2636 | hash[x][y] = [entity];
2637 | } else if (!hash[x][y]) {
2638 | hash[x][y] = [entity];
2639 | }
2640 |
2641 | // Check against each entity in this cell, then insert
2642 | else {
2643 | var cell = hash[x][y];
2644 | for (var c = 0; c < cell.length; c++) {
2645 |
2646 | // Intersects and wasn't already checkd?
2647 | if (entity.touches(cell[c]) && !checked[cell[c].id]) {
2648 | checked[cell[c].id] = true;
2649 | ig.Entity.checkPair(entity, cell[c]);
2650 | }
2651 | }
2652 | cell.push(entity);
2653 | }
2654 | } // end for y size
2655 | } // end for x size
2656 | } // end for entities
2657 | }
2658 | });
2659 |
2660 | ig.Game.SORT = {
2661 | Z_INDEX: function Z_INDEX(a, b) {
2662 | return a.zIndex - b.zIndex;
2663 | },
2664 | POS_X: function POS_X(a, b) {
2665 | return a.pos.x + a.size.x - (b.pos.x + b.size.x);
2666 | },
2667 | POS_Y: function POS_Y(a, b) {
2668 | return a.pos.y + a.size.y - (b.pos.y + b.size.y);
2669 | }
2670 | };
2671 | });
2672 | }.call(window));
2673 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(/*! ig */ 1)))
2674 |
2675 | /***/ },
2676 | /* 17 */
2677 | /*!*****************************!*\
2678 | !*** ./lib/impact/image.js ***!
2679 | \*****************************/
2680 | /***/ function(module, exports, __webpack_require__) {
2681 |
2682 | /* WEBPACK VAR INJECTION */(function(ig) {/*** IMPORTS FROM imports-loader ***/
2683 | (function() {
2684 |
2685 | 'use strict';
2686 |
2687 | ig.module('impact.image').defines(function () {
2688 | "use strict";
2689 |
2690 | ig.Image = ig.Class.extend({
2691 | data: null,
2692 | width: 0,
2693 | height: 0,
2694 | loaded: false,
2695 | failed: false,
2696 | loadCallback: null,
2697 | path: '',
2698 |
2699 | staticInstantiate: function staticInstantiate(path) {
2700 | return ig.Image.cache[path] || null;
2701 | },
2702 |
2703 | init: function init(path) {
2704 | this.path = path;
2705 | this.load();
2706 | },
2707 |
2708 | load: function load(loadCallback) {
2709 | if (this.loaded) {
2710 | if (loadCallback) {
2711 | loadCallback(this.path, true);
2712 | }
2713 | return;
2714 | } else if (!this.loaded && ig.ready) {
2715 | this.loadCallback = loadCallback || null;
2716 |
2717 | this.data = new Image();
2718 | this.data.onload = this.onload.bind(this);
2719 | this.data.onerror = this.onerror.bind(this);
2720 | this.data.src = ig.prefix + this.path + ig.nocache;
2721 | } else {
2722 | ig.addResource(this);
2723 | }
2724 |
2725 | ig.Image.cache[this.path] = this;
2726 | },
2727 |
2728 | reload: function reload() {
2729 | this.loaded = false;
2730 | this.data = new Image();
2731 | this.data.onload = this.onload.bind(this);
2732 | this.data.src = this.path + '?' + Date.now();
2733 | },
2734 |
2735 | onload: function onload(event) {
2736 | this.width = this.data.width;
2737 | this.height = this.data.height;
2738 | this.loaded = true;
2739 |
2740 | if (ig.system.scale != 1) {
2741 | this.resize(ig.system.scale);
2742 | }
2743 |
2744 | if (this.loadCallback) {
2745 | this.loadCallback(this.path, true);
2746 | }
2747 | },
2748 |
2749 | onerror: function onerror(event) {
2750 | this.failed = true;
2751 |
2752 | if (this.loadCallback) {
2753 | this.loadCallback(this.path, false);
2754 | }
2755 | },
2756 |
2757 | resize: function resize(scale) {
2758 | // Nearest-Neighbor scaling
2759 |
2760 | // The original image is drawn into an offscreen canvas of the same size
2761 | // and copied into another offscreen canvas with the new size.
2762 | // The scaled offscreen canvas becomes the image (data) of this object.
2763 |
2764 | var origPixels = ig.getImagePixels(this.data, 0, 0, this.width, this.height);
2765 |
2766 | var widthScaled = this.width * scale;
2767 | var heightScaled = this.height * scale;
2768 |
2769 | var scaled = ig.$new('canvas');
2770 | scaled.width = widthScaled;
2771 | scaled.height = heightScaled;
2772 | var scaledCtx = scaled.getContext('2d');
2773 | var scaledPixels = scaledCtx.getImageData(0, 0, widthScaled, heightScaled);
2774 |
2775 | for (var y = 0; y < heightScaled; y++) {
2776 | for (var x = 0; x < widthScaled; x++) {
2777 | var index = (Math.floor(y / scale) * this.width + Math.floor(x / scale)) * 4;
2778 | var indexScaled = (y * widthScaled + x) * 4;
2779 | scaledPixels.data[indexScaled] = origPixels.data[index];
2780 | scaledPixels.data[indexScaled + 1] = origPixels.data[index + 1];
2781 | scaledPixels.data[indexScaled + 2] = origPixels.data[index + 2];
2782 | scaledPixels.data[indexScaled + 3] = origPixels.data[index + 3];
2783 | }
2784 | }
2785 | scaledCtx.putImageData(scaledPixels, 0, 0);
2786 | this.data = scaled;
2787 | },
2788 |
2789 | draw: function draw(targetX, targetY, sourceX, sourceY, width, height) {
2790 | if (!this.loaded) {
2791 | return;
2792 | }
2793 |
2794 | var scale = ig.system.scale;
2795 | sourceX = sourceX ? sourceX * scale : 0;
2796 | sourceY = sourceY ? sourceY * scale : 0;
2797 | width = (width ? width : this.width) * scale;
2798 | height = (height ? height : this.height) * scale;
2799 |
2800 | ig.system.context.drawImage(this.data, sourceX, sourceY, width, height, ig.system.getDrawPos(targetX), ig.system.getDrawPos(targetY), width, height);
2801 |
2802 | ig.Image.drawCount++;
2803 | },
2804 |
2805 | drawTile: function drawTile(targetX, targetY, tile, tileWidth, tileHeight, flipX, flipY) {
2806 | tileHeight = tileHeight ? tileHeight : tileWidth;
2807 |
2808 | if (!this.loaded || tileWidth > this.width || tileHeight > this.height) {
2809 | return;
2810 | }
2811 |
2812 | var scale = ig.system.scale;
2813 | var tileWidthScaled = Math.floor(tileWidth * scale);
2814 | var tileHeightScaled = Math.floor(tileHeight * scale);
2815 |
2816 | var scaleX = flipX ? -1 : 1;
2817 | var scaleY = flipY ? -1 : 1;
2818 |
2819 | if (flipX || flipY) {
2820 | ig.system.context.save();
2821 | ig.system.context.scale(scaleX, scaleY);
2822 | }
2823 | ig.system.context.drawImage(this.data, Math.floor(tile * tileWidth) % this.width * scale, Math.floor(tile * tileWidth / this.width) * tileHeight * scale, tileWidthScaled, tileHeightScaled, ig.system.getDrawPos(targetX) * scaleX - (flipX ? tileWidthScaled : 0), ig.system.getDrawPos(targetY) * scaleY - (flipY ? tileHeightScaled : 0), tileWidthScaled, tileHeightScaled);
2824 | if (flipX || flipY) {
2825 | ig.system.context.restore();
2826 | }
2827 |
2828 | ig.Image.drawCount++;
2829 | }
2830 | });
2831 |
2832 | ig.Image.drawCount = 0;
2833 | ig.Image.cache = {};
2834 | ig.Image.reloadCache = function () {
2835 | for (var path in ig.Image.cache) {
2836 | ig.Image.cache[path].reload();
2837 | }
2838 | };
2839 | });
2840 | }.call(window));
2841 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(/*! ig */ 1)))
2842 |
2843 | /***/ },
2844 | /* 18 */
2845 | /*!******************************!*\
2846 | !*** ./lib/impact/impact.js ***!
2847 | \******************************/
2848 | /***/ function(module, exports, __webpack_require__) {
2849 |
2850 | /* WEBPACK VAR INJECTION */(function(ig) {/*** IMPORTS FROM imports-loader ***/
2851 | (function() {
2852 |
2853 | 'use strict';
2854 |
2855 | var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
2856 |
2857 | // -----------------------------------------------------------------------------
2858 | // Impact Game Engine 1.24
2859 | // http://impactjs.com/
2860 | // -----------------------------------------------------------------------------
2861 |
2862 |
2863 | (function (window) {
2864 | "use strict";
2865 |
2866 | // -----------------------------------------------------------------------------
2867 | // Native Object extensions
2868 |
2869 | Number.prototype.map = function (istart, istop, ostart, ostop) {
2870 | return ostart + (ostop - ostart) * ((this - istart) / (istop - istart));
2871 | };
2872 |
2873 | Number.prototype.limit = function (min, max) {
2874 | return Math.min(max, Math.max(min, this));
2875 | };
2876 |
2877 | Number.prototype.round = function (precision) {
2878 | precision = Math.pow(10, precision || 0);
2879 | return Math.round(this * precision) / precision;
2880 | };
2881 |
2882 | Number.prototype.floor = function () {
2883 | return Math.floor(this);
2884 | };
2885 |
2886 | Number.prototype.ceil = function () {
2887 | return Math.ceil(this);
2888 | };
2889 |
2890 | Number.prototype.toInt = function () {
2891 | return this | 0;
2892 | };
2893 |
2894 | Number.prototype.toRad = function () {
2895 | return this / 180 * Math.PI;
2896 | };
2897 |
2898 | Number.prototype.toDeg = function () {
2899 | return this * 180 / Math.PI;
2900 | };
2901 |
2902 | Object.defineProperty(Array.prototype, 'erase', { value: function value(item) {
2903 | for (var i = this.length; i--;) {
2904 | if (this[i] === item) {
2905 | this.splice(i, 1);
2906 | }
2907 | }
2908 | return this;
2909 | } });
2910 |
2911 | Object.defineProperty(Array.prototype, 'random', { value: function value(item) {
2912 | return this[Math.floor(Math.random() * this.length)];
2913 | } });
2914 |
2915 | Function.prototype.bind = Function.prototype.bind || function (oThis) {
2916 | if (typeof this !== "function") {
2917 | throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
2918 | }
2919 |
2920 | var aArgs = Array.prototype.slice.call(arguments, 1),
2921 | fToBind = this,
2922 | fNOP = function fNOP() {},
2923 | fBound = function fBound() {
2924 | return fToBind.apply(this instanceof fNOP && oThis ? this : oThis, aArgs.concat(Array.prototype.slice.call(arguments)));
2925 | };
2926 |
2927 | fNOP.prototype = this.prototype;
2928 | fBound.prototype = new fNOP();
2929 |
2930 | return fBound;
2931 | };
2932 |
2933 | // -----------------------------------------------------------------------------
2934 | // ig Namespace
2935 |
2936 | window.ig = {
2937 | game: null,
2938 | debug: null,
2939 | version: '1.24',
2940 | global: window,
2941 | modules: {},
2942 | resources: [],
2943 | ready: false,
2944 | baked: false,
2945 | nocache: '',
2946 | ua: {},
2947 | prefix: window.ImpactPrefix || '',
2948 | lib: 'lib/',
2949 |
2950 | _current: null,
2951 | _loadQueue: [],
2952 | _waitForOnload: 0,
2953 |
2954 | $: function $(selector) {
2955 | return selector.charAt(0) == '#' ? document.getElementById(selector.substr(1)) : document.getElementsByTagName(selector);
2956 | },
2957 |
2958 | $new: function $new(name) {
2959 | return document.createElement(name);
2960 | },
2961 |
2962 | copy: function copy(object) {
2963 | if (!object || (typeof object === 'undefined' ? 'undefined' : _typeof(object)) != 'object' || object instanceof HTMLElement || object instanceof ig.Class) {
2964 | return object;
2965 | } else if (object instanceof Array) {
2966 | var c = [];
2967 | for (var i = 0, l = object.length; i < l; i++) {
2968 | c[i] = ig.copy(object[i]);
2969 | }
2970 | return c;
2971 | } else {
2972 | var c = {};
2973 | for (var i in object) {
2974 | c[i] = ig.copy(object[i]);
2975 | }
2976 | return c;
2977 | }
2978 | },
2979 |
2980 | merge: function merge(original, extended) {
2981 | for (var key in extended) {
2982 | var ext = extended[key];
2983 | if ((typeof ext === 'undefined' ? 'undefined' : _typeof(ext)) != 'object' || ext instanceof HTMLElement || ext instanceof ig.Class || ext === null) {
2984 | original[key] = ext;
2985 | } else {
2986 | if (!original[key] || _typeof(original[key]) != 'object') {
2987 | original[key] = ext instanceof Array ? [] : {};
2988 | }
2989 | ig.merge(original[key], ext);
2990 | }
2991 | }
2992 | return original;
2993 | },
2994 |
2995 | ksort: function ksort(obj) {
2996 | if (!obj || (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) != 'object') {
2997 | return [];
2998 | }
2999 |
3000 | var keys = [],
3001 | values = [];
3002 | for (var i in obj) {
3003 | keys.push(i);
3004 | }
3005 |
3006 | keys.sort();
3007 | for (var i = 0; i < keys.length; i++) {
3008 | values.push(obj[keys[i]]);
3009 | }
3010 |
3011 | return values;
3012 | },
3013 |
3014 | // Ah, yes. I love vendor prefixes. So much fun!
3015 | setVendorAttribute: function setVendorAttribute(el, attr, val) {
3016 | var uc = attr.charAt(0).toUpperCase() + attr.substr(1);
3017 | el[attr] = el['ms' + uc] = el['moz' + uc] = el['webkit' + uc] = el['o' + uc] = val;
3018 | },
3019 |
3020 | getVendorAttribute: function getVendorAttribute(el, attr) {
3021 | var uc = attr.charAt(0).toUpperCase() + attr.substr(1);
3022 | return el[attr] || el['ms' + uc] || el['moz' + uc] || el['webkit' + uc] || el['o' + uc];
3023 | },
3024 |
3025 | normalizeVendorAttribute: function normalizeVendorAttribute(el, attr) {
3026 | var prefixedVal = ig.getVendorAttribute(el, attr);
3027 | if (!el[attr] && prefixedVal) {
3028 | el[attr] = prefixedVal;
3029 | }
3030 | },
3031 |
3032 | // This function normalizes getImageData to extract the real, actual
3033 | // pixels from an image. The naive method recently failed on retina
3034 | // devices with a backgingStoreRatio != 1
3035 | getImagePixels: function getImagePixels(image, x, y, width, height) {
3036 | var canvas = ig.$new('canvas');
3037 | canvas.width = image.width;
3038 | canvas.height = image.height;
3039 | var ctx = canvas.getContext('2d');
3040 |
3041 | // Try to draw pixels as accurately as possible
3042 | ig.System.SCALE.CRISP(canvas, ctx);
3043 |
3044 | var ratio = ig.getVendorAttribute(ctx, 'backingStorePixelRatio') || 1;
3045 | ig.normalizeVendorAttribute(ctx, 'getImageDataHD');
3046 |
3047 | var realWidth = image.width / ratio,
3048 | realHeight = image.height / ratio;
3049 |
3050 | canvas.width = Math.ceil(realWidth);
3051 | canvas.height = Math.ceil(realHeight);
3052 |
3053 | ctx.drawImage(image, 0, 0, realWidth, realHeight);
3054 |
3055 | return ratio === 1 ? ctx.getImageData(x, y, width, height) : ctx.getImageDataHD(x, y, width, height);
3056 | },
3057 |
3058 | module: function module(name) {
3059 | if (ig._current) {
3060 | throw "Module '" + ig._current.name + "' defines nothing";
3061 | }
3062 | if (ig.modules[name] && ig.modules[name].body) {
3063 | throw "Module '" + name + "' is already defined";
3064 | }
3065 |
3066 | ig._current = { name: name, requires: [], loaded: false, body: null };
3067 | ig.modules[name] = ig._current;
3068 | ig._loadQueue.push(ig._current);
3069 | return ig;
3070 | },
3071 |
3072 | requires: function requires() {
3073 | ig._current.requires = Array.prototype.slice.call(arguments);
3074 | return ig;
3075 | },
3076 |
3077 | defines: function defines(body) {
3078 | ig._current.body = body;
3079 | ig._current = null;
3080 | ig._initDOMReady();
3081 | },
3082 |
3083 | addResource: function addResource(resource) {
3084 | ig.resources.push(resource);
3085 | },
3086 |
3087 | setNocache: function setNocache(set) {
3088 | ig.nocache = set ? '?' + Date.now() : '';
3089 | },
3090 |
3091 | // Stubs for ig.Debug
3092 | log: function log() {},
3093 | assert: function assert(condition, msg) {},
3094 | show: function show(name, number) {},
3095 | mark: function mark(msg, color) {},
3096 |
3097 | _loadScript: function _loadScript(name, requiredFrom) {
3098 | ig.modules[name] = { name: name, requires: [], loaded: false, body: null };
3099 | ig._waitForOnload++;
3100 |
3101 | var path = ig.prefix + ig.lib + name.replace(/\./g, '/') + '.js' + ig.nocache;
3102 | var script = ig.$new('script');
3103 | script.type = 'text/javascript';
3104 | script.src = path;
3105 | script.onload = function () {
3106 | ig._waitForOnload--;
3107 | ig._execModules();
3108 | };
3109 | script.onerror = function () {
3110 | throw 'Failed to load module ' + name + ' at ' + path + ' ' + 'required from ' + requiredFrom;
3111 | };
3112 | ig.$('head')[0].appendChild(script);
3113 | },
3114 |
3115 | _execModules: function _execModules() {
3116 | var modulesLoaded = false;
3117 | for (var i = 0; i < ig._loadQueue.length; i++) {
3118 | var m = ig._loadQueue[i];
3119 | var dependenciesLoaded = true;
3120 |
3121 | for (var j = 0; j < m.requires.length; j++) {
3122 | var name = m.requires[j];
3123 | if (!ig.modules[name]) {
3124 | dependenciesLoaded = false;
3125 | ig._loadScript(name, m.name);
3126 | } else if (!ig.modules[name].loaded) {
3127 | dependenciesLoaded = false;
3128 | }
3129 | }
3130 |
3131 | if (dependenciesLoaded && m.body) {
3132 | ig._loadQueue.splice(i, 1);
3133 | m.loaded = true;
3134 | m.body();
3135 | modulesLoaded = true;
3136 | i--;
3137 | }
3138 | }
3139 |
3140 | if (modulesLoaded) {
3141 | ig._execModules();
3142 | }
3143 |
3144 | // No modules executed, no more files to load but loadQueue not empty?
3145 | // Must be some unresolved dependencies!
3146 | else if (!ig.baked && ig._waitForOnload == 0 && ig._loadQueue.length != 0) {
3147 | var unresolved = [];
3148 | for (var i = 0; i < ig._loadQueue.length; i++) {
3149 |
3150 | // Which dependencies aren't loaded?
3151 | var unloaded = [];
3152 | var requires = ig._loadQueue[i].requires;
3153 | for (var j = 0; j < requires.length; j++) {
3154 | var m = ig.modules[requires[j]];
3155 | if (!m || !m.loaded) {
3156 | unloaded.push(requires[j]);
3157 | }
3158 | }
3159 | unresolved.push(ig._loadQueue[i].name + ' (requires: ' + unloaded.join(', ') + ')');
3160 | }
3161 |
3162 | throw "Unresolved (or circular?) dependencies. " + "Most likely there's a name/path mismatch for one of the listed modules " + "or a previous syntax error prevents a module from loading:\n" + unresolved.join('\n');
3163 | }
3164 | },
3165 |
3166 | _DOMReady: function _DOMReady() {
3167 | if (!ig.modules['dom.ready'].loaded) {
3168 | if (!document.body) {
3169 | return setTimeout(ig._DOMReady, 13);
3170 | }
3171 | ig.modules['dom.ready'].loaded = true;
3172 | ig._waitForOnload--;
3173 | ig._execModules();
3174 | }
3175 | return 0;
3176 | },
3177 |
3178 | _boot: function _boot() {
3179 | if (document.location.href.match(/\?nocache/)) {
3180 | ig.setNocache(true);
3181 | }
3182 |
3183 | // Probe user agent string
3184 | ig.ua.pixelRatio = window.devicePixelRatio || 1;
3185 | ig.ua.viewport = {
3186 | width: window.innerWidth,
3187 | height: window.innerHeight
3188 | };
3189 | ig.ua.screen = {
3190 | width: window.screen.availWidth * ig.ua.pixelRatio,
3191 | height: window.screen.availHeight * ig.ua.pixelRatio
3192 | };
3193 |
3194 | ig.ua.iPhone = /iPhone/i.test(navigator.userAgent);
3195 | ig.ua.iPhone4 = ig.ua.iPhone && ig.ua.pixelRatio == 2;
3196 | ig.ua.iPad = /iPad/i.test(navigator.userAgent);
3197 | ig.ua.android = /android/i.test(navigator.userAgent);
3198 | ig.ua.winPhone = /Windows Phone/i.test(navigator.userAgent);
3199 | ig.ua.iOS = ig.ua.iPhone || ig.ua.iPad;
3200 | ig.ua.mobile = ig.ua.iOS || ig.ua.android || ig.ua.winPhone || /mobile/i.test(navigator.userAgent);
3201 | ig.ua.touchDevice = 'ontouchstart' in window || window.navigator.msMaxTouchPoints;
3202 | },
3203 |
3204 | _initDOMReady: function _initDOMReady() {
3205 | if (ig.modules['dom.ready']) {
3206 | ig._execModules();
3207 | return;
3208 | }
3209 |
3210 | ig._boot();
3211 |
3212 | ig.modules['dom.ready'] = { requires: [], loaded: false, body: null };
3213 | ig._waitForOnload++;
3214 | if (document.readyState === 'complete') {
3215 | ig._DOMReady();
3216 | } else {
3217 | document.addEventListener('DOMContentLoaded', ig._DOMReady, false);
3218 | window.addEventListener('load', ig._DOMReady, false);
3219 | }
3220 | }
3221 | };
3222 |
3223 | // -----------------------------------------------------------------------------
3224 | // Provide ig.setAnimation and ig.clearAnimation as a compatible way to use
3225 | // requestAnimationFrame if available or setInterval otherwise
3226 |
3227 | // Use requestAnimationFrame if available
3228 | ig.normalizeVendorAttribute(window, 'requestAnimationFrame');
3229 | if (window.requestAnimationFrame) {
3230 | var next = 1,
3231 | anims = {};
3232 |
3233 | window.ig.setAnimation = function (callback, element) {
3234 | var current = next++;
3235 | anims[current] = true;
3236 |
3237 | var animate = function animate() {
3238 | if (!anims[current]) {
3239 | return;
3240 | } // deleted?
3241 | window.requestAnimationFrame(animate, element);
3242 | callback();
3243 | };
3244 | window.requestAnimationFrame(animate, element);
3245 | return current;
3246 | };
3247 |
3248 | window.ig.clearAnimation = function (id) {
3249 | delete anims[id];
3250 | };
3251 | }
3252 |
3253 | // [set/clear]Interval fallback
3254 | else {
3255 | window.ig.setAnimation = function (callback, element) {
3256 | return window.setInterval(callback, 1000 / 60);
3257 | };
3258 | window.ig.clearAnimation = function (id) {
3259 | window.clearInterval(id);
3260 | };
3261 | }
3262 |
3263 | // -----------------------------------------------------------------------------
3264 | // Class object based on John Resigs code; inspired by base2 and Prototype
3265 | // http://ejohn.org/blog/simple-javascript-inheritance/
3266 |
3267 | var initializing = false,
3268 | fnTest = /xyz/.test(function () {
3269 | xyz;
3270 | }) ? /\bparent\b/ : /.*/;
3271 | var lastClassId = 0;
3272 |
3273 | window.ig.Class = function () {};
3274 | var inject = function inject(prop) {
3275 | var proto = this.prototype;
3276 | var parent = {};
3277 | for (var name in prop) {
3278 | if (typeof prop[name] == "function" && typeof proto[name] == "function" && fnTest.test(prop[name])) {
3279 | parent[name] = proto[name]; // save original function
3280 | proto[name] = function (name, fn) {
3281 | return function () {
3282 | var tmp = this.parent;
3283 | this.parent = parent[name];
3284 | var ret = fn.apply(this, arguments);
3285 | this.parent = tmp;
3286 | return ret;
3287 | };
3288 | }(name, prop[name]);
3289 | } else {
3290 | proto[name] = prop[name];
3291 | }
3292 | }
3293 | };
3294 |
3295 | window.ig.Class.extend = function (prop) {
3296 | var parent = this.prototype;
3297 |
3298 | initializing = true;
3299 | var prototype = new this();
3300 | initializing = false;
3301 |
3302 | for (var name in prop) {
3303 | if (typeof prop[name] == "function" && typeof parent[name] == "function" && fnTest.test(prop[name])) {
3304 | prototype[name] = function (name, fn) {
3305 | return function () {
3306 | var tmp = this.parent;
3307 | this.parent = parent[name];
3308 | var ret = fn.apply(this, arguments);
3309 | this.parent = tmp;
3310 | return ret;
3311 | };
3312 | }(name, prop[name]);
3313 | } else {
3314 | prototype[name] = prop[name];
3315 | }
3316 | }
3317 |
3318 | function Class() {
3319 | if (!initializing) {
3320 |
3321 | // If this class has a staticInstantiate method, invoke it
3322 | // and check if we got something back. If not, the normal
3323 | // constructor (init) is called.
3324 | if (this.staticInstantiate) {
3325 | var obj = this.staticInstantiate.apply(this, arguments);
3326 | if (obj) {
3327 | return obj;
3328 | }
3329 | }
3330 | for (var p in this) {
3331 | if (_typeof(this[p]) == 'object') {
3332 | this[p] = ig.copy(this[p]); // deep copy!
3333 | }
3334 | }
3335 | if (this.init) {
3336 | this.init.apply(this, arguments);
3337 | }
3338 | }
3339 | return this;
3340 | }
3341 |
3342 | Class.prototype = prototype;
3343 | Class.prototype.constructor = Class;
3344 | Class.extend = window.ig.Class.extend;
3345 | Class.inject = inject;
3346 | Class.classId = prototype.classId = ++lastClassId;
3347 |
3348 | return Class;
3349 | };
3350 |
3351 | // Merge the ImpactMixin - if present - into the 'ig' namespace. This gives other
3352 | // code the chance to modify 'ig' before it's doing any work.
3353 | if (window.ImpactMixin) {
3354 | ig.merge(ig, window.ImpactMixin);
3355 | }
3356 | })(window);
3357 |
3358 | // -----------------------------------------------------------------------------
3359 | // The main() function creates the system, input, sound and game objects,
3360 | // creates a preloader and starts the run loop
3361 |
3362 | ig.module('impact.impact').requires('dom.ready', 'impact.loader', 'impact.system', 'impact.input', 'impact.sound').defines(function () {
3363 | "use strict";
3364 |
3365 | ig.main = function (canvasId, gameClass, fps, width, height, scale, loaderClass) {
3366 | ig.system = new ig.System(canvasId, fps, width, height, scale || 1);
3367 | ig.input = new ig.Input();
3368 | ig.soundManager = new ig.SoundManager();
3369 | ig.music = new ig.Music();
3370 | ig.ready = true;
3371 |
3372 | var loader = new (loaderClass || ig.Loader)(gameClass, ig.resources);
3373 | loader.load();
3374 | };
3375 | });
3376 | }.call(window));
3377 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(/*! ig */ 1)))
3378 |
3379 | /***/ },
3380 | /* 19 */
3381 | /*!*****************************!*\
3382 | !*** ./lib/impact/input.js ***!
3383 | \*****************************/
3384 | /***/ function(module, exports, __webpack_require__) {
3385 |
3386 | /* WEBPACK VAR INJECTION */(function(ig) {/*** IMPORTS FROM imports-loader ***/
3387 | (function() {
3388 |
3389 | 'use strict';
3390 |
3391 | ig.module('impact.input').defines(function () {
3392 | "use strict";
3393 |
3394 | ig.KEY = {
3395 | 'MOUSE1': -1,
3396 | 'MOUSE2': -3,
3397 | 'MWHEEL_UP': -4,
3398 | 'MWHEEL_DOWN': -5,
3399 |
3400 | 'BACKSPACE': 8,
3401 | 'TAB': 9,
3402 | 'ENTER': 13,
3403 | 'PAUSE': 19,
3404 | 'CAPS': 20,
3405 | 'ESC': 27,
3406 | 'SPACE': 32,
3407 | 'PAGE_UP': 33,
3408 | 'PAGE_DOWN': 34,
3409 | 'END': 35,
3410 | 'HOME': 36,
3411 | 'LEFT_ARROW': 37,
3412 | 'UP_ARROW': 38,
3413 | 'RIGHT_ARROW': 39,
3414 | 'DOWN_ARROW': 40,
3415 | 'INSERT': 45,
3416 | 'DELETE': 46,
3417 | '_0': 48,
3418 | '_1': 49,
3419 | '_2': 50,
3420 | '_3': 51,
3421 | '_4': 52,
3422 | '_5': 53,
3423 | '_6': 54,
3424 | '_7': 55,
3425 | '_8': 56,
3426 | '_9': 57,
3427 | 'A': 65,
3428 | 'B': 66,
3429 | 'C': 67,
3430 | 'D': 68,
3431 | 'E': 69,
3432 | 'F': 70,
3433 | 'G': 71,
3434 | 'H': 72,
3435 | 'I': 73,
3436 | 'J': 74,
3437 | 'K': 75,
3438 | 'L': 76,
3439 | 'M': 77,
3440 | 'N': 78,
3441 | 'O': 79,
3442 | 'P': 80,
3443 | 'Q': 81,
3444 | 'R': 82,
3445 | 'S': 83,
3446 | 'T': 84,
3447 | 'U': 85,
3448 | 'V': 86,
3449 | 'W': 87,
3450 | 'X': 88,
3451 | 'Y': 89,
3452 | 'Z': 90,
3453 | 'NUMPAD_0': 96,
3454 | 'NUMPAD_1': 97,
3455 | 'NUMPAD_2': 98,
3456 | 'NUMPAD_3': 99,
3457 | 'NUMPAD_4': 100,
3458 | 'NUMPAD_5': 101,
3459 | 'NUMPAD_6': 102,
3460 | 'NUMPAD_7': 103,
3461 | 'NUMPAD_8': 104,
3462 | 'NUMPAD_9': 105,
3463 | 'MULTIPLY': 106,
3464 | 'ADD': 107,
3465 | 'SUBSTRACT': 109,
3466 | 'DECIMAL': 110,
3467 | 'DIVIDE': 111,
3468 | 'F1': 112,
3469 | 'F2': 113,
3470 | 'F3': 114,
3471 | 'F4': 115,
3472 | 'F5': 116,
3473 | 'F6': 117,
3474 | 'F7': 118,
3475 | 'F8': 119,
3476 | 'F9': 120,
3477 | 'F10': 121,
3478 | 'F11': 122,
3479 | 'F12': 123,
3480 | 'SHIFT': 16,
3481 | 'CTRL': 17,
3482 | 'ALT': 18,
3483 | 'PLUS': 187,
3484 | 'COMMA': 188,
3485 | 'MINUS': 189,
3486 | 'PERIOD': 190
3487 | };
3488 |
3489 | ig.Input = ig.Class.extend({
3490 | bindings: {},
3491 | actions: {},
3492 | presses: {},
3493 | locks: {},
3494 | delayedKeyup: {},
3495 |
3496 | isUsingMouse: false,
3497 | isUsingKeyboard: false,
3498 | isUsingAccelerometer: false,
3499 | mouse: { x: 0, y: 0 },
3500 | accel: { x: 0, y: 0, z: 0 },
3501 |
3502 | initMouse: function initMouse() {
3503 | if (this.isUsingMouse) {
3504 | return;
3505 | }
3506 | this.isUsingMouse = true;
3507 | var mouseWheelBound = this.mousewheel.bind(this);
3508 | ig.system.canvas.addEventListener('mousewheel', mouseWheelBound, false);
3509 | ig.system.canvas.addEventListener('DOMMouseScroll', mouseWheelBound, false);
3510 |
3511 | ig.system.canvas.addEventListener('contextmenu', this.contextmenu.bind(this), false);
3512 | ig.system.canvas.addEventListener('mousedown', this.keydown.bind(this), false);
3513 | ig.system.canvas.addEventListener('mouseup', this.keyup.bind(this), false);
3514 | ig.system.canvas.addEventListener('mousemove', this.mousemove.bind(this), false);
3515 |
3516 | if (ig.ua.touchDevice) {
3517 | // Standard
3518 | ig.system.canvas.addEventListener('touchstart', this.keydown.bind(this), false);
3519 | ig.system.canvas.addEventListener('touchend', this.keyup.bind(this), false);
3520 | ig.system.canvas.addEventListener('touchmove', this.mousemove.bind(this), false);
3521 |
3522 | // MS
3523 | ig.system.canvas.addEventListener('MSPointerDown', this.keydown.bind(this), false);
3524 | ig.system.canvas.addEventListener('MSPointerUp', this.keyup.bind(this), false);
3525 | ig.system.canvas.addEventListener('MSPointerMove', this.mousemove.bind(this), false);
3526 | ig.system.canvas.style.msTouchAction = 'none';
3527 | }
3528 | },
3529 |
3530 | initKeyboard: function initKeyboard() {
3531 | if (this.isUsingKeyboard) {
3532 | return;
3533 | }
3534 | this.isUsingKeyboard = true;
3535 | window.addEventListener('keydown', this.keydown.bind(this), false);
3536 | window.addEventListener('keyup', this.keyup.bind(this), false);
3537 | },
3538 |
3539 | initAccelerometer: function initAccelerometer() {
3540 | if (this.isUsingAccelerometer) {
3541 | return;
3542 | }
3543 | this.isUsingAccelerometer = true;
3544 | window.addEventListener('devicemotion', this.devicemotion.bind(this), false);
3545 | },
3546 |
3547 | mousewheel: function mousewheel(event) {
3548 | var delta = event.wheelDelta ? event.wheelDelta : event.detail * -1;
3549 | var code = delta > 0 ? ig.KEY.MWHEEL_UP : ig.KEY.MWHEEL_DOWN;
3550 | var action = this.bindings[code];
3551 | if (action) {
3552 | this.actions[action] = true;
3553 | this.presses[action] = true;
3554 | this.delayedKeyup[action] = true;
3555 | event.stopPropagation();
3556 | event.preventDefault();
3557 | }
3558 | },
3559 |
3560 | mousemove: function mousemove(event) {
3561 | var internalWidth = parseInt(ig.system.canvas.offsetWidth) || ig.system.realWidth;
3562 | var scale = ig.system.scale * (internalWidth / ig.system.realWidth);
3563 |
3564 | var pos = { left: 0, top: 0 };
3565 | if (ig.system.canvas.getBoundingClientRect) {
3566 | pos = ig.system.canvas.getBoundingClientRect();
3567 | }
3568 |
3569 | var ev = event.touches ? event.touches[0] : event;
3570 | this.mouse.x = (ev.clientX - pos.left) / scale;
3571 | this.mouse.y = (ev.clientY - pos.top) / scale;
3572 | },
3573 |
3574 | contextmenu: function contextmenu(event) {
3575 | if (this.bindings[ig.KEY.MOUSE2]) {
3576 | event.stopPropagation();
3577 | event.preventDefault();
3578 | }
3579 | },
3580 |
3581 | keydown: function keydown(event) {
3582 | var tag = event.target.tagName;
3583 | if (tag == 'INPUT' || tag == 'TEXTAREA') {
3584 | return;
3585 | }
3586 |
3587 | var code = event.type == 'keydown' ? event.keyCode : event.button == 2 ? ig.KEY.MOUSE2 : ig.KEY.MOUSE1;
3588 |
3589 | // Focus window element for mouse clicks. Prevents issues when
3590 | // running the game in an iframe.
3591 | if (code < 0 && !ig.ua.mobile) {
3592 | window.focus();
3593 | }
3594 |
3595 | if (event.type == 'touchstart' || event.type == 'mousedown') {
3596 | this.mousemove(event);
3597 | }
3598 |
3599 | var action = this.bindings[code];
3600 | if (action) {
3601 | this.actions[action] = true;
3602 | if (!this.locks[action]) {
3603 | this.presses[action] = true;
3604 | this.locks[action] = true;
3605 | }
3606 | event.preventDefault();
3607 | }
3608 | },
3609 |
3610 | keyup: function keyup(event) {
3611 | var tag = event.target.tagName;
3612 | if (tag == 'INPUT' || tag == 'TEXTAREA') {
3613 | return;
3614 | }
3615 |
3616 | var code = event.type == 'keyup' ? event.keyCode : event.button == 2 ? ig.KEY.MOUSE2 : ig.KEY.MOUSE1;
3617 |
3618 | var action = this.bindings[code];
3619 | if (action) {
3620 | this.delayedKeyup[action] = true;
3621 | event.preventDefault();
3622 | }
3623 | },
3624 |
3625 | devicemotion: function devicemotion(event) {
3626 | this.accel = event.accelerationIncludingGravity;
3627 | },
3628 |
3629 | bind: function bind(key, action) {
3630 | if (key < 0) {
3631 | this.initMouse();
3632 | } else if (key > 0) {
3633 | this.initKeyboard();
3634 | }
3635 | this.bindings[key] = action;
3636 | },
3637 |
3638 | bindTouch: function bindTouch(selector, action) {
3639 | var element = ig.$(selector);
3640 |
3641 | var that = this;
3642 | element.addEventListener('touchstart', function (ev) {
3643 | that.touchStart(ev, action);
3644 | }, false);
3645 | element.addEventListener('touchend', function (ev) {
3646 | that.touchEnd(ev, action);
3647 | }, false);
3648 | element.addEventListener('MSPointerDown', function (ev) {
3649 | that.touchStart(ev, action);
3650 | }, false);
3651 | element.addEventListener('MSPointerUp', function (ev) {
3652 | that.touchEnd(ev, action);
3653 | }, false);
3654 | },
3655 |
3656 | unbind: function unbind(key) {
3657 | var action = this.bindings[key];
3658 | this.delayedKeyup[action] = true;
3659 |
3660 | this.bindings[key] = null;
3661 | },
3662 |
3663 | unbindAll: function unbindAll() {
3664 | this.bindings = {};
3665 | this.actions = {};
3666 | this.presses = {};
3667 | this.locks = {};
3668 | this.delayedKeyup = {};
3669 | },
3670 |
3671 | state: function state(action) {
3672 | return this.actions[action];
3673 | },
3674 |
3675 | pressed: function pressed(action) {
3676 | return this.presses[action];
3677 | },
3678 |
3679 | released: function released(action) {
3680 | return !!this.delayedKeyup[action];
3681 | },
3682 |
3683 | clearPressed: function clearPressed() {
3684 | for (var action in this.delayedKeyup) {
3685 | this.actions[action] = false;
3686 | this.locks[action] = false;
3687 | }
3688 | this.delayedKeyup = {};
3689 | this.presses = {};
3690 | },
3691 |
3692 | touchStart: function touchStart(event, action) {
3693 | this.actions[action] = true;
3694 | this.presses[action] = true;
3695 |
3696 | event.stopPropagation();
3697 | event.preventDefault();
3698 | return false;
3699 | },
3700 |
3701 | touchEnd: function touchEnd(event, action) {
3702 | this.delayedKeyup[action] = true;
3703 | event.stopPropagation();
3704 | event.preventDefault();
3705 | return false;
3706 | }
3707 | });
3708 | });
3709 | }.call(window));
3710 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(/*! ig */ 1)))
3711 |
3712 | /***/ },
3713 | /* 20 */
3714 | /*!******************************!*\
3715 | !*** ./lib/impact/loader.js ***!
3716 | \******************************/
3717 | /***/ function(module, exports, __webpack_require__) {
3718 |
3719 | /* WEBPACK VAR INJECTION */(function(ig) {/*** IMPORTS FROM imports-loader ***/
3720 | (function() {
3721 |
3722 | 'use strict';
3723 |
3724 | ig.module('impact.loader').requires('impact.image', 'impact.font', 'impact.sound').defines(function () {
3725 | "use strict";
3726 |
3727 | ig.Loader = ig.Class.extend({
3728 | resources: [],
3729 |
3730 | gameClass: null,
3731 | status: 0,
3732 | done: false,
3733 |
3734 | _unloaded: [],
3735 | _drawStatus: 0,
3736 | _intervalId: 0,
3737 | _loadCallbackBound: null,
3738 |
3739 | init: function init(gameClass, resources) {
3740 | this.gameClass = gameClass;
3741 | this.resources = resources;
3742 | this._loadCallbackBound = this._loadCallback.bind(this);
3743 |
3744 | for (var i = 0; i < this.resources.length; i++) {
3745 | this._unloaded.push(this.resources[i].path);
3746 | }
3747 | },
3748 |
3749 | load: function load() {
3750 | ig.system.clear('#000');
3751 |
3752 | if (!this.resources.length) {
3753 | this.end();
3754 | return;
3755 | }
3756 |
3757 | for (var i = 0; i < this.resources.length; i++) {
3758 | this.loadResource(this.resources[i]);
3759 | }
3760 | this._intervalId = setInterval(this.draw.bind(this), 16);
3761 | },
3762 |
3763 | loadResource: function loadResource(res) {
3764 | res.load(this._loadCallbackBound);
3765 | },
3766 |
3767 | end: function end() {
3768 | if (this.done) {
3769 | return;
3770 | }
3771 |
3772 | this.done = true;
3773 | clearInterval(this._intervalId);
3774 | ig.system.setGame(this.gameClass);
3775 | },
3776 |
3777 | draw: function draw() {
3778 | this._drawStatus += (this.status - this._drawStatus) / 5;
3779 | var s = ig.system.scale;
3780 | var w = ig.system.width * 0.6;
3781 | var h = ig.system.height * 0.1;
3782 | var x = ig.system.width * 0.5 - w / 2;
3783 | var y = ig.system.height * 0.5 - h / 2;
3784 |
3785 | ig.system.context.fillStyle = '#000';
3786 | ig.system.context.fillRect(0, 0, 480, 320);
3787 |
3788 | ig.system.context.fillStyle = '#fff';
3789 | ig.system.context.fillRect(x * s, y * s, w * s, h * s);
3790 |
3791 | ig.system.context.fillStyle = '#000';
3792 | ig.system.context.fillRect(x * s + s, y * s + s, w * s - s - s, h * s - s - s);
3793 |
3794 | ig.system.context.fillStyle = '#fff';
3795 | ig.system.context.fillRect(x * s, y * s, w * s * this._drawStatus, h * s);
3796 | },
3797 |
3798 | _loadCallback: function _loadCallback(path, status) {
3799 | if (status) {
3800 | this._unloaded.erase(path);
3801 | } else {
3802 | throw 'Failed to load resource: ' + path;
3803 | }
3804 |
3805 | this.status = 1 - this._unloaded.length / this.resources.length;
3806 | if (this._unloaded.length == 0) {
3807 | // all done?
3808 | setTimeout(this.end.bind(this), 250);
3809 | }
3810 | }
3811 | });
3812 | });
3813 | }.call(window));
3814 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(/*! ig */ 1)))
3815 |
3816 | /***/ },
3817 | /* 21 */
3818 | /*!***************************!*\
3819 | !*** ./lib/impact/map.js ***!
3820 | \***************************/
3821 | /***/ function(module, exports, __webpack_require__) {
3822 |
3823 | /* WEBPACK VAR INJECTION */(function(ig) {/*** IMPORTS FROM imports-loader ***/
3824 | (function() {
3825 |
3826 | "use strict";
3827 |
3828 | ig.module('impact.map').defines(function () {
3829 | "use strict";
3830 |
3831 | ig.Map = ig.Class.extend({
3832 | tilesize: 8,
3833 | width: 1,
3834 | height: 1,
3835 | data: [[]],
3836 | name: null,
3837 |
3838 | init: function init(tilesize, data) {
3839 | this.tilesize = tilesize;
3840 | this.data = data;
3841 | this.height = data.length;
3842 | this.width = data[0].length;
3843 |
3844 | this.pxWidth = this.width * this.tilesize;
3845 | this.pxHeight = this.height * this.tilesize;
3846 | },
3847 |
3848 | getTile: function getTile(x, y) {
3849 | var tx = Math.floor(x / this.tilesize);
3850 | var ty = Math.floor(y / this.tilesize);
3851 | if (tx >= 0 && tx < this.width && ty >= 0 && ty < this.height) {
3852 | return this.data[ty][tx];
3853 | } else {
3854 | return 0;
3855 | }
3856 | },
3857 |
3858 | setTile: function setTile(x, y, tile) {
3859 | var tx = Math.floor(x / this.tilesize);
3860 | var ty = Math.floor(y / this.tilesize);
3861 | if (tx >= 0 && tx < this.width && ty >= 0 && ty < this.height) {
3862 | this.data[ty][tx] = tile;
3863 | }
3864 | }
3865 | });
3866 | });
3867 | }.call(window));
3868 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(/*! ig */ 1)))
3869 |
3870 | /***/ },
3871 | /* 22 */
3872 | /*!*****************************!*\
3873 | !*** ./lib/impact/sound.js ***!
3874 | \*****************************/
3875 | /***/ function(module, exports, __webpack_require__) {
3876 |
3877 | /* WEBPACK VAR INJECTION */(function(ig) {/*** IMPORTS FROM imports-loader ***/
3878 | (function() {
3879 |
3880 | 'use strict';
3881 |
3882 | ig.module('impact.sound').defines(function () {
3883 | "use strict";
3884 |
3885 | ig.SoundManager = ig.Class.extend({
3886 | clips: {},
3887 | volume: 1,
3888 | format: null,
3889 |
3890 | init: function init() {
3891 | // Quick sanity check if the Browser supports the Audio tag
3892 | if (!ig.Sound.enabled || !window.Audio) {
3893 | ig.Sound.enabled = false;
3894 | return;
3895 | }
3896 |
3897 | // Probe sound formats and determine the file extension to load
3898 | var probe = new Audio();
3899 | for (var i = 0; i < ig.Sound.use.length; i++) {
3900 | var format = ig.Sound.use[i];
3901 | if (probe.canPlayType(format.mime)) {
3902 | this.format = format;
3903 | break;
3904 | }
3905 | }
3906 |
3907 | // No compatible format found? -> Disable sound
3908 | if (!this.format) {
3909 | ig.Sound.enabled = false;
3910 | }
3911 |
3912 | // Create WebAudio Context
3913 | if (ig.Sound.enabled && ig.Sound.useWebAudio) {
3914 | this.audioContext = new AudioContext();
3915 | this.boundWebAudioUnlock = this.unlockWebAudio.bind(this);
3916 | document.addEventListener('touchstart', this.boundWebAudioUnlock, false);
3917 | }
3918 | },
3919 |
3920 | unlockWebAudio: function unlockWebAudio() {
3921 | document.removeEventListener('touchstart', this.boundWebAudioUnlock, false);
3922 |
3923 | // create empty buffer
3924 | var buffer = this.audioContext.createBuffer(1, 1, 22050);
3925 | var source = this.audioContext.createBufferSource();
3926 | source.buffer = buffer;
3927 |
3928 | source.connect(this.audioContext.destination);
3929 | source.start(0);
3930 | },
3931 |
3932 | load: function load(path, multiChannel, loadCallback) {
3933 | if (multiChannel && ig.Sound.useWebAudio) {
3934 | // Requested as Multichannel and we're using WebAudio?
3935 | return this.loadWebAudio(path, multiChannel, loadCallback);
3936 | } else {
3937 | // Oldschool HTML5 Audio - always used for Music
3938 | return this.loadHTML5Audio(path, multiChannel, loadCallback);
3939 | }
3940 | },
3941 |
3942 | loadWebAudio: function loadWebAudio(path, multiChannel, loadCallback) {
3943 | // Path to the soundfile with the right extension (.ogg or .mp3)
3944 | var realPath = ig.prefix + path.replace(/[^\.]+$/, this.format.ext) + ig.nocache;
3945 |
3946 | if (this.clips[path]) {
3947 | return this.clips[path];
3948 | }
3949 |
3950 | var audioSource = new ig.Sound.WebAudioSource();
3951 | this.clips[path] = audioSource;
3952 |
3953 | var request = new XMLHttpRequest();
3954 | request.open('GET', realPath, true);
3955 | request.responseType = 'arraybuffer';
3956 |
3957 | var that = this;
3958 | request.onload = function (ev) {
3959 | that.audioContext.decodeAudioData(request.response, function (buffer) {
3960 | audioSource.buffer = buffer;
3961 | loadCallback(path, true, ev);
3962 | }, function (ev) {
3963 | loadCallback(path, false, ev);
3964 | });
3965 | };
3966 | request.onerror = function (ev) {
3967 | loadCallback(path, false, ev);
3968 | };
3969 | request.send();
3970 |
3971 | return audioSource;
3972 | },
3973 |
3974 | loadHTML5Audio: function loadHTML5Audio(path, multiChannel, loadCallback) {
3975 |
3976 | // Path to the soundfile with the right extension (.ogg or .mp3)
3977 | var realPath = ig.prefix + path.replace(/[^\.]+$/, this.format.ext) + ig.nocache;
3978 |
3979 | // Sound file already loaded?
3980 | if (this.clips[path]) {
3981 | // Loaded as WebAudio, but now requested as HTML5 Audio? Probably Music?
3982 | if (this.clips[path] instanceof ig.Sound.WebAudioSource) {
3983 | return this.clips[path];
3984 | }
3985 |
3986 | // Only loaded as single channel and now requested as multichannel?
3987 | if (multiChannel && this.clips[path].length < ig.Sound.channels) {
3988 | for (var i = this.clips[path].length; i < ig.Sound.channels; i++) {
3989 | var a = new Audio(realPath);
3990 | a.load();
3991 | this.clips[path].push(a);
3992 | }
3993 | }
3994 | return this.clips[path][0];
3995 | }
3996 |
3997 | var clip = new Audio(realPath);
3998 | if (loadCallback) {
3999 |
4000 | // The canplaythrough event is dispatched when the browser determines
4001 | // that the sound can be played without interuption, provided the
4002 | // download rate doesn't change.
4003 | // Mobile browsers stubbornly refuse to preload HTML5, so we simply
4004 | // ignore the canplaythrough event and immediately "fake" a successful
4005 | // load callback
4006 | if (ig.ua.mobile) {
4007 | setTimeout(function () {
4008 | loadCallback(path, true, null);
4009 | }, 0);
4010 | } else {
4011 | clip.addEventListener('canplaythrough', function cb(ev) {
4012 | clip.removeEventListener('canplaythrough', cb, false);
4013 | loadCallback(path, true, ev);
4014 | }, false);
4015 |
4016 | clip.addEventListener('error', function (ev) {
4017 | loadCallback(path, false, ev);
4018 | }, false);
4019 | }
4020 | }
4021 | clip.preload = 'auto';
4022 | clip.load();
4023 |
4024 | this.clips[path] = [clip];
4025 | if (multiChannel) {
4026 | for (var i = 1; i < ig.Sound.channels; i++) {
4027 | var a = new Audio(realPath);
4028 | a.load();
4029 | this.clips[path].push(a);
4030 | }
4031 | }
4032 |
4033 | return clip;
4034 | },
4035 |
4036 | get: function get(path) {
4037 | // Find and return a channel that is not currently playing
4038 | var channels = this.clips[path];
4039 |
4040 | // Is this a WebAudio source? We only ever have one for each Sound
4041 | if (channels && channels instanceof ig.Sound.WebAudioSource) {
4042 | return channels;
4043 | }
4044 |
4045 | // Oldschool HTML5 Audio - find a channel that's not currently
4046 | // playing or, if all are playing, rewind one
4047 | for (var i = 0, clip; clip = channels[i++];) {
4048 | if (clip.paused || clip.ended) {
4049 | if (clip.ended) {
4050 | clip.currentTime = 0;
4051 | }
4052 | return clip;
4053 | }
4054 | }
4055 |
4056 | // Still here? Pause and rewind the first channel
4057 | channels[0].pause();
4058 | channels[0].currentTime = 0;
4059 | return channels[0];
4060 | }
4061 | });
4062 |
4063 | ig.Music = ig.Class.extend({
4064 | tracks: [],
4065 | namedTracks: {},
4066 | currentTrack: null,
4067 | currentIndex: 0,
4068 | random: false,
4069 |
4070 | _volume: 1,
4071 | _loop: false,
4072 | _fadeInterval: 0,
4073 | _fadeTimer: null,
4074 | _endedCallbackBound: null,
4075 |
4076 | init: function init() {
4077 | this._endedCallbackBound = this._endedCallback.bind(this);
4078 |
4079 | Object.defineProperty(this, "volume", {
4080 | get: this.getVolume.bind(this),
4081 | set: this.setVolume.bind(this)
4082 | });
4083 |
4084 | Object.defineProperty(this, "loop", {
4085 | get: this.getLooping.bind(this),
4086 | set: this.setLooping.bind(this)
4087 | });
4088 | },
4089 |
4090 | add: function add(music, name) {
4091 | if (!ig.Sound.enabled) {
4092 | return;
4093 | }
4094 |
4095 | var path = music instanceof ig.Sound ? music.path : music;
4096 |
4097 | var track = ig.soundManager.load(path, false);
4098 |
4099 | // Did we get a WebAudio Source? This is suboptimal; Music should be loaded
4100 | // as HTML5 Audio so it can be streamed
4101 | if (track instanceof ig.Sound.WebAudioSource) {
4102 | // Since this error will likely occour at game start, we stop the game
4103 | // to not produce any more errors.
4104 | ig.system.stopRunLoop();
4105 | throw "Sound '" + path + "' loaded as Multichannel but used for Music. " + "Set the multiChannel param to false when loading, e.g.: new ig.Sound(path, false)";
4106 | }
4107 |
4108 | track.loop = this._loop;
4109 | track.volume = this._volume;
4110 | track.addEventListener('ended', this._endedCallbackBound, false);
4111 | this.tracks.push(track);
4112 |
4113 | if (name) {
4114 | this.namedTracks[name] = track;
4115 | }
4116 |
4117 | if (!this.currentTrack) {
4118 | this.currentTrack = track;
4119 | }
4120 | },
4121 |
4122 | next: function next() {
4123 | if (!this.tracks.length) {
4124 | return;
4125 | }
4126 |
4127 | this.stop();
4128 | this.currentIndex = this.random ? Math.floor(Math.random() * this.tracks.length) : (this.currentIndex + 1) % this.tracks.length;
4129 | this.currentTrack = this.tracks[this.currentIndex];
4130 | this.play();
4131 | },
4132 |
4133 | pause: function pause() {
4134 | if (!this.currentTrack) {
4135 | return;
4136 | }
4137 | this.currentTrack.pause();
4138 | },
4139 |
4140 | stop: function stop() {
4141 | if (!this.currentTrack) {
4142 | return;
4143 | }
4144 | this.currentTrack.pause();
4145 | this.currentTrack.currentTime = 0;
4146 | },
4147 |
4148 | play: function play(name) {
4149 | // If a name was provided, stop playing the current track (if any)
4150 | // and play the named track
4151 | if (name && this.namedTracks[name]) {
4152 | var newTrack = this.namedTracks[name];
4153 | if (newTrack != this.currentTrack) {
4154 | this.stop();
4155 | this.currentTrack = newTrack;
4156 | }
4157 | } else if (!this.currentTrack) {
4158 | return;
4159 | }
4160 | this.currentTrack.play();
4161 | },
4162 |
4163 | getLooping: function getLooping() {
4164 | return this._loop;
4165 | },
4166 |
4167 | setLooping: function setLooping(l) {
4168 | this._loop = l;
4169 | for (var i in this.tracks) {
4170 | this.tracks[i].loop = l;
4171 | }
4172 | },
4173 |
4174 | getVolume: function getVolume() {
4175 | return this._volume;
4176 | },
4177 |
4178 | setVolume: function setVolume(v) {
4179 | this._volume = v.limit(0, 1);
4180 | for (var i in this.tracks) {
4181 | this.tracks[i].volume = this._volume;
4182 | }
4183 | },
4184 |
4185 | fadeOut: function fadeOut(time) {
4186 | if (!this.currentTrack) {
4187 | return;
4188 | }
4189 |
4190 | clearInterval(this._fadeInterval);
4191 | this.fadeTimer = new ig.Timer(time);
4192 | this._fadeInterval = setInterval(this._fadeStep.bind(this), 50);
4193 | },
4194 |
4195 | _fadeStep: function _fadeStep() {
4196 | var v = this.fadeTimer.delta().map(-this.fadeTimer.target, 0, 1, 0).limit(0, 1) * this._volume;
4197 |
4198 | if (v <= 0.01) {
4199 | this.stop();
4200 | this.currentTrack.volume = this._volume;
4201 | clearInterval(this._fadeInterval);
4202 | } else {
4203 | this.currentTrack.volume = v;
4204 | }
4205 | },
4206 |
4207 | _endedCallback: function _endedCallback() {
4208 | if (this._loop) {
4209 | this.play();
4210 | } else {
4211 | this.next();
4212 | }
4213 | }
4214 | });
4215 |
4216 | ig.Sound = ig.Class.extend({
4217 | path: '',
4218 | volume: 1,
4219 | currentClip: null,
4220 | multiChannel: true,
4221 | _loop: false,
4222 |
4223 | init: function init(path, multiChannel) {
4224 | this.path = path;
4225 | this.multiChannel = multiChannel !== false;
4226 |
4227 | Object.defineProperty(this, "loop", {
4228 | get: this.getLooping.bind(this),
4229 | set: this.setLooping.bind(this)
4230 | });
4231 |
4232 | this.load();
4233 | },
4234 |
4235 | getLooping: function getLooping() {
4236 | return this._loop;
4237 | },
4238 |
4239 | setLooping: function setLooping(loop) {
4240 | this._loop = loop;
4241 |
4242 | if (this.currentClip) {
4243 | this.currentClip.loop = loop;
4244 | }
4245 | },
4246 |
4247 | load: function load(loadCallback) {
4248 | if (!ig.Sound.enabled) {
4249 | if (loadCallback) {
4250 | loadCallback(this.path, true);
4251 | }
4252 | return;
4253 | }
4254 |
4255 | if (ig.ready) {
4256 | ig.soundManager.load(this.path, this.multiChannel, loadCallback);
4257 | } else {
4258 | ig.addResource(this);
4259 | }
4260 | },
4261 |
4262 | play: function play() {
4263 | if (!ig.Sound.enabled) {
4264 | return;
4265 | }
4266 |
4267 | this.currentClip = ig.soundManager.get(this.path);
4268 | this.currentClip.loop = this._loop;
4269 | this.currentClip.volume = ig.soundManager.volume * this.volume;
4270 | this.currentClip.play();
4271 | },
4272 |
4273 | stop: function stop() {
4274 | if (this.currentClip) {
4275 | this.currentClip.pause();
4276 | this.currentClip.currentTime = 0;
4277 | }
4278 | }
4279 | });
4280 |
4281 | ig.Sound.WebAudioSource = ig.Class.extend({
4282 | sources: [],
4283 | gain: null,
4284 | buffer: null,
4285 | _loop: false,
4286 |
4287 | init: function init() {
4288 | this.gain = ig.soundManager.audioContext.createGain();
4289 | this.gain.connect(ig.soundManager.audioContext.destination);
4290 |
4291 | Object.defineProperty(this, "loop", {
4292 | get: this.getLooping.bind(this),
4293 | set: this.setLooping.bind(this)
4294 | });
4295 |
4296 | Object.defineProperty(this, "volume", {
4297 | get: this.getVolume.bind(this),
4298 | set: this.setVolume.bind(this)
4299 | });
4300 | },
4301 |
4302 | play: function play() {
4303 | if (!this.buffer) {
4304 | return;
4305 | }
4306 | var source = ig.soundManager.audioContext.createBufferSource();
4307 | source.buffer = this.buffer;
4308 | source.connect(this.gain);
4309 | source.loop = this._loop;
4310 |
4311 | // Add this new source to our sources array and remove it again
4312 | // later when it has finished playing.
4313 | var that = this;
4314 | this.sources.push(source);
4315 | source.onended = function () {
4316 | that.sources.erase(source);
4317 | };
4318 |
4319 | source.start(0);
4320 | },
4321 |
4322 | pause: function pause() {
4323 | for (var i = 0; i < this.sources.length; i++) {
4324 | try {
4325 | this.sources[i].stop();
4326 | } catch (err) {}
4327 | }
4328 | },
4329 |
4330 | getLooping: function getLooping() {
4331 | return this._loop;
4332 | },
4333 |
4334 | setLooping: function setLooping(loop) {
4335 | this._loop = loop;
4336 |
4337 | for (var i = 0; i < this.sources.length; i++) {
4338 | this.sources[i].loop = loop;
4339 | }
4340 | },
4341 |
4342 | getVolume: function getVolume() {
4343 | return this.gain.gain.value;
4344 | },
4345 |
4346 | setVolume: function setVolume(volume) {
4347 | this.gain.gain.value = volume;
4348 | }
4349 | });
4350 |
4351 | ig.Sound.FORMAT = {
4352 | MP3: { ext: 'mp3', mime: 'audio/mpeg' },
4353 | M4A: { ext: 'm4a', mime: 'audio/mp4; codecs=mp4a' },
4354 | OGG: { ext: 'ogg', mime: 'audio/ogg; codecs=vorbis' },
4355 | WEBM: { ext: 'webm', mime: 'audio/webm; codecs=vorbis' },
4356 | CAF: { ext: 'caf', mime: 'audio/x-caf' }
4357 | };
4358 | ig.Sound.use = [ig.Sound.FORMAT.OGG, ig.Sound.FORMAT.MP3];
4359 | ig.Sound.channels = 4;
4360 | ig.Sound.enabled = true;
4361 |
4362 | ig.normalizeVendorAttribute(window, 'AudioContext');
4363 | ig.Sound.useWebAudio = !!window.AudioContext && !window.nwf;
4364 | });
4365 | }.call(window));
4366 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(/*! ig */ 1)))
4367 |
4368 | /***/ },
4369 | /* 23 */
4370 | /*!******************************!*\
4371 | !*** ./lib/impact/system.js ***!
4372 | \******************************/
4373 | /***/ function(module, exports, __webpack_require__) {
4374 |
4375 | /* WEBPACK VAR INJECTION */(function(ig) {/*** IMPORTS FROM imports-loader ***/
4376 | (function() {
4377 |
4378 | 'use strict';
4379 |
4380 | ig.module('impact.system').requires('impact.timer', 'impact.image').defines(function () {
4381 | "use strict";
4382 |
4383 | ig.System = ig.Class.extend({
4384 | fps: 30,
4385 | width: 320,
4386 | height: 240,
4387 | realWidth: 320,
4388 | realHeight: 240,
4389 | scale: 1,
4390 |
4391 | tick: 0,
4392 | animationId: 0,
4393 | newGameClass: null,
4394 | running: false,
4395 |
4396 | delegate: null,
4397 | clock: null,
4398 | canvas: null,
4399 | context: null,
4400 |
4401 | init: function init(canvasId, fps, width, height, scale) {
4402 | this.fps = fps;
4403 |
4404 | this.clock = new ig.Timer();
4405 | this.canvas = ig.$(canvasId);
4406 | this.resize(width, height, scale);
4407 | this.context = this.canvas.getContext('2d');
4408 |
4409 | this.getDrawPos = ig.System.drawMode;
4410 |
4411 | // Automatically switch to crisp scaling when using a scale
4412 | // other than 1
4413 | if (this.scale != 1) {
4414 | ig.System.scaleMode = ig.System.SCALE.CRISP;
4415 | }
4416 | ig.System.scaleMode(this.canvas, this.context);
4417 | },
4418 |
4419 | resize: function resize(width, height, scale) {
4420 | this.width = width;
4421 | this.height = height;
4422 | this.scale = scale || this.scale;
4423 |
4424 | this.realWidth = this.width * this.scale;
4425 | this.realHeight = this.height * this.scale;
4426 | this.canvas.width = this.realWidth;
4427 | this.canvas.height = this.realHeight;
4428 | },
4429 |
4430 | setGame: function setGame(gameClass) {
4431 | if (this.running) {
4432 | this.newGameClass = gameClass;
4433 | } else {
4434 | this.setGameNow(gameClass);
4435 | }
4436 | },
4437 |
4438 | setGameNow: function setGameNow(gameClass) {
4439 | ig.game = new gameClass();
4440 | ig.system.setDelegate(ig.game);
4441 | },
4442 |
4443 | setDelegate: function setDelegate(object) {
4444 | if (typeof object.run == 'function') {
4445 | this.delegate = object;
4446 | this.startRunLoop();
4447 | } else {
4448 | throw 'System.setDelegate: No run() function in object';
4449 | }
4450 | },
4451 |
4452 | stopRunLoop: function stopRunLoop() {
4453 | ig.clearAnimation(this.animationId);
4454 | this.running = false;
4455 | },
4456 |
4457 | startRunLoop: function startRunLoop() {
4458 | this.stopRunLoop();
4459 | this.animationId = ig.setAnimation(this.run.bind(this), this.canvas);
4460 | this.running = true;
4461 | },
4462 |
4463 | clear: function clear(color) {
4464 | this.context.fillStyle = color;
4465 | this.context.fillRect(0, 0, this.realWidth, this.realHeight);
4466 | },
4467 |
4468 | run: function run() {
4469 | ig.Timer.step();
4470 | this.tick = this.clock.tick();
4471 |
4472 | this.delegate.run();
4473 | ig.input.clearPressed();
4474 |
4475 | if (this.newGameClass) {
4476 | this.setGameNow(this.newGameClass);
4477 | this.newGameClass = null;
4478 | }
4479 | },
4480 |
4481 | getDrawPos: null // Set through constructor
4482 | });
4483 |
4484 | ig.System.DRAW = {
4485 | AUTHENTIC: function AUTHENTIC(p) {
4486 | return Math.round(p) * this.scale;
4487 | },
4488 | SMOOTH: function SMOOTH(p) {
4489 | return Math.round(p * this.scale);
4490 | },
4491 | SUBPIXEL: function SUBPIXEL(p) {
4492 | return p * this.scale;
4493 | }
4494 | };
4495 | ig.System.drawMode = ig.System.DRAW.SMOOTH;
4496 |
4497 | ig.System.SCALE = {
4498 | CRISP: function CRISP(canvas, context) {
4499 | ig.setVendorAttribute(context, 'imageSmoothingEnabled', false);
4500 | canvas.style.imageRendering = '-moz-crisp-edges';
4501 | canvas.style.imageRendering = '-o-crisp-edges';
4502 | canvas.style.imageRendering = '-webkit-optimize-contrast';
4503 | canvas.style.imageRendering = 'crisp-edges';
4504 | canvas.style.msInterpolationMode = 'nearest-neighbor'; // No effect on Canvas :/
4505 | },
4506 | SMOOTH: function SMOOTH(canvas, context) {
4507 | ig.setVendorAttribute(context, 'imageSmoothingEnabled', true);
4508 | canvas.style.imageRendering = '';
4509 | canvas.style.msInterpolationMode = '';
4510 | }
4511 | };
4512 | ig.System.scaleMode = ig.System.SCALE.SMOOTH;
4513 | });
4514 | }.call(window));
4515 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(/*! ig */ 1)))
4516 |
4517 | /***/ },
4518 | /* 24 */
4519 | /*!*****************************!*\
4520 | !*** ./lib/impact/timer.js ***!
4521 | \*****************************/
4522 | /***/ function(module, exports, __webpack_require__) {
4523 |
4524 | /* WEBPACK VAR INJECTION */(function(ig) {/*** IMPORTS FROM imports-loader ***/
4525 | (function() {
4526 |
4527 | "use strict";
4528 |
4529 | ig.module('impact.timer').defines(function () {
4530 | "use strict";
4531 |
4532 | ig.Timer = ig.Class.extend({
4533 | target: 0,
4534 | base: 0,
4535 | last: 0,
4536 | pausedAt: 0,
4537 |
4538 | init: function init(seconds) {
4539 | this.base = ig.Timer.time;
4540 | this.last = ig.Timer.time;
4541 |
4542 | this.target = seconds || 0;
4543 | },
4544 |
4545 | set: function set(seconds) {
4546 | this.target = seconds || 0;
4547 | this.base = ig.Timer.time;
4548 | this.pausedAt = 0;
4549 | },
4550 |
4551 | reset: function reset() {
4552 | this.base = ig.Timer.time;
4553 | this.pausedAt = 0;
4554 | },
4555 |
4556 | tick: function tick() {
4557 | var delta = ig.Timer.time - this.last;
4558 | this.last = ig.Timer.time;
4559 | return this.pausedAt ? 0 : delta;
4560 | },
4561 |
4562 | delta: function delta() {
4563 | return (this.pausedAt || ig.Timer.time) - this.base - this.target;
4564 | },
4565 |
4566 | pause: function pause() {
4567 | if (!this.pausedAt) {
4568 | this.pausedAt = ig.Timer.time;
4569 | }
4570 | },
4571 |
4572 | unpause: function unpause() {
4573 | if (this.pausedAt) {
4574 | this.base += ig.Timer.time - this.pausedAt;
4575 | this.pausedAt = 0;
4576 | }
4577 | }
4578 | });
4579 |
4580 | ig.Timer._last = 0;
4581 | ig.Timer.time = Number.MIN_VALUE;
4582 | ig.Timer.timeScale = 1;
4583 | ig.Timer.maxStep = 0.05;
4584 |
4585 | ig.Timer.step = function () {
4586 | var current = Date.now();
4587 | var delta = (current - ig.Timer._last) / 1000;
4588 | ig.Timer.time += Math.min(delta, ig.Timer.maxStep) * ig.Timer.timeScale;
4589 | ig.Timer._last = current;
4590 | };
4591 | });
4592 | }.call(window));
4593 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(/*! ig */ 1)))
4594 |
4595 | /***/ }
4596 | /******/ ]);
4597 | //# sourceMappingURL=game.min.js.map
--------------------------------------------------------------------------------