Initial commit
@@ -0,0 +1,118 @@
|
||||
Impact Commercial Software License Agreement
|
||||
|
||||
|
||||
1. OWNERSHIP, LICENSE GRANT
|
||||
|
||||
Subject to the terms below (the 'License Agreement'), Dominic Szablewski
|
||||
Anwendungsentwicklung ('We', 'Us') grants you to install and use the Impact
|
||||
Game Engine (the 'Software').
|
||||
|
||||
This is a license agreement and not an agreement for sale. We reserve
|
||||
ownership of all intellectual property rights inherent in or relating to
|
||||
the Software, which include, but are not limited to, all copyright, patent
|
||||
rights, all rights in relation to registered and unregistered trademarks
|
||||
(including service marks), confidential information (including trade
|
||||
secrets and know-how) and all rights other than those expressly granted by
|
||||
this Agreement.
|
||||
|
||||
Subject to the terms and conditions of this License Agreement, We grant to
|
||||
You a non-transferable, non-exclusive license for a Designated User (as
|
||||
defined below) within Your organization to install and use the Software on
|
||||
any workstations used exclusively by such Designated User and for You to
|
||||
distribute the Software as part of your applications or games, solely in
|
||||
connection with distribution of the Software in accordance with sections 3
|
||||
and 4 below. This license is not sublicensable except as explicitly set
|
||||
forth herein. "Designated User(s)" shall mean Your employee(s) acting
|
||||
within the scope of their employment or Your consultant(s) or contractor(s)
|
||||
acting within the scope of the services they provide for You or on Your
|
||||
behalf.
|
||||
|
||||
|
||||
2. PERMITTED USES, SOURCE CODE, MODIFICATIONS
|
||||
|
||||
We provide You with source code so that You can create Modifications of the
|
||||
original Software, where Modification means: a) any addition to or deletion
|
||||
from the contents of a file included in the original Software or previous
|
||||
Modifications created by You, or b) any new file that contains any part of
|
||||
the original Software or previous Modifications. While You retain all
|
||||
rights to any original work authored by You as part of the Modifications,
|
||||
We continue to own all copyright and other intellectual property rights in
|
||||
the Software.
|
||||
|
||||
|
||||
3. DISTRIBUTION
|
||||
|
||||
You may distribute the Software in any applications, frameworks, or
|
||||
elements (collectively referred to as "Applications") that you develop
|
||||
using the Software in accordance with this License Agreement, provided that
|
||||
such distribution does not violate the restrictions set forth in section 4
|
||||
of this agreement.
|
||||
|
||||
You will not owe Us any royalties for Your distribution of the Software in
|
||||
accordance with this License Agreement.
|
||||
|
||||
|
||||
4. PROHIBITED USES
|
||||
|
||||
You may not redistribute the Software or Modifications other than by
|
||||
including the Software or a portion thereof within Your own product, which
|
||||
must have substantially different functionality than the Software or
|
||||
Modifications and must not allow any third party to use the Software or
|
||||
Modifications, or any portions thereof, for software development or
|
||||
application development purposes. You are explicitly not allowed to
|
||||
redistribute the Software or Modifications as part of any product that can
|
||||
be described as a development toolkit or library or is intended for use by
|
||||
software developers or application developers and not end-users.
|
||||
|
||||
|
||||
5. TERMINATION
|
||||
|
||||
This Agreement shall terminate automatically if you fail to comply with the
|
||||
limitations described in this Agreement. No notice shall be required to
|
||||
effectuate such termination. Upon termination, you must remove and destroy
|
||||
all copies of the Software. For the avoidance of doubt, failure to pay
|
||||
invoices, sharing of license keys between users, and/or reselling of
|
||||
activated license keys will result in termination of this agreement.
|
||||
|
||||
|
||||
6. DISCLAIMER OF WARRANTY
|
||||
|
||||
YOU AGREE THAT WE HAVE MADE NO EXPRESS WARRANTIES, ORAL OR WRITTEN, TO YOU
|
||||
REGARDING THE SOFTWARE AND THAT THE SOFTWARE IS BEING PROVIDED TO YOU 'AS
|
||||
IS' WITHOUT WARRANTY OF ANY KIND. WE DISCLAIM ANY AND ALL OTHER WARRANTIES,
|
||||
WHETHER EXPRESSED, IMPLIED, OR STATUTORY. YOUR RIGHTS MAY VARY DEPENDING ON
|
||||
THE STATE IN WHICH YOU LIVE. WE SHALL NOT BE LIABLE FOR INDIRECT,
|
||||
INCIDENTAL, SPECIAL, COVER, RELIANCE, OR CONSEQUENTIAL DAMAGES RESULTING
|
||||
FROM THE USE OF THIS PRODUCT.
|
||||
|
||||
|
||||
7. LIMITATION OF LIABILITY
|
||||
|
||||
YOU USE THIS PROGRAM SOLELY AT YOUR OWN RISK. IN NO EVENT SHALL WE BE
|
||||
LIABLE TO YOU FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO ANY LOSS, OR
|
||||
OTHER INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND ARISING OUT
|
||||
OF THE USE OF THE SOFTWARE, EVEN IF WE HAVE BEEN ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGES. IN NO EVENT WILL WE BE LIABLE FOR ANY CLAIM, WHETHER IN
|
||||
CONTRACT, TORT, OR ANY OTHER THEORY OF LIABILITY, EXCEED THE COST OF THE
|
||||
SOFTWARE. THIS LIMITATION SHALL APPLY TO CLAIMS OF PERSONAL INJURY TO THE
|
||||
EXTENT PERMITTED BY LAW.
|
||||
|
||||
|
||||
8. UPDATES
|
||||
|
||||
You are entitled to receive minor version updates to the Software (i.e.
|
||||
versions identified as follows (X.Y, X.Y+1). You are not entitled to
|
||||
receive major version updates (i.e. X.Y, X+1.Y). Major version updates to
|
||||
the Software are available separately for purchase.
|
||||
|
||||
|
||||
9. MISCELLANEOUS
|
||||
|
||||
The license granted herein applies only to the version of the Software
|
||||
available when purchased in connection with the terms of this Agreement.
|
||||
Any previous or subsequent license granted to You for use of the Software
|
||||
shall be governed by the terms and conditions of the agreement entered in
|
||||
connection with purchase of that version of the Software. You agree that
|
||||
you will comply with all applicable laws and regulations with respect to
|
||||
the Software, including without limitation all export and re-export control
|
||||
laws and regulations.
|
||||
@@ -0,0 +1,31 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>The Adventures of Kuroneko and Shironeko</title>
|
||||
<style type="text/css">
|
||||
html,body {
|
||||
background-color: #333;
|
||||
color: #fff;
|
||||
font-family: helvetica, arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 12pt;
|
||||
}
|
||||
|
||||
#canvas {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type="text/javascript" src="lib/impact/impact.js"></script>
|
||||
<script type="text/javascript" src="lib/game/main.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="canvas"></canvas>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,45 @@
|
||||
ig.module(
|
||||
'game.entities.cheese'
|
||||
)
|
||||
.requires(
|
||||
'impact.entity',
|
||||
'game.entities.kuroneko',
|
||||
)
|
||||
.defines(function() {
|
||||
EntityCheese = ig.Entity.extend({
|
||||
|
||||
collides: ig.Entity.COLLIDES.LITE,
|
||||
|
||||
size: {x: 32, y: 20},
|
||||
offset: {x: 0, y: 12},
|
||||
gravityFactor: 0,
|
||||
|
||||
animSheet: new ig.AnimationSheet('media/cheese.png', 32, 32),
|
||||
|
||||
init: function(x, y, settings) {
|
||||
this.parent(x, y, settings);
|
||||
|
||||
this.addAnim('normal', 1, [0]);
|
||||
},
|
||||
|
||||
update: function() {
|
||||
this.parent();
|
||||
|
||||
this.currentAnim = this.anims.normal;
|
||||
},
|
||||
|
||||
collideWith: function(other, axis) {
|
||||
this.player = ig.game.getEntitiesByType(EntityKuroneko)[0];
|
||||
if (other instanceof EntityKuroneko) {
|
||||
this.kill();
|
||||
if (this.player.health < 4) {
|
||||
this.player.health += 1;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
kill: function() {
|
||||
ig.game.removeEntity(this);
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,25 @@
|
||||
ig.module(
|
||||
'game.entities.easteregg'
|
||||
)
|
||||
.requires(
|
||||
'impact.entity',
|
||||
'game.entities.kuroneko',
|
||||
'game.entities.cheese',
|
||||
)
|
||||
.defines(function() {
|
||||
EntityEasteregg = EntityCheese.extend({
|
||||
|
||||
animSheet: new ig.AnimationSheet('media/easteregg.png', 32, 32),
|
||||
|
||||
collideWith: function(other, axis) {
|
||||
this.player = ig.game.getEntitiesByType(EntityKuroneko)[0];
|
||||
if (other instanceof EntityKuroneko) {
|
||||
this.kill();
|
||||
ig.game.score += 10000;
|
||||
if (this.player.health < 4) {
|
||||
this.player.health += 4;
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,24 @@
|
||||
ig.module(
|
||||
'game.entities.endgame'
|
||||
)
|
||||
.requires(
|
||||
'impact.entity',
|
||||
'game.entities.kuroneko',
|
||||
'game.entities.nextlevel',
|
||||
)
|
||||
.defines(function() {
|
||||
EntityEndgame = EntityNextlevel.extend({
|
||||
check: function( other ) {
|
||||
if(other instanceof EntityKuroneko){
|
||||
this.player = ig.game.getEntitiesByType(EntityKuroneko)[0];
|
||||
this.player.currentAnim = this.player.anims.nothing;
|
||||
this.player.speed = 0;
|
||||
if (ig.game.score == 0 || ig.game.score == 10000) {
|
||||
setTimeout(function() {ig.game.loadLevel( LevelGoodend );}.bind(this), 1000);
|
||||
} else {
|
||||
setTimeout(function() {ig.game.loadLevel( LevelBadend );}.bind(this), 1000);
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,132 @@
|
||||
ig.module(
|
||||
'game.entities.kuroneko'
|
||||
)
|
||||
.requires(
|
||||
'impact.entity'
|
||||
)
|
||||
.defines(function() {
|
||||
|
||||
EntityKuroneko = ig.Entity.extend({
|
||||
collides: ig.Entity.COLLIDES.ACTIVE,
|
||||
|
||||
size: {x: 24, y: 28},
|
||||
offset: {x: 4, y: 4},
|
||||
gravityFactor: 4,
|
||||
maxVel: {x: 150, y: 520},
|
||||
speed: 400,
|
||||
jump_height: 800,
|
||||
friction: {x: 500, y: 0},
|
||||
health: 4,
|
||||
type: ig.Entity.TYPE.A,
|
||||
is_dead: false,
|
||||
flip: false,
|
||||
kuro: true,
|
||||
|
||||
animSheet: new ig.AnimationSheet('media/kuroneko.png', 32, 32),
|
||||
jumpSheet: new ig.AnimationSheet('media/kuroneko-jump.png', 46, 32),
|
||||
|
||||
init: function(x, y, settings) {
|
||||
this.parent(x, y, settings);
|
||||
|
||||
this.invincibleTimer = new ig.Timer();
|
||||
|
||||
this.addAnim('idle', 1, [0]);
|
||||
this.addAnim('walk', 0.13, [2,3,4,5,4,3]);
|
||||
this.addAnim('idle_shiro', 1, [6]);
|
||||
this.addAnim('walk_shiro', 0.13, [8,9,10,11,10,9]);
|
||||
this.addAnim('nothing', 1, [20]);
|
||||
this.anims.jump = new ig.Animation(this.jumpSheet, 1, [0]);
|
||||
this.anims.jump_shiro = new ig.Animation(this.jumpSheet, 1, [1]);
|
||||
},
|
||||
|
||||
update: function() {
|
||||
this.parent();
|
||||
|
||||
this.currentAnim.flip.x = this.flip;
|
||||
|
||||
//Handle movement
|
||||
if (ig.input.state('right')) {
|
||||
this.accel.x = this.speed;
|
||||
this.flip = false;
|
||||
} else if (ig.input.state('left')) {
|
||||
this.accel.x = -this.speed;
|
||||
this.flip = true;
|
||||
} else {
|
||||
this.accel.x = 0;
|
||||
}
|
||||
if (ig.input.pressed('up') && this.standing) {
|
||||
if (this.vel.y == 0) {
|
||||
this.vel.y -= this.jump_height;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.pos.y > 640 - 32) {
|
||||
this.kill();
|
||||
}
|
||||
|
||||
//Handle animations
|
||||
if (this.kuro) {
|
||||
if (this.vel.y != 0 && !this.standing) {
|
||||
this.offset = { x: 10, y: 4 };
|
||||
this.currentAnim = this.anims.jump;
|
||||
} else if (this.vel.x != 0 && this.standing) {
|
||||
this.offset = { x: 4, y: 4 };
|
||||
this.currentAnim = this.anims.walk;
|
||||
} else {
|
||||
this.offset = { x: 4, y: 4 };
|
||||
this.currentAnim = this.anims.idle;
|
||||
}
|
||||
} else {
|
||||
if (this.vel.y != 0 && !this.standing) {
|
||||
this.offset = { x: 10, y: 4 };
|
||||
this.currentAnim = this.anims.jump_shiro;
|
||||
} else if (this.vel.x != 0 && this.standing) {
|
||||
this.offset = { x: 4, y: 4 };
|
||||
this.currentAnim = this.anims.walk_shiro;
|
||||
} else {
|
||||
this.offset = { x: 4, y: 4 };
|
||||
this.currentAnim = this.anims.idle_shiro;
|
||||
}
|
||||
}
|
||||
|
||||
//Change color on different BGs
|
||||
if (ig.game.currentLevel == LevelLevel1) {
|
||||
if (this.pos.x > 832 && this.pos.x < 1568) {
|
||||
this.kuro = false;
|
||||
} else if (this.pos.x > 1568 && this.pos.x < 2368) {
|
||||
this.kuro = true;
|
||||
} else if (this.pos.x > 2368) {
|
||||
this.kuro = false;
|
||||
} else {
|
||||
this.kuro = true;
|
||||
}
|
||||
} else if (ig.game.currentLevel == LevelLevel2) {
|
||||
if (this.pos.x > 1023 && this.pos.x < 2016) {
|
||||
this.kuro = false;
|
||||
} else if (this.pos.x > 2016 && this.pos.x < 3008) {
|
||||
this.kuro = true;
|
||||
} else if (this.pos.x > 3008 && this.pos.x < 4000) {
|
||||
this.kuro = false;
|
||||
} else if (this.pos.x > 4000 && this.pos.x < 4992) {
|
||||
this.kuro = true;
|
||||
} else if (this.pos.x > 4992 && this.pos.x < 5984) {
|
||||
this.kuro = false;
|
||||
} else if (this.pos.x > 5984) {
|
||||
this.kuro = true;
|
||||
} else {
|
||||
this.kuro = true;
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
kill: function() {
|
||||
this.is_dead = true;
|
||||
ig.game.removeEntity(this);
|
||||
ig.game.score = 0;
|
||||
|
||||
setTimeout(function() {ig.game.loadLevel(LevelGameover)}, 700);
|
||||
}
|
||||
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,88 @@
|
||||
ig.module(
|
||||
'game.entities.mouse'
|
||||
)
|
||||
.requires(
|
||||
'impact.entity',
|
||||
'game.entities.kuroneko',
|
||||
)
|
||||
.defines(function() {
|
||||
EntityMouse = ig.Entity.extend({
|
||||
|
||||
collides: ig.Entity.COLLIDES.PASSIVE,
|
||||
|
||||
size: {x: 26, y: 9},
|
||||
gravityFactor: 4,
|
||||
speed: 100,
|
||||
maxVel: {x: 300, y: 100},
|
||||
flip: true,
|
||||
player: null,
|
||||
is_dead: false,
|
||||
|
||||
animSheet: new ig.AnimationSheet('media/mouse.png', 26, 9),
|
||||
|
||||
init: function(x, y, settings) {
|
||||
this.parent(x, y, settings);
|
||||
|
||||
this.addAnim('normal', 1, [0]);
|
||||
this.addAnim('dead', 1, [1]);
|
||||
},
|
||||
|
||||
update: function() {
|
||||
this.parent();
|
||||
|
||||
if (!this.is_dead) {
|
||||
this.currentAnim = this.anims.normal;
|
||||
} else {
|
||||
this.currentAnim = this.anims.dead;
|
||||
this.currentAnim.flip.y = true;
|
||||
}
|
||||
this.currentAnim.flip.x = this.flip;
|
||||
|
||||
var xdir = this.flip ? -1:1;
|
||||
this.vel.x = this.speed * this.turnAround();;
|
||||
},
|
||||
|
||||
handleMovementTrace: function(res) {
|
||||
this.parent(res);
|
||||
|
||||
if (res.collision.x) {
|
||||
this.flip = !this.flip;
|
||||
}
|
||||
},
|
||||
|
||||
collideWith: function(other, axis) {
|
||||
this.player = ig.game.getEntitiesByType(EntityKuroneko)[0];
|
||||
if (other instanceof EntityKuroneko) {
|
||||
if (axis === 'y') {
|
||||
this.kill();
|
||||
this.player.vel.y = -200;
|
||||
ig.game.score += 100;
|
||||
} else if (axis === 'x') {
|
||||
this.player.receiveDamage(1, this);
|
||||
if (this.player.pos.x < this.pos.x) {
|
||||
this.player.vel.x = -400;
|
||||
} else {
|
||||
this.player.vel.x = 400;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
turnAround: function(){
|
||||
//is the next collision tile empty
|
||||
var x = this.pos.x + (this.flip ? + 5 : this.size.x - 5);
|
||||
var y = this.pos.y + this.size.y + 5;
|
||||
if(!ig.game.collisionMap.getTile(x, y)){
|
||||
this.flip = !this.flip;
|
||||
}
|
||||
return this.flip ? -1 : 1;
|
||||
},
|
||||
|
||||
kill: function() {
|
||||
this.is_dead = true;
|
||||
this.speed = 0;
|
||||
this.collides = ig.Entity.COLLIDES.NEVER;
|
||||
setTimeout(function(){ig.game.removeEntity(this);}.bind(this), 500);
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,30 @@
|
||||
ig.module(
|
||||
'game.entities.nextlevel'
|
||||
)
|
||||
.requires(
|
||||
'impact.entity',
|
||||
'game.entities.kuroneko',
|
||||
)
|
||||
.defines(function() {
|
||||
EntityNextlevel = ig.Entity.extend({
|
||||
_wmDrawBox: true,
|
||||
_wmBoxColor: 'rgba(0, 0, 255, 0.7)',
|
||||
size: {x: 16, y: 48},
|
||||
gravityFactor: 0,
|
||||
checkAgainst: ig.Entity.TYPE.A,
|
||||
player: null,
|
||||
|
||||
update: function(x, y, settings) {
|
||||
this.parent(x, y, settings);
|
||||
},
|
||||
|
||||
check: function( other ) {
|
||||
if(other instanceof EntityKuroneko){
|
||||
this.player = ig.game.getEntitiesByType(EntityKuroneko)[0];
|
||||
this.player.currentAnim = this.player.anims.nothing;
|
||||
this.player.speed = 0;
|
||||
setTimeout(function() {ig.game.loadLevel( LevelLevel2 );}.bind(this), 1000);
|
||||
}
|
||||
},
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,40 @@
|
||||
ig.module( 'game.levels.badend' )
|
||||
.requires( 'impact.image' )
|
||||
.defines(function(){
|
||||
LevelBadend=/*JSON[*/{
|
||||
"entities": [],
|
||||
"layer": [
|
||||
{
|
||||
"name": "main",
|
||||
"width": 20,
|
||||
"height": 15,
|
||||
"linkWithCollision": false,
|
||||
"visible": true,
|
||||
"tilesetName": "media/badend.png",
|
||||
"repeat": false,
|
||||
"preRender": false,
|
||||
"distance": "1",
|
||||
"tilesize": 32,
|
||||
"foreground": false,
|
||||
"data": [
|
||||
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20],
|
||||
[21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40],
|
||||
[41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60],
|
||||
[61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80],
|
||||
[81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100],
|
||||
[101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120],
|
||||
[121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140],
|
||||
[141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160],
|
||||
[161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180],
|
||||
[181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200],
|
||||
[201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220],
|
||||
[221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240],
|
||||
[241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260],
|
||||
[261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280],
|
||||
[281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300]
|
||||
]
|
||||
}
|
||||
]
|
||||
}/*]JSON*/;
|
||||
LevelBadendResources=[new ig.Image('media/badend.png')];
|
||||
});
|
||||
@@ -0,0 +1,40 @@
|
||||
ig.module( 'game.levels.gameover' )
|
||||
.requires( 'impact.image' )
|
||||
.defines(function(){
|
||||
LevelGameover=/*JSON[*/{
|
||||
"entities": [],
|
||||
"layer": [
|
||||
{
|
||||
"name": "main",
|
||||
"width": 20,
|
||||
"height": 15,
|
||||
"linkWithCollision": false,
|
||||
"visible": true,
|
||||
"tilesetName": "media/gameover.png",
|
||||
"repeat": false,
|
||||
"preRender": false,
|
||||
"distance": "1",
|
||||
"tilesize": 32,
|
||||
"foreground": false,
|
||||
"data": [
|
||||
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20],
|
||||
[21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40],
|
||||
[41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60],
|
||||
[61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80],
|
||||
[81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100],
|
||||
[101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120],
|
||||
[121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140],
|
||||
[141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160],
|
||||
[161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180],
|
||||
[181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200],
|
||||
[201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220],
|
||||
[221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240],
|
||||
[241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260],
|
||||
[261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280],
|
||||
[281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300]
|
||||
]
|
||||
}
|
||||
]
|
||||
}/*]JSON*/;
|
||||
LevelGameoverResources=[new ig.Image('media/gameover.png')];
|
||||
});
|
||||
@@ -0,0 +1,40 @@
|
||||
ig.module( 'game.levels.goodend' )
|
||||
.requires( 'impact.image' )
|
||||
.defines(function(){
|
||||
LevelGoodend=/*JSON[*/{
|
||||
"entities": [],
|
||||
"layer": [
|
||||
{
|
||||
"name": "main",
|
||||
"width": 20,
|
||||
"height": 15,
|
||||
"linkWithCollision": false,
|
||||
"visible": true,
|
||||
"tilesetName": "media/goodend.png",
|
||||
"repeat": false,
|
||||
"preRender": false,
|
||||
"distance": "1",
|
||||
"tilesize": 32,
|
||||
"foreground": false,
|
||||
"data": [
|
||||
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20],
|
||||
[21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40],
|
||||
[41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60],
|
||||
[61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80],
|
||||
[81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100],
|
||||
[101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120],
|
||||
[121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140],
|
||||
[141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160],
|
||||
[161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180],
|
||||
[181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200],
|
||||
[201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220],
|
||||
[221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240],
|
||||
[241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260],
|
||||
[261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280],
|
||||
[281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300]
|
||||
]
|
||||
}
|
||||
]
|
||||
}/*]JSON*/;
|
||||
LevelGoodendResources=[new ig.Image('media/goodend.png')];
|
||||
});
|
||||
@@ -0,0 +1,111 @@
|
||||
ig.module( 'game.levels.level1' )
|
||||
.requires( 'impact.image','game.entities.kuroneko','game.entities.cheese','game.entities.mouse','game.entities.nextlevel','game.entities.easteregg' )
|
||||
.defines(function(){
|
||||
LevelLevel1=/*JSON[*/{
|
||||
"entities": [
|
||||
{
|
||||
"type": "EntityKuroneko",
|
||||
"x": 108,
|
||||
"y": 580
|
||||
},
|
||||
{
|
||||
"type": "EntityCheese",
|
||||
"x": 1828,
|
||||
"y": 588
|
||||
},
|
||||
{
|
||||
"type": "EntityMouse",
|
||||
"x": 1260,
|
||||
"y": 584
|
||||
},
|
||||
{
|
||||
"type": "EntityMouse",
|
||||
"x": 2144,
|
||||
"y": 496
|
||||
},
|
||||
{
|
||||
"type": "EntityNextlevel",
|
||||
"x": 3064,
|
||||
"y": 552
|
||||
},
|
||||
{
|
||||
"type": "EntityEasteregg",
|
||||
"x": 3136,
|
||||
"y": 76
|
||||
}
|
||||
],
|
||||
"layer": [
|
||||
{
|
||||
"name": "main",
|
||||
"width": 100,
|
||||
"height": 20,
|
||||
"linkWithCollision": false,
|
||||
"visible": 1,
|
||||
"tilesetName": "media/tutorial.png",
|
||||
"repeat": false,
|
||||
"preRender": false,
|
||||
"distance": "1",
|
||||
"tilesize": 32,
|
||||
"foreground": false,
|
||||
"data": [
|
||||
[130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,567,567,567,567,567,567,567,567,567,567,567,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,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,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640],
|
||||
[130,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,640],
|
||||
[130,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,640],
|
||||
[130,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,640],
|
||||
[130,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,640],
|
||||
[130,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,640],
|
||||
[130,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,640],
|
||||
[130,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,640],
|
||||
[130,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,640],
|
||||
[130,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,640],
|
||||
[130,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,975,976,977,978,979,980,640],
|
||||
[130,981,982,983,984,985,986,987,988,989,990,991,992,993,994,995,996,997,998,999,1000,1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1013,1014,1015,1016,1017,1018,1019,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,640],
|
||||
[130,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,1104,1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116,1117,1118,1119,1120,1121,1122,1123,1124,1125,1126,1127,1128,1129,1130,1131,1132,1133,1134,1135,1136,1137,1138,1139,1140,1141,1142,1143,1144,1145,1146,1147,1148,1149,1150,1151,1152,1153,1154,1155,1156,1157,1158,1159,1160,1161,1162,1163,1164,1165,1166,1167,1168,1169,1170,1171,1172,1173,1174,1175,1176,640],
|
||||
[130,1177,1178,1179,1180,1181,1182,1183,1184,1185,1186,1187,1188,1189,1190,1191,1192,1193,1194,1195,1196,1197,1198,1199,1200,1201,1202,1203,1204,1205,1206,1207,1208,1209,1210,1211,1212,1213,1214,1215,1216,1217,1218,1219,1220,1221,1222,1223,1224,1225,1226,1227,1228,1229,1230,1231,1232,1233,1234,1235,1236,1237,1238,1239,1240,1241,1242,1243,1244,1245,1246,1247,1248,1249,1250,1251,1252,1253,1254,1255,1256,1257,1258,1259,1260,1261,1262,1263,1264,1265,1266,1267,1268,1269,1270,1271,1272,1273,1274,640],
|
||||
[130,1275,1276,1277,1278,1279,1280,1281,1282,1283,1284,1285,1286,1287,1288,1289,1290,1291,1292,1293,1294,1295,1296,1297,1298,1299,1300,1301,1302,1303,1304,1305,1306,1307,1308,1309,1228,1228,1228,1313,1314,1228,1228,1228,1318,1319,1320,1321,1322,1323,1324,1325,1326,1327,1328,1329,1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,1341,1342,1343,1344,1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359,1360,1361,1362,1363,1364,1365,1366,1367,1368,1369,1370,1371,1372,640],
|
||||
[130,1373,1374,1375,1376,1377,1378,1379,1380,1381,1382,1383,1384,1385,1386,1387,1388,1389,1390,1391,1392,1393,1394,1395,1396,1397,1398,1399,1400,1401,1402,1403,1404,1405,1406,1407,1228,1409,1410,1411,1412,1413,1414,1228,1416,1417,1418,1419,1420,1421,1422,1423,1424,1425,1426,1427,1428,1429,1430,1431,1432,1433,1434,862,862,1437,1438,1439,1440,1441,862,862,1444,1445,1446,1447,1448,1449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,0,1467,1468,1469,1470,640],
|
||||
[130,1471,1472,1473,1474,1475,1476,1477,1478,1479,1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1228,1507,1508,1509,1510,1511,1512,1228,1514,1515,1516,1517,1518,1519,1520,1521,1522,1523,1524,1525,1526,1527,1528,1529,1530,1531,1532,1533,1534,862,862,862,862,862,1540,1541,1542,1543,1544,1545,1546,1547,1548,1549,1550,1551,1552,1553,1554,1555,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565,1566,1567,1568,640],
|
||||
[130,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,1599,1600,1601,1602,1603,1228,1605,1606,1607,1608,1609,1610,1228,1612,1613,1614,1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,1629,1630,1631,1632,1633,1634,1635,1636,1637,1638,1639,1640,1641,1642,1643,1644,1645,1646,1647,1648,1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,1659,1660,1661,1662,1663,1664,1665,1666,640],
|
||||
[130,1667,1668,1669,1670,1671,1672,1673,1674,1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700,1701,1228,1703,1704,1705,1706,1707,1708,1228,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,1720,1721,1722,1723,1724,1725,1726,1727,854,854,658,1342,1342,1733,1734,1735,1736,854,854,658,1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,640],
|
||||
[130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,567,567,567,567,567,567,567,567,567,567,567,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,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,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "collision",
|
||||
"width": 100,
|
||||
"height": 20,
|
||||
"linkWithCollision": false,
|
||||
"visible": 1,
|
||||
"tilesetName": "",
|
||||
"repeat": false,
|
||||
"preRender": false,
|
||||
"distance": 1,
|
||||
"tilesize": 32,
|
||||
"foreground": false,
|
||||
"data": [
|
||||
[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,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,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,1,1,1,1],
|
||||
[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,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,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,0,0,0,0,0,0,0,0,1],
|
||||
[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,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,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,0,0,0,0,0,0,0,0,1],
|
||||
[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,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,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,0,0,0,0,12,12,12,12,1],
|
||||
[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,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,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,0,0,0,0,0,0,0,0,1],
|
||||
[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,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,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,0,0,0,0,0,0,0,0,1],
|
||||
[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,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,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,0,0,0,0,12,12,12,12,1],
|
||||
[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,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,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,0,0,0,0,0,0,0,0,1],
|
||||
[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,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,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,0,0,0,0,0,0,0,0,1],
|
||||
[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,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,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,0,0,0,0,0,0,0,0,1],
|
||||
[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,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,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,0,0,0,0,12,12,12,12,1],
|
||||
[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,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,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,0,0,0,0,0,0,0,0,1],
|
||||
[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,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,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,0,0,0,0,0,0,0,0,1],
|
||||
[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,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,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,0,0,0,0,0,0,0,0,1],
|
||||
[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,0,0,0,0,0,1,1,1,0,0,1,1,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,12,12,12,1],
|
||||
[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,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,1,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,1],
|
||||
[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,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,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,1],
|
||||
[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,0,0,0,0,0,1,0,0,0,0,0,0,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,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],
|
||||
[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,0,0,0,0,0,1,0,0,0,0,0,0,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,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],
|
||||
[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,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,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,1,1,1,1]
|
||||
]
|
||||
}
|
||||
]
|
||||
}/*]JSON*/;
|
||||
LevelLevel1Resources=[new ig.Image('media/tutorial.png')];
|
||||
});
|
||||
@@ -0,0 +1,281 @@
|
||||
ig.module( 'game.levels.level2' )
|
||||
.requires( 'impact.image','game.entities.mouse','game.entities.cheese','game.entities.endgame','game.entities.kuroneko' )
|
||||
.defines(function(){
|
||||
LevelLevel2=/*JSON[*/{
|
||||
"entities": [
|
||||
{
|
||||
"type": "EntityMouse",
|
||||
"x": 1188,
|
||||
"y": 484
|
||||
},
|
||||
{
|
||||
"type": "EntityMouse",
|
||||
"x": 1248,
|
||||
"y": 484
|
||||
},
|
||||
{
|
||||
"type": "EntityCheese",
|
||||
"x": 2992,
|
||||
"y": 172
|
||||
},
|
||||
{
|
||||
"type": "EntityCheese",
|
||||
"x": 3420,
|
||||
"y": 588
|
||||
},
|
||||
{
|
||||
"type": "EntityCheese",
|
||||
"x": 2540,
|
||||
"y": 396
|
||||
},
|
||||
{
|
||||
"type": "EntityMouse",
|
||||
"x": 2420,
|
||||
"y": 588
|
||||
},
|
||||
{
|
||||
"type": "EntityCheese",
|
||||
"x": 2532,
|
||||
"y": 232
|
||||
},
|
||||
{
|
||||
"type": "EntityCheese",
|
||||
"x": 4352,
|
||||
"y": 408
|
||||
},
|
||||
{
|
||||
"type": "EntityMouse",
|
||||
"x": 2160,
|
||||
"y": 592
|
||||
},
|
||||
{
|
||||
"type": "EntityMouse",
|
||||
"x": 2700,
|
||||
"y": 300
|
||||
},
|
||||
{
|
||||
"type": "EntityMouse",
|
||||
"x": 2328,
|
||||
"y": 300
|
||||
},
|
||||
{
|
||||
"type": "EntityMouse",
|
||||
"x": 2812,
|
||||
"y": 460
|
||||
},
|
||||
{
|
||||
"type": "EntityMouse",
|
||||
"x": 2044,
|
||||
"y": 588
|
||||
},
|
||||
{
|
||||
"type": "EntityCheese",
|
||||
"x": 3480,
|
||||
"y": 588
|
||||
},
|
||||
{
|
||||
"type": "EntityMouse",
|
||||
"x": 2352,
|
||||
"y": 468
|
||||
},
|
||||
{
|
||||
"type": "EntityMouse",
|
||||
"x": 544,
|
||||
"y": 440
|
||||
},
|
||||
{
|
||||
"type": "EntityCheese",
|
||||
"x": 3536,
|
||||
"y": 588
|
||||
},
|
||||
{
|
||||
"type": "EntityMouse",
|
||||
"x": 3480,
|
||||
"y": 404
|
||||
},
|
||||
{
|
||||
"type": "EntityMouse",
|
||||
"x": 1680,
|
||||
"y": 488
|
||||
},
|
||||
{
|
||||
"type": "EntityMouse",
|
||||
"x": 1880,
|
||||
"y": 488
|
||||
},
|
||||
{
|
||||
"type": "EntityCheese",
|
||||
"x": 1404,
|
||||
"y": 492
|
||||
},
|
||||
{
|
||||
"type": "EntityCheese",
|
||||
"x": 4352,
|
||||
"y": 428
|
||||
},
|
||||
{
|
||||
"type": "EntityCheese",
|
||||
"x": 4384,
|
||||
"y": 428
|
||||
},
|
||||
{
|
||||
"type": "EntityCheese",
|
||||
"x": 4416,
|
||||
"y": 428
|
||||
},
|
||||
{
|
||||
"type": "EntityCheese",
|
||||
"x": 4448,
|
||||
"y": 428
|
||||
},
|
||||
{
|
||||
"type": "EntityCheese",
|
||||
"x": 4480,
|
||||
"y": 428
|
||||
},
|
||||
{
|
||||
"type": "EntityCheese",
|
||||
"x": 4512,
|
||||
"y": 428
|
||||
},
|
||||
{
|
||||
"type": "EntityCheese",
|
||||
"x": 4548,
|
||||
"y": 408
|
||||
},
|
||||
{
|
||||
"type": "EntityCheese",
|
||||
"x": 4548,
|
||||
"y": 428
|
||||
},
|
||||
{
|
||||
"type": "EntityCheese",
|
||||
"x": 4512,
|
||||
"y": 408
|
||||
},
|
||||
{
|
||||
"type": "EntityCheese",
|
||||
"x": 4480,
|
||||
"y": 408
|
||||
},
|
||||
{
|
||||
"type": "EntityCheese",
|
||||
"x": 4448,
|
||||
"y": 408
|
||||
},
|
||||
{
|
||||
"type": "EntityCheese",
|
||||
"x": 4416,
|
||||
"y": 408
|
||||
},
|
||||
{
|
||||
"type": "EntityCheese",
|
||||
"x": 4384,
|
||||
"y": 408
|
||||
},
|
||||
{
|
||||
"type": "EntityEndgame",
|
||||
"x": 6280,
|
||||
"y": 560
|
||||
},
|
||||
{
|
||||
"type": "EntityMouse",
|
||||
"x": 424,
|
||||
"y": 440
|
||||
},
|
||||
{
|
||||
"type": "EntityMouse",
|
||||
"x": 648,
|
||||
"y": 440
|
||||
},
|
||||
{
|
||||
"type": "EntityMouse",
|
||||
"x": 456,
|
||||
"y": 440
|
||||
},
|
||||
{
|
||||
"type": "EntityMouse",
|
||||
"x": 368,
|
||||
"y": 440
|
||||
},
|
||||
{
|
||||
"type": "EntityKuroneko",
|
||||
"x": 132,
|
||||
"y": 580
|
||||
}
|
||||
],
|
||||
"layer": [
|
||||
{
|
||||
"name": "main",
|
||||
"width": 200,
|
||||
"height": 20,
|
||||
"linkWithCollision": false,
|
||||
"visible": 1,
|
||||
"tilesetName": "media/level1.png",
|
||||
"repeat": false,
|
||||
"preRender": false,
|
||||
"distance": "1",
|
||||
"tilesize": 32,
|
||||
"foreground": false,
|
||||
"data": [
|
||||
[2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084],
|
||||
[2084,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,2084],
|
||||
[2084,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,2084],
|
||||
[2084,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,2084],
|
||||
[2084,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,2084],
|
||||
[2084,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,975,976,977,978,979,980,981,982,983,984,985,986,987,988,989,990,2084],
|
||||
[2084,991,992,993,994,995,996,997,998,999,1000,1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1013,1014,1015,1016,1017,1018,1019,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1373,1373,1373,2369,2369,2369,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,1104,1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116,1117,1118,1119,1120,1121,1122,1123,1124,1125,1126,1127,1128,1129,1130,1131,1132,1133,1134,1135,1136,1137,1138,1139,1140,1141,1142,1143,1144,1145,1146,1147,1148,1149,1150,1151,1152,1153,1154,1155,1156,1157,1158,1159,1160,1161,1162,1163,1164,1165,1166,1167,1168,1169,1170,1171,1172,1173,1174,1175,1176,1177,1178,1179,1180,1181,1182,1183,1184,1185,1186,1187,1188,2084],
|
||||
[2084,1189,1190,1191,1192,1193,1194,1195,1196,1197,1198,1199,1200,1201,1202,1203,1204,1205,1206,1207,1208,1209,1210,1211,1212,1213,1214,1215,1216,1217,1218,1219,1220,1221,1222,1223,1224,1225,1226,1227,1228,1229,1230,1231,1232,1233,1234,1235,1236,1237,1238,1239,1240,1241,1242,1243,1244,1245,1246,1247,1248,1249,1250,1251,1252,1253,1254,1255,1256,1257,1258,1259,1260,1261,1262,1263,1264,1265,1266,1267,1268,1269,1270,1271,1272,1273,1274,1275,1276,1277,1278,1279,1280,1281,1282,1283,1284,1285,1286,1287,1288,1289,1290,1291,1292,1293,1294,1295,1296,1297,1298,1299,1300,1301,1302,1303,1304,1305,1306,1307,1308,1309,1310,1311,1312,1313,1314,1315,1316,1317,1318,1319,1320,1321,1322,1323,1324,1325,1326,1327,1328,1329,1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,1341,1342,1343,1344,1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359,1360,1361,1362,1363,1364,1365,1366,1367,1368,1369,1370,1371,1372,1373,1374,1375,1376,1377,1378,1379,1380,1381,1382,1383,1384,1385,1386,2084],
|
||||
[2084,1387,1388,1389,1390,1391,1392,1393,1394,1395,1396,1397,1398,1399,1400,1401,1402,1403,1404,1405,1406,1407,1408,1409,1410,1411,1412,1413,1414,1415,1416,1417,1418,1419,1420,1421,1422,1423,1424,1425,1426,1427,1428,1429,1430,1431,1432,1433,1434,1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,1445,1446,1447,1448,1449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1476,1477,1478,1479,1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,1515,1516,1517,1518,1519,1520,1521,1522,1523,1524,1525,1526,1527,1528,1529,1530,1531,1532,1533,1534,1535,1536,1537,1538,1539,1540,1541,1542,1543,1544,1545,1546,1547,1548,1549,1550,1551,1552,1553,1554,1555,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565,1566,1567,1568,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,2084],
|
||||
[2084,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,1599,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,1629,1630,1631,1632,1633,1634,1635,1636,1637,1638,1639,1640,1641,1642,1643,1644,1645,1646,1647,1648,1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,1659,1660,1661,1662,1663,1664,1665,1666,1667,1668,1669,1670,1671,1672,1673,1674,1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,1704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1929,1720,1721,1722,1723,1724,1725,1726,1929,1728,1729,1730,1731,1732,1733,1734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,1765,1766,1767,1768,1769,1770,1771,1772,1773,1774,1775,1776,1777,1778,1779,1780,1781,1782,2084],
|
||||
[2084,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,1794,1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805,1806,1807,1808,1809,1810,1811,1812,1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,1824,1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1562,1562,1562,1562,1562,1857,1858,1859,1860,1861,1862,1863,1864,1865,1562,1562,1562,1562,1562,1871,1872,1873,1874,1875,1876,1877,1878,1879,2369,2369,2369,2369,2369,1885,1886,1887,1888,1889,1890,1891,1892,1893,1894,1895,1896,1897,1898,1899,1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,1915,1916,1929,1918,1919,1920,1921,1922,1923,1924,1929,1926,1927,1928,1929,1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,1944,1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1957,1958,1959,1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,1974,1975,1976,1977,1978,1979,1980,2084],
|
||||
[2084,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2034,2035,2036,2037,2038,2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,2049,2050,2051,2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,2064,2065,2066,2067,2068,2069,2070,2071,2072,2073,2074,2075,2076,2077,2078,2079,2080,2081,2082,2083,2084,2085,2086,2087,2088,2089,2090,2091,2092,2093,2094,2095,2096,2097,2098,2099,2100,2101,2102,2103,2104,2105,2106,2107,2108,2109,2110,2111,2112,2113,2114,1929,2116,2117,2118,2119,2120,2121,2122,1929,2124,2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2136,2137,2138,2139,2140,2141,2142,2143,2144,2145,2146,2147,2148,2149,2150,2151,2152,2153,2154,2155,2156,2157,2158,2159,2160,2161,2162,2163,2164,2165,2166,2167,2168,2169,2170,2171,2172,2173,2174,2175,2176,2177,2178,2084],
|
||||
[2084,2179,2180,2181,2182,2183,2184,2185,2186,2187,2188,2189,2190,2191,2192,2193,2194,2195,2196,2197,2198,2199,2200,2201,2202,2203,2204,2205,2206,2207,2208,2209,2210,2211,2212,2213,2214,2215,2216,2217,2218,2219,2220,2221,2222,2223,2224,2225,2226,2227,2228,2229,2230,2231,2232,2233,2234,2235,2236,2237,2238,2239,2240,2241,2242,2243,2244,2245,2246,2247,2248,2249,2250,2251,2252,2253,2254,2255,2256,2257,2258,2259,2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2274,2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,2302,2303,2304,2305,2306,2307,2308,2309,2310,2311,2312,1562,2314,2315,2316,2317,2318,2319,2320,1562,2322,2323,2324,2325,2326,2327,2328,2329,2330,2331,2332,2333,2334,2335,2336,2337,2338,2339,2340,2341,2342,2343,2344,2345,2346,2347,2348,2349,2350,2351,2352,2353,2354,2355,2356,2357,2358,2359,2360,2361,2362,2363,2364,2365,2366,2367,2368,2369,2370,2371,2372,2373,2374,2375,2376,2084],
|
||||
[2084,2377,2378,2379,2380,2381,2382,2383,2384,2385,2386,2387,2388,2389,2390,2391,2392,2393,2394,2395,2396,2397,2398,2399,2400,2401,2402,2403,2404,2405,2406,2407,2408,2409,2410,2411,2412,2413,2414,2415,2416,2417,2418,2419,2420,2421,2422,2423,2424,2425,2426,2427,2428,2429,2430,2431,2432,2433,2434,2435,2436,2437,2438,2439,2440,2441,2442,2443,2444,2445,2446,2447,2448,2449,2450,2451,2452,2453,2454,2455,2456,2457,2458,2459,2460,2461,2462,2463,2464,2465,2466,2467,2468,2469,2470,2471,2472,2473,2474,2475,2476,2477,2478,2479,2480,2084,2084,2084,2084,2084,2084,2084,2084,2084,2490,2491,2492,2493,2494,2495,2496,2497,2498,2499,2500,2501,2502,2503,2504,2505,2506,2507,2508,2509,2510,1562,2512,2513,2514,2515,2516,2517,2518,1562,2520,2521,2522,2523,2524,2525,2526,2527,2528,2529,2530,2531,2532,2533,2534,2535,2536,2537,2538,2539,2540,2541,2542,2543,2544,2545,2546,2547,2548,2549,2550,2551,2552,2553,2554,2555,2556,2557,2558,2559,2560,2561,2562,2563,2564,2565,2566,2567,2568,2569,2570,2571,2572,2573,2574,2084],
|
||||
[2084,2575,2576,2577,2578,2579,2580,2581,2582,2583,2584,1815,1815,1815,1815,2410,2410,2410,2410,2410,2410,1815,2596,2597,2598,2599,2600,2601,2602,2603,2604,2605,2606,2607,2608,2609,2610,2611,2612,2613,2614,2615,2616,2617,2618,2619,2620,2621,2622,2623,2624,2625,2626,2627,2628,2629,2630,2631,2632,2633,2634,2635,2636,2637,2638,2639,2640,2641,2642,2643,2644,2645,2646,2647,2648,2649,2650,2651,2652,2653,2654,2655,2656,2657,2658,2659,2660,2661,2662,2663,2664,2665,2666,2667,2668,2669,2670,2671,2672,2673,2674,2675,2676,2677,2678,2369,2369,2369,2369,2369,2369,2369,2369,2687,2688,2689,2690,2691,2692,2693,2694,2695,2696,2697,2698,2699,2700,2701,2702,2703,2704,2705,2706,2707,2708,1562,1562,1562,1562,1562,1562,1562,1562,1562,2718,2719,2720,2721,2722,2723,2724,2725,2726,2727,2728,2729,2730,2731,2732,2733,1933,2735,2736,2737,2738,2739,2740,2741,2742,2743,2744,2745,2746,2747,2748,2749,2750,2751,2752,2753,2754,2755,2756,1933,2758,2759,2760,2761,2762,2763,2764,2765,2766,2767,2768,2769,2770,2771,2772,2084],
|
||||
[2084,2773,2774,2775,2776,2777,2778,2779,2780,2781,2782,2783,2784,2785,2786,2787,2788,2789,2790,2791,2792,2793,2794,2795,2796,2797,2798,2799,2800,2801,2802,2803,2804,2805,2806,2807,2808,2809,2810,2811,2812,2813,2814,2815,2816,2817,2818,2819,2820,2821,2822,2823,2824,2825,2826,2827,2828,2829,2830,2831,2832,2833,2834,2835,2836,2837,2838,2839,2840,2841,1562,1562,1562,1562,1562,2847,2848,2849,2850,2851,2852,2853,2854,2855,1562,1562,1562,1562,1562,2861,2862,2863,2864,2865,2866,2867,2868,2869,2870,2871,2872,2873,2874,2875,2876,2877,2878,2879,2880,2881,2882,2883,2884,2885,2886,2887,2888,2889,2890,2891,2892,2893,2894,2895,2896,2897,2898,2899,2900,2901,2902,2903,2904,2905,2906,2907,2908,2909,2910,2911,2912,2913,2914,2915,2916,2917,2918,2919,2920,2921,2922,2923,2924,2925,2926,2927,2928,2929,2930,1933,1933,2933,2934,2935,2936,2937,2938,2939,2940,2941,2942,2943,2944,2945,2946,2947,2948,2949,2950,2951,2952,2953,2954,1933,1933,2957,2958,2959,2960,2961,2962,2963,2964,2965,2966,2967,2968,2969,2970,2084],
|
||||
[2084,2971,2972,2973,2974,2975,2976,2977,2978,2979,2980,2981,2982,2983,2984,2985,2986,2987,2988,2989,2990,2991,2992,2993,2994,2995,2996,2997,2998,2999,3000,3001,3002,3003,3004,982,982,982,982,982,982,982,982,982,982,2026,3016,3017,3018,3019,3020,982,982,982,982,982,982,982,982,982,982,3031,3032,3033,3034,3035,3036,3037,3038,3039,3040,3041,3042,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3053,3054,3055,3056,3057,3058,3059,3060,3061,3062,3063,3064,3065,3066,3067,3068,3069,3070,3071,3072,3073,3074,3075,3076,3077,3078,3079,3080,3081,3082,3083,3084,3085,3086,3087,3088,3089,3090,3091,3092,3093,3094,3095,3096,3097,3098,3099,3100,3101,3102,3103,3104,3105,3106,3107,3108,3109,3110,3111,3112,3113,3114,3115,3116,3117,3118,3119,3120,3121,3122,3123,3124,3125,3126,3127,1933,1933,1933,3131,3132,3133,3134,3135,3136,3137,3138,3139,3140,3141,3142,3143,3144,3145,3146,3147,3148,3149,3150,3151,3152,1933,1933,1933,3156,3157,3158,3159,3160,3161,3162,3163,3164,3165,3166,3167,3168,2084],
|
||||
[2084,3169,3170,3171,3172,3173,3174,3175,3176,3177,3178,3179,3180,3181,3182,3183,3184,3185,3186,3187,3188,3189,3190,3191,3192,3193,3194,3195,3196,3197,3198,3199,3200,3201,3202,982,982,982,982,982,982,982,982,982,982,2026,3214,3215,3216,3217,3218,982,982,982,982,982,982,982,982,982,982,3229,3230,3231,3232,3233,3234,3235,3236,3237,3238,3239,3240,3241,3242,3243,3244,3245,3246,3247,3248,3249,3250,3251,3252,3253,3254,3255,3256,3257,3258,3259,3260,3261,3262,3263,3264,3265,3266,3267,3268,3269,3270,3271,3272,3273,3274,3275,3276,3277,3278,3279,3280,3281,3282,3283,3284,3285,3286,3287,3288,3289,3290,3291,3292,3293,3294,3295,3296,3297,3298,3299,3300,3301,3302,3303,3304,3305,3306,3307,3308,3309,3310,3311,3312,3313,3314,3315,3316,3317,3318,3319,3320,3321,3322,3323,3324,1933,1933,1933,1933,3329,3330,3331,3332,3333,3334,3335,3336,3337,3338,3339,3340,3341,3342,3343,3344,3345,3346,3347,3348,3349,3350,1933,1933,1933,1933,3355,3356,3357,3358,3359,3360,3361,3362,3363,3364,3365,3366,2084],
|
||||
[2084,3367,3368,3369,3370,3371,3372,3373,3374,3375,3376,3377,3378,3379,3380,3381,3382,3383,3384,3385,3386,3387,3388,3389,3390,3391,3392,3393,3394,3395,3396,3397,3398,3399,3400,982,982,982,982,982,982,982,982,982,982,2026,3412,3413,3414,3415,3416,982,982,982,982,982,982,982,982,982,982,3427,3428,3429,3430,3431,3432,3433,3434,3435,3436,3437,3438,3439,3440,3441,3442,3443,3444,3445,3446,3447,3448,3449,3450,3451,3452,3453,3454,3455,3456,3457,3458,3459,3460,3461,3462,3463,3464,3465,3466,3467,3468,3469,3470,3471,3472,3473,3474,3475,3476,3477,3478,3479,3480,3481,3482,3483,3484,3485,3486,3487,3488,3489,3490,3491,3492,3493,3494,3495,3496,3497,3498,3499,3500,3501,3502,3503,3504,3505,3506,3507,3508,3509,3510,3511,3512,3513,3514,3515,3516,3517,3518,3519,3520,3521,1933,1933,1933,1933,1933,3527,3528,3529,3530,3531,3532,3533,3534,3535,3536,3537,3538,3539,3540,3541,3542,3543,3544,3545,3546,3547,3548,1933,1933,1933,1933,1970,3554,3555,3556,3557,3558,3559,3560,3561,3562,3563,3564,2084],
|
||||
[2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2,2,2,2,2,2,2,2,2,2,2,2,2,1831,1831,1831,1831,1831,1831,2,2,2,2,2,2,2,2,2,2,2,2,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,982,982,982,982,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084,2084]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "collision",
|
||||
"width": 200,
|
||||
"height": 20,
|
||||
"linkWithCollision": false,
|
||||
"visible": 0,
|
||||
"tilesetName": "",
|
||||
"repeat": false,
|
||||
"preRender": false,
|
||||
"distance": 1,
|
||||
"tilesize": 32,
|
||||
"foreground": false,
|
||||
"data": [
|
||||
[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,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,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,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,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,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,1,1,1,1,1,1,1,1],
|
||||
[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,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,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,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,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,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
|
||||
[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,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,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,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,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,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
|
||||
[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,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,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,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,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,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
|
||||
[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,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,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,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,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,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
|
||||
[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,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,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,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,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,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
|
||||
[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,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,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,1,1,1,1,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,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,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,0,0,0,0,0,0,0,0,0,0,0,0,1],
|
||||
[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,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,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,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,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,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
|
||||
[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,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,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,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,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,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
|
||||
[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,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,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,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,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,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
|
||||
[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,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,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,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,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,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,0,0,0,0,0,0,1],
|
||||
[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,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,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,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,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,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
|
||||
[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,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,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,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,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,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],
|
||||
[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,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,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,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,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,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],
|
||||
[1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,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,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
|
||||
[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,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,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,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,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,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
|
||||
[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,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,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,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,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,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
|
||||
[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,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,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,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,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,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1],
|
||||
[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,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,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,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,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,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,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,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,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,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,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,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,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
|
||||
]
|
||||
}
|
||||
]
|
||||
}/*]JSON*/;
|
||||
LevelLevel2Resources=[new ig.Image('media/level1.png')];
|
||||
});
|
||||
@@ -0,0 +1,40 @@
|
||||
ig.module( 'game.levels.title' )
|
||||
.requires( 'impact.image' )
|
||||
.defines(function(){
|
||||
LevelTitle=/*JSON[*/{
|
||||
"entities": [],
|
||||
"layer": [
|
||||
{
|
||||
"name": "title",
|
||||
"width": 20,
|
||||
"height": 15,
|
||||
"linkWithCollision": false,
|
||||
"visible": 1,
|
||||
"tilesetName": "media/Menu.png",
|
||||
"repeat": false,
|
||||
"preRender": false,
|
||||
"distance": "1",
|
||||
"tilesize": 32,
|
||||
"foreground": false,
|
||||
"data": [
|
||||
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20],
|
||||
[21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40],
|
||||
[41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60],
|
||||
[61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80],
|
||||
[81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100],
|
||||
[101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120],
|
||||
[121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140],
|
||||
[141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160],
|
||||
[161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180],
|
||||
[181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200],
|
||||
[201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220],
|
||||
[221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240],
|
||||
[241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260],
|
||||
[261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280],
|
||||
[281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300]
|
||||
]
|
||||
}
|
||||
]
|
||||
}/*]JSON*/;
|
||||
LevelTitleResources=[new ig.Image('media/Menu.png')];
|
||||
});
|
||||
@@ -0,0 +1,189 @@
|
||||
ig.module(
|
||||
'game.main'
|
||||
)
|
||||
.requires(
|
||||
'impact.game',
|
||||
'impact.font',
|
||||
|
||||
'game.entities.kuroneko',
|
||||
'game.entities.cheese',
|
||||
'game.entities.mouse',
|
||||
'game.entities.nextlevel',
|
||||
'game.entities.endgame',
|
||||
'game.entities.easteregg',
|
||||
|
||||
'game.levels.title',
|
||||
'game.levels.level1',
|
||||
'game.levels.level2',
|
||||
'game.levels.gameover',
|
||||
'game.levels.goodend',
|
||||
'game.levels.badend',
|
||||
|
||||
'impact.debug.debug',
|
||||
)
|
||||
.defines(function(){
|
||||
|
||||
MyGame = ig.Game.extend({
|
||||
|
||||
gravity: 200,
|
||||
player: null,
|
||||
score: 0,
|
||||
checkpoint: null,
|
||||
|
||||
|
||||
init: function() {
|
||||
this.loadLevel( LevelTitle );
|
||||
|
||||
ig.input.bind(ig.KEY.RIGHT_ARROW, 'right');
|
||||
ig.input.bind(ig.KEY.LEFT_ARROW, 'left');
|
||||
ig.input.bind(ig.KEY.UP_ARROW, 'up');
|
||||
ig.input.bind(ig.KEY.SPACE, 'space');
|
||||
|
||||
},
|
||||
|
||||
update: function() {
|
||||
// Update all entities and backgroundMaps
|
||||
this.parent();
|
||||
|
||||
this.player = this.getEntitiesByType(EntityKuroneko)[0];
|
||||
if (this.player) {
|
||||
this.scrollScreen();
|
||||
}
|
||||
|
||||
|
||||
if (this.currentLevel == LevelTitle) {
|
||||
//play title music
|
||||
if (ig.input.pressed('space')) {
|
||||
this.loadLevel( LevelLevel1 );
|
||||
}
|
||||
}
|
||||
|
||||
if (this.currentLevel == LevelLevel1) {
|
||||
//play game music
|
||||
this.checkpoint = LevelLevel1;
|
||||
}
|
||||
|
||||
if (this.currentLevel == LevelLevel2) {
|
||||
//play game music
|
||||
this.checkpoint = LevelLevel2;
|
||||
}
|
||||
|
||||
if (this.currentLevel == LevelGameover) {
|
||||
//play some sad music
|
||||
if (ig.input.pressed('space')) {
|
||||
this.loadLevel( this.checkpoint );
|
||||
}
|
||||
}
|
||||
|
||||
if (this.currentLevel == LevelBadend || this.currentLevel == LevelGoodend) {
|
||||
//play ending music
|
||||
if (ig.input.pressed('space')) {
|
||||
this.loadLevel( LevelTitle );
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
loadLevel: function(data) {
|
||||
this.parent(data);
|
||||
|
||||
this.currentLevel = data;
|
||||
},
|
||||
|
||||
scrollScreen: function() {
|
||||
//Camera code
|
||||
if(this.player.pos.x > (ig.game.collisionMap.width*ig.game.collisionMap.tilesize-ig.system.width/2))
|
||||
{
|
||||
this.screen.x = ig.game.collisionMap.width*ig.game.collisionMap.tilesize-ig.system.width;
|
||||
}
|
||||
else if (this.player.pos.x < ig.system.width/2)
|
||||
{
|
||||
this.screen.x = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.screen.x = this.player.pos.x - ig.system.width/2;
|
||||
}
|
||||
|
||||
if(this.player.pos.y > (ig.game.collisionMap.height*ig.game.collisionMap.tilesize-ig.system.height/2))
|
||||
{
|
||||
this.screen.y = ig.game.collisionMap.height*ig.game.collisionMap.tilesize-ig.system.height;
|
||||
}
|
||||
else if (this.player.pos.y < ig.system.height/2)
|
||||
{
|
||||
this.screen.y = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.screen.y = this.player.pos.y - ig.system.height/2;
|
||||
}
|
||||
},
|
||||
|
||||
draw: function() {
|
||||
// Draw all entities and backgroundMaps
|
||||
this.parent();
|
||||
|
||||
this.player = this.getEntitiesByType(EntityKuroneko)[0];
|
||||
|
||||
var canvas = document.getElementById('canvas');
|
||||
var ctx = canvas.getContext('2d');
|
||||
ctx.font = '30px Ariel'
|
||||
|
||||
|
||||
if (this.currentLevel == LevelLevel1 || this.currentLevel == LevelLevel2) {
|
||||
if (this.player) {
|
||||
if (this.player.health == 4) {
|
||||
ctx.beginPath();
|
||||
ctx.lineWidth = "6";
|
||||
ctx.strokeStyle = "#808080";
|
||||
ctx.rect(60, 30, 96, 16);
|
||||
ctx.stroke();
|
||||
ctx.fillStyle = '#ac3232';
|
||||
ctx.fillRect(63, 33, 90, 10);
|
||||
}
|
||||
else if (this.player.health == 3) {
|
||||
ctx.beginPath();
|
||||
ctx.lineWidth = "6";
|
||||
ctx.strokeStyle = "#808080";
|
||||
ctx.rect(60, 30, 96, 16);
|
||||
ctx.stroke();
|
||||
ctx.fillStyle = '#ac3232';
|
||||
ctx.fillRect(63, 33, 67.5, 10);
|
||||
}
|
||||
else if (this.player.health == 2) {
|
||||
ctx.beginPath();
|
||||
ctx.lineWidth = "6";
|
||||
ctx.strokeStyle = "#808080";
|
||||
ctx.rect(60, 30, 96, 16);
|
||||
ctx.stroke();
|
||||
ctx.fillStyle = '#ac3232';
|
||||
ctx.fillRect(63, 33, 45, 10);
|
||||
}
|
||||
else if (this.player.health == 1) {
|
||||
ctx.beginPath();
|
||||
ctx.lineWidth = "6";
|
||||
ctx.strokeStyle = "#808080";
|
||||
ctx.rect(60, 30, 96, 16);
|
||||
ctx.stroke();
|
||||
ctx.fillStyle = '#ac3232';
|
||||
ctx.fillRect(63, 33, 22.5, 10);
|
||||
}
|
||||
|
||||
ctx.fillText(`Score: ${this.score}`, 750, 45);
|
||||
}
|
||||
ctx.beginPath();
|
||||
ctx.lineWidth = "6";
|
||||
ctx.strokeStyle = "#808080";
|
||||
ctx.rect(60, 30, 96, 16);
|
||||
ctx.stroke();
|
||||
ctx.fillStyle = '#ac3232';
|
||||
ctx.fillRect(63, 33, 0, 10);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Start the Game with 60fps, a resolution of 640x480, scaled
|
||||
// up by a factor of 1.5
|
||||
ig.main( '#canvas', MyGame, 60, 640, 480, 1.5 );
|
||||
|
||||
});
|
||||
@@ -0,0 +1,130 @@
|
||||
ig.module(
|
||||
'impact.animation'
|
||||
)
|
||||
.requires(
|
||||
'impact.timer',
|
||||
'impact.image'
|
||||
)
|
||||
.defines(function(){ "use strict";
|
||||
|
||||
ig.AnimationSheet = ig.Class.extend({
|
||||
width: 8,
|
||||
height: 8,
|
||||
image: null,
|
||||
|
||||
init: function( path, width, height ) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
this.image = new ig.Image( path );
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
ig.Animation = ig.Class.extend({
|
||||
sheet: null,
|
||||
timer: null,
|
||||
|
||||
sequence: [],
|
||||
flip: {x: false, y: false},
|
||||
pivot: {x: 0, y: 0},
|
||||
|
||||
frame: 0,
|
||||
tile: 0,
|
||||
loopCount: 0,
|
||||
alpha: 1,
|
||||
angle: 0,
|
||||
|
||||
|
||||
init: function( sheet, frameTime, sequence, stop ) {
|
||||
this.sheet = sheet;
|
||||
this.pivot = {x: sheet.width/2, y: sheet.height/2 };
|
||||
this.timer = new ig.Timer();
|
||||
|
||||
this.frameTime = frameTime;
|
||||
this.sequence = sequence;
|
||||
this.stop = !!stop;
|
||||
this.tile = this.sequence[0];
|
||||
},
|
||||
|
||||
|
||||
rewind: function() {
|
||||
this.timer.set();
|
||||
this.loopCount = 0;
|
||||
this.frame = 0;
|
||||
this.tile = this.sequence[0];
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
gotoFrame: function( f ) {
|
||||
// Offset the timer by one tenth of a millisecond to make sure we
|
||||
// jump to the correct frame and circumvent rounding errors
|
||||
this.timer.set( this.frameTime * -f - 0.0001 );
|
||||
this.update();
|
||||
},
|
||||
|
||||
|
||||
gotoRandomFrame: function() {
|
||||
this.gotoFrame( Math.floor(Math.random() * this.sequence.length) )
|
||||
},
|
||||
|
||||
|
||||
update: function() {
|
||||
var frameTotal = Math.floor(this.timer.delta() / this.frameTime);
|
||||
this.loopCount = Math.floor(frameTotal / this.sequence.length);
|
||||
if( this.stop && this.loopCount > 0 ) {
|
||||
this.frame = this.sequence.length - 1;
|
||||
}
|
||||
else {
|
||||
this.frame = frameTotal % this.sequence.length;
|
||||
}
|
||||
this.tile = this.sequence[ this.frame ];
|
||||
},
|
||||
|
||||
|
||||
draw: function( targetX, targetY ) {
|
||||
var bbsize = Math.max(this.sheet.width, this.sheet.height);
|
||||
|
||||
// On screen?
|
||||
if(
|
||||
targetX > ig.system.width || targetY > ig.system.height ||
|
||||
targetX + bbsize < 0 || targetY + bbsize < 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if( this.alpha != 1) {
|
||||
ig.system.context.globalAlpha = this.alpha;
|
||||
}
|
||||
|
||||
if( this.angle == 0 ) {
|
||||
this.sheet.image.drawTile(
|
||||
targetX, targetY,
|
||||
this.tile, this.sheet.width, this.sheet.height,
|
||||
this.flip.x, this.flip.y
|
||||
);
|
||||
}
|
||||
else {
|
||||
ig.system.context.save();
|
||||
ig.system.context.translate(
|
||||
ig.system.getDrawPos(targetX + this.pivot.x),
|
||||
ig.system.getDrawPos(targetY + this.pivot.y)
|
||||
);
|
||||
ig.system.context.rotate( this.angle );
|
||||
this.sheet.image.drawTile(
|
||||
-this.pivot.x, -this.pivot.y,
|
||||
this.tile, this.sheet.width, this.sheet.height,
|
||||
this.flip.x, this.flip.y
|
||||
);
|
||||
ig.system.context.restore();
|
||||
}
|
||||
|
||||
if( this.alpha != 1) {
|
||||
ig.system.context.globalAlpha = 1;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,249 @@
|
||||
ig.module(
|
||||
'impact.background-map'
|
||||
)
|
||||
.requires(
|
||||
'impact.map',
|
||||
'impact.image'
|
||||
)
|
||||
.defines(function(){ "use strict";
|
||||
|
||||
ig.BackgroundMap = ig.Map.extend({
|
||||
tiles: null,
|
||||
scroll: {x: 0, y:0},
|
||||
distance: 1,
|
||||
repeat: false,
|
||||
tilesetName: '',
|
||||
foreground: false,
|
||||
enabled: true,
|
||||
|
||||
preRender: false,
|
||||
preRenderedChunks: null,
|
||||
chunkSize: 512,
|
||||
debugChunks: false,
|
||||
|
||||
|
||||
anims: {},
|
||||
|
||||
|
||||
init: function( tilesize, data, tileset ) {
|
||||
this.parent( tilesize, data );
|
||||
this.setTileset( tileset );
|
||||
},
|
||||
|
||||
|
||||
setTileset: function( tileset ) {
|
||||
this.tilesetName = tileset instanceof ig.Image ? tileset.path : tileset;
|
||||
this.tiles = new ig.Image( this.tilesetName );
|
||||
this.preRenderedChunks = null;
|
||||
},
|
||||
|
||||
|
||||
setScreenPos: function( x, y ) {
|
||||
this.scroll.x = x / this.distance;
|
||||
this.scroll.y = y / this.distance;
|
||||
},
|
||||
|
||||
|
||||
preRenderMapToChunks: function() {
|
||||
var totalWidth = this.width * this.tilesize * ig.system.scale,
|
||||
totalHeight = this.height * this.tilesize * ig.system.scale;
|
||||
|
||||
// If this layer is smaller than the chunkSize, adjust the chunkSize
|
||||
// accordingly, so we don't have as much overdraw
|
||||
this.chunkSize = Math.min( Math.max(totalWidth, totalHeight), this.chunkSize );
|
||||
|
||||
var chunkCols = Math.ceil(totalWidth / this.chunkSize),
|
||||
chunkRows = Math.ceil(totalHeight / this.chunkSize);
|
||||
|
||||
this.preRenderedChunks = [];
|
||||
for( var y = 0; y < chunkRows; y++ ) {
|
||||
this.preRenderedChunks[y] = [];
|
||||
|
||||
for( var x = 0; x < chunkCols; x++ ) {
|
||||
|
||||
|
||||
var chunkWidth = (x == chunkCols-1)
|
||||
? totalWidth - x * this.chunkSize
|
||||
: this.chunkSize;
|
||||
|
||||
var chunkHeight = (y == chunkRows-1)
|
||||
? totalHeight - y * this.chunkSize
|
||||
: this.chunkSize;
|
||||
|
||||
this.preRenderedChunks[y][x] = this.preRenderChunk( x, y, chunkWidth, chunkHeight );
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
preRenderChunk: function( cx, cy, w, h ) {
|
||||
var tw = w / this.tilesize / ig.system.scale + 1,
|
||||
th = h / this.tilesize / ig.system.scale + 1;
|
||||
|
||||
var nx = (cx * this.chunkSize / ig.system.scale) % this.tilesize,
|
||||
ny = (cy * this.chunkSize / ig.system.scale) % this.tilesize;
|
||||
|
||||
var tx = Math.floor(cx * this.chunkSize / this.tilesize / ig.system.scale),
|
||||
ty = Math.floor(cy * this.chunkSize / this.tilesize / ig.system.scale);
|
||||
|
||||
|
||||
var chunk = ig.$new('canvas');
|
||||
chunk.width = w;
|
||||
chunk.height = h;
|
||||
chunk.retinaResolutionEnabled = false; // Opt out for Ejecta
|
||||
|
||||
var chunkContext = chunk.getContext('2d');
|
||||
ig.System.scaleMode(chunk, chunkContext);
|
||||
|
||||
var screenContext = ig.system.context;
|
||||
ig.system.context = chunkContext;
|
||||
|
||||
for( var x = 0; x < tw; x++ ) {
|
||||
for( var y = 0; y < th; y++ ) {
|
||||
if( x + tx < this.width && y + ty < this.height ) {
|
||||
var tile = this.data[y+ty][x+tx];
|
||||
if( tile ) {
|
||||
this.tiles.drawTile(
|
||||
x * this.tilesize - nx, y * this.tilesize - ny,
|
||||
tile - 1, this.tilesize
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ig.system.context = screenContext;
|
||||
|
||||
return chunk;
|
||||
},
|
||||
|
||||
|
||||
draw: function() {
|
||||
if( !this.tiles.loaded || !this.enabled ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if( this.preRender ) {
|
||||
this.drawPreRendered();
|
||||
}
|
||||
else {
|
||||
this.drawTiled();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
drawPreRendered: function() {
|
||||
if( !this.preRenderedChunks ) {
|
||||
this.preRenderMapToChunks();
|
||||
}
|
||||
|
||||
var dx = ig.system.getDrawPos(this.scroll.x),
|
||||
dy = ig.system.getDrawPos(this.scroll.y);
|
||||
|
||||
|
||||
if( this.repeat ) {
|
||||
var w = this.width * this.tilesize * ig.system.scale;
|
||||
dx = (dx%w + w) % w;
|
||||
|
||||
var h = this.height * this.tilesize * ig.system.scale;
|
||||
dy = (dy%h + h) % h;
|
||||
}
|
||||
|
||||
var minChunkX = Math.max( Math.floor(dx / this.chunkSize), 0 ),
|
||||
minChunkY = Math.max( Math.floor(dy / this.chunkSize), 0 ),
|
||||
maxChunkX = Math.ceil((dx+ig.system.realWidth) / this.chunkSize),
|
||||
maxChunkY = Math.ceil((dy+ig.system.realHeight) / this.chunkSize),
|
||||
maxRealChunkX = this.preRenderedChunks[0].length,
|
||||
maxRealChunkY = this.preRenderedChunks.length;
|
||||
|
||||
|
||||
if( !this.repeat ) {
|
||||
maxChunkX = Math.min( maxChunkX, maxRealChunkX );
|
||||
maxChunkY = Math.min( maxChunkY, maxRealChunkY );
|
||||
}
|
||||
|
||||
|
||||
var nudgeY = 0;
|
||||
for( var cy = minChunkY; cy < maxChunkY; cy++ ) {
|
||||
|
||||
var nudgeX = 0;
|
||||
for( var cx = minChunkX; cx < maxChunkX; cx++ ) {
|
||||
var chunk = this.preRenderedChunks[cy % maxRealChunkY][cx % maxRealChunkX];
|
||||
|
||||
var x = -dx + cx * this.chunkSize - nudgeX;
|
||||
var y = -dy + cy * this.chunkSize - nudgeY;
|
||||
ig.system.context.drawImage( chunk, x, y);
|
||||
ig.Image.drawCount++;
|
||||
|
||||
if( this.debugChunks ) {
|
||||
ig.system.context.strokeStyle = '#f0f';
|
||||
ig.system.context.strokeRect( x, y, this.chunkSize, this.chunkSize );
|
||||
}
|
||||
|
||||
// If we repeat in X and this chunk's width wasn't the full chunk size
|
||||
// and the screen is not already filled, we need to draw anohter chunk
|
||||
// AND nudge it to be flush with the last chunk
|
||||
if( this.repeat && chunk.width < this.chunkSize && x + chunk.width < ig.system.realWidth ) {
|
||||
nudgeX += this.chunkSize - chunk.width;
|
||||
maxChunkX++;
|
||||
}
|
||||
}
|
||||
|
||||
// Same as above, but for Y
|
||||
if( this.repeat && chunk.height < this.chunkSize && y + chunk.height < ig.system.realHeight ) {
|
||||
nudgeY += this.chunkSize - chunk.height;
|
||||
maxChunkY++;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
drawTiled: function() {
|
||||
var tile = 0,
|
||||
anim = null,
|
||||
tileOffsetX = (this.scroll.x / this.tilesize).toInt(),
|
||||
tileOffsetY = (this.scroll.y / this.tilesize).toInt(),
|
||||
pxOffsetX = this.scroll.x % this.tilesize,
|
||||
pxOffsetY = this.scroll.y % this.tilesize,
|
||||
pxMinX = -pxOffsetX - this.tilesize,
|
||||
pxMinY = -pxOffsetY - this.tilesize,
|
||||
pxMaxX = ig.system.width + this.tilesize - pxOffsetX,
|
||||
pxMaxY = ig.system.height + this.tilesize - pxOffsetY;
|
||||
|
||||
|
||||
// FIXME: could be sped up for non-repeated maps: restrict the for loops
|
||||
// to the map size instead of to the screen size and skip the 'repeat'
|
||||
// checks inside the loop.
|
||||
|
||||
for( var mapY = -1, pxY = pxMinY; pxY < pxMaxY; mapY++, pxY += this.tilesize) {
|
||||
var tileY = mapY + tileOffsetY;
|
||||
|
||||
// Repeat Y?
|
||||
if( tileY >= this.height || tileY < 0 ) {
|
||||
if( !this.repeat ) { continue; }
|
||||
tileY = (tileY%this.height + this.height) % this.height;
|
||||
}
|
||||
|
||||
for( var mapX = -1, pxX = pxMinX; pxX < pxMaxX; mapX++, pxX += this.tilesize ) {
|
||||
var tileX = mapX + tileOffsetX;
|
||||
|
||||
// Repeat X?
|
||||
if( tileX >= this.width || tileX < 0 ) {
|
||||
if( !this.repeat ) { continue; }
|
||||
tileX = (tileX%this.width + this.width) % this.width;
|
||||
}
|
||||
|
||||
// Draw!
|
||||
if( (tile = this.data[tileY][tileX]) ) {
|
||||
if( (anim = this.anims[tile-1]) ) {
|
||||
anim.draw( pxX, pxY );
|
||||
}
|
||||
else {
|
||||
this.tiles.drawTile( pxX, pxY, tile-1, this.tilesize );
|
||||
}
|
||||
}
|
||||
} // end for x
|
||||
} // end for y
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,274 @@
|
||||
ig.module(
|
||||
'impact.collision-map'
|
||||
)
|
||||
.requires(
|
||||
'impact.map'
|
||||
)
|
||||
.defines(function(){ "use strict";
|
||||
|
||||
ig.CollisionMap = ig.Map.extend({
|
||||
|
||||
lastSlope: 1,
|
||||
tiledef: null,
|
||||
|
||||
init: function( tilesize, data, tiledef ) {
|
||||
this.parent( tilesize, data );
|
||||
this.tiledef = tiledef || ig.CollisionMap.defaultTileDef;
|
||||
|
||||
for( var t in this.tiledef ) {
|
||||
if( t|0 > this.lastSlope ) {
|
||||
this.lastSlope = t|0;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
trace: function( x, y, vx, vy, objectWidth, objectHeight ) {
|
||||
// Set up the trace-result
|
||||
var res = {
|
||||
collision: {x: false, y: false, slope: false},
|
||||
pos: {x: x, y: y},
|
||||
tile: {x: 0, y: 0}
|
||||
};
|
||||
|
||||
// Break the trace down into smaller steps if necessary
|
||||
var steps = Math.ceil(Math.max(Math.abs(vx), Math.abs(vy)) / this.tilesize);
|
||||
if( steps > 1 ) {
|
||||
var sx = vx / steps;
|
||||
var sy = vy / steps;
|
||||
|
||||
for( var i = 0; i < steps && (sx || sy); i++ ) {
|
||||
this._traceStep( res, x, y, sx, sy, objectWidth, objectHeight, vx, vy, i );
|
||||
|
||||
x = res.pos.x;
|
||||
y = res.pos.y;
|
||||
if( res.collision.x ) { sx = 0; vx = 0; }
|
||||
if( res.collision.y ) { sy = 0; vy = 0; }
|
||||
if( res.collision.slope ) { break; }
|
||||
}
|
||||
}
|
||||
|
||||
// Just one step
|
||||
else {
|
||||
this._traceStep( res, x, y, vx, vy, objectWidth, objectHeight, vx, vy, 0 );
|
||||
}
|
||||
|
||||
return res;
|
||||
},
|
||||
|
||||
|
||||
_traceStep: function( res, x, y, vx, vy, width, height, rvx, rvy, step ) {
|
||||
|
||||
res.pos.x += vx;
|
||||
res.pos.y += vy;
|
||||
|
||||
var t = 0;
|
||||
|
||||
// Horizontal collision (walls)
|
||||
if( vx ) {
|
||||
var pxOffsetX = (vx > 0 ? width : 0);
|
||||
var tileOffsetX = (vx < 0 ? this.tilesize : 0);
|
||||
|
||||
var firstTileY = Math.max( Math.floor(y / this.tilesize), 0 );
|
||||
var lastTileY = Math.min( Math.ceil((y + height) / this.tilesize), this.height );
|
||||
var tileX = Math.floor( (res.pos.x + pxOffsetX) / this.tilesize );
|
||||
|
||||
// We need to test the new tile position as well as the current one, as we
|
||||
// could still collide with the current tile if it's a line def.
|
||||
// We can skip this test if this is not the first step or the new tile position
|
||||
// is the same as the current one.
|
||||
var prevTileX = Math.floor( (x + pxOffsetX) / this.tilesize );
|
||||
if( step > 0 || tileX == prevTileX || prevTileX < 0 || prevTileX >= this.width ) {
|
||||
prevTileX = -1;
|
||||
}
|
||||
|
||||
// Still inside this collision map?
|
||||
if( tileX >= 0 && tileX < this.width ) {
|
||||
for( var tileY = firstTileY; tileY < lastTileY; tileY++ ) {
|
||||
if( prevTileX != -1 ) {
|
||||
t = this.data[tileY][prevTileX];
|
||||
if(
|
||||
t > 1 && t <= this.lastSlope &&
|
||||
this._checkTileDef(res, t, x, y, rvx, rvy, width, height, prevTileX, tileY)
|
||||
) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
t = this.data[tileY][tileX];
|
||||
if(
|
||||
t == 1 || t > this.lastSlope || // fully solid tile?
|
||||
(t > 1 && this._checkTileDef(res, t, x, y, rvx, rvy, width, height, tileX, tileY)) // slope?
|
||||
) {
|
||||
if( t > 1 && t <= this.lastSlope && res.collision.slope ) {
|
||||
break;
|
||||
}
|
||||
|
||||
// full tile collision!
|
||||
res.collision.x = true;
|
||||
res.tile.x = t;
|
||||
x = res.pos.x = tileX * this.tilesize - pxOffsetX + tileOffsetX;
|
||||
rvx = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Vertical collision (floor, ceiling)
|
||||
if( vy ) {
|
||||
var pxOffsetY = (vy > 0 ? height : 0);
|
||||
var tileOffsetY = (vy < 0 ? this.tilesize : 0);
|
||||
|
||||
var firstTileX = Math.max( Math.floor(res.pos.x / this.tilesize), 0 );
|
||||
var lastTileX = Math.min( Math.ceil((res.pos.x + width) / this.tilesize), this.width );
|
||||
var tileY = Math.floor( (res.pos.y + pxOffsetY) / this.tilesize );
|
||||
|
||||
var prevTileY = Math.floor( (y + pxOffsetY) / this.tilesize );
|
||||
if( step > 0 || tileY == prevTileY || prevTileY < 0 || prevTileY >= this.height ) {
|
||||
prevTileY = -1;
|
||||
}
|
||||
|
||||
// Still inside this collision map?
|
||||
if( tileY >= 0 && tileY < this.height ) {
|
||||
for( var tileX = firstTileX; tileX < lastTileX; tileX++ ) {
|
||||
if( prevTileY != -1 ) {
|
||||
t = this.data[prevTileY][tileX];
|
||||
if(
|
||||
t > 1 && t <= this.lastSlope &&
|
||||
this._checkTileDef(res, t, x, y, rvx, rvy, width, height, tileX, prevTileY) ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
t = this.data[tileY][tileX];
|
||||
if(
|
||||
t == 1 || t > this.lastSlope || // fully solid tile?
|
||||
(t > 1 && this._checkTileDef(res, t, x, y, rvx, rvy, width, height, tileX, tileY)) // slope?
|
||||
) {
|
||||
if( t > 1 && t <= this.lastSlope && res.collision.slope ) {
|
||||
break;
|
||||
}
|
||||
|
||||
// full tile collision!
|
||||
res.collision.y = true;
|
||||
res.tile.y = t;
|
||||
res.pos.y = tileY * this.tilesize - pxOffsetY + tileOffsetY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// res is changed in place, nothing to return
|
||||
},
|
||||
|
||||
|
||||
_checkTileDef: function( res, t, x, y, vx, vy, width, height, tileX, tileY ) {
|
||||
var def = this.tiledef[t];
|
||||
if( !def ) { return false; }
|
||||
|
||||
var lx = (tileX + def[0]) * this.tilesize,
|
||||
ly = (tileY + def[1]) * this.tilesize,
|
||||
lvx = (def[2] - def[0]) * this.tilesize,
|
||||
lvy = (def[3] - def[1]) * this.tilesize,
|
||||
solid = def[4];
|
||||
|
||||
// Find the box corner to test, relative to the line
|
||||
var tx = x + vx + (lvy < 0 ? width : 0) - lx,
|
||||
ty = y + vy + (lvx > 0 ? height : 0) - ly;
|
||||
|
||||
// Is the box corner behind the line?
|
||||
if( lvx * ty - lvy * tx > 0 ) {
|
||||
|
||||
// Lines are only solid from one side - find the dot product of
|
||||
// line normal and movement vector and dismiss if wrong side
|
||||
if( vx * -lvy + vy * lvx < 0 ) {
|
||||
return solid;
|
||||
}
|
||||
|
||||
// Find the line normal
|
||||
var length = Math.sqrt(lvx * lvx + lvy * lvy);
|
||||
var nx = lvy/length,
|
||||
ny = -lvx/length;
|
||||
|
||||
// Project out of the line
|
||||
var proj = tx * nx + ty * ny;
|
||||
var px = nx * proj,
|
||||
py = ny * proj;
|
||||
|
||||
// If we project further out than we moved in, then this is a full
|
||||
// tile collision for solid tiles.
|
||||
// For non-solid tiles, make sure we were in front of the line.
|
||||
if( px*px+py*py >= vx*vx+vy*vy ) {
|
||||
return solid || (lvx * (ty-vy) - lvy * (tx-vx) < 0.5);
|
||||
}
|
||||
|
||||
res.pos.x = x + vx - px;
|
||||
res.pos.y = y + vy - py;
|
||||
res.collision.slope = {x: lvx, y: lvy, nx: nx, ny: ny};
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Default Slope Tile definition. Each tile is defined by an array of 5 vars:
|
||||
// - 4 for the line in tile coordinates (0 -- 1)
|
||||
// - 1 specifing whether the tile is 'filled' behind the line or not
|
||||
// [ x1, y1, x2, y2, solid ]
|
||||
|
||||
// Defining 'half', 'one third' and 'two thirds' as vars makes it a bit
|
||||
// easier to read... I hope.
|
||||
var H = 1/2,
|
||||
N = 1/3,
|
||||
M = 2/3,
|
||||
SOLID = true,
|
||||
NON_SOLID = false;
|
||||
|
||||
ig.CollisionMap.defaultTileDef = {
|
||||
/* 15 NE */ 5: [0,1, 1,M, SOLID], 6: [0,M, 1,N, SOLID], 7: [0,N, 1,0, SOLID],
|
||||
/* 22 NE */ 3: [0,1, 1,H, SOLID], 4: [0,H, 1,0, SOLID],
|
||||
/* 45 NE */ 2: [0,1, 1,0, SOLID],
|
||||
/* 67 NE */ 10: [H,1, 1,0, SOLID], 21: [0,1, H,0, SOLID],
|
||||
/* 75 NE */ 32: [M,1, 1,0, SOLID], 43: [N,1, M,0, SOLID], 54: [0,1, N,0, SOLID],
|
||||
|
||||
/* 15 SE */ 27: [0,0, 1,N, SOLID], 28: [0,N, 1,M, SOLID], 29: [0,M, 1,1, SOLID],
|
||||
/* 22 SE */ 25: [0,0, 1,H, SOLID], 26: [0,H, 1,1, SOLID],
|
||||
/* 45 SE */ 24: [0,0, 1,1, SOLID],
|
||||
/* 67 SE */ 11: [0,0, H,1, SOLID], 22: [H,0, 1,1, SOLID],
|
||||
/* 75 SE */ 33: [0,0, N,1, SOLID], 44: [N,0, M,1, SOLID], 55: [M,0, 1,1, SOLID],
|
||||
|
||||
/* 15 NW */ 16: [1,N, 0,0, SOLID], 17: [1,M, 0,N, SOLID], 18: [1,1, 0,M, SOLID],
|
||||
/* 22 NW */ 14: [1,H, 0,0, SOLID], 15: [1,1, 0,H, SOLID],
|
||||
/* 45 NW */ 13: [1,1, 0,0, SOLID],
|
||||
/* 67 NW */ 8: [H,1, 0,0, SOLID], 19: [1,1, H,0, SOLID],
|
||||
/* 75 NW */ 30: [N,1, 0,0, SOLID], 41: [M,1, N,0, SOLID], 52: [1,1, M,0, SOLID],
|
||||
|
||||
/* 15 SW */ 38: [1,M, 0,1, SOLID], 39: [1,N, 0,M, SOLID], 40: [1,0, 0,N, SOLID],
|
||||
/* 22 SW */ 36: [1,H, 0,1, SOLID], 37: [1,0, 0,H, SOLID],
|
||||
/* 45 SW */ 35: [1,0, 0,1, SOLID],
|
||||
/* 67 SW */ 9: [1,0, H,1, SOLID], 20: [H,0, 0,1, SOLID],
|
||||
/* 75 SW */ 31: [1,0, M,1, SOLID], 42: [M,0, N,1, SOLID], 53: [N,0, 0,1, SOLID],
|
||||
|
||||
/* Go N */ 12: [0,0, 1,0, NON_SOLID],
|
||||
/* Go S */ 23: [1,1, 0,1, NON_SOLID],
|
||||
/* Go E */ 34: [1,0, 1,1, NON_SOLID],
|
||||
/* Go W */ 45: [0,1, 0,0, NON_SOLID]
|
||||
|
||||
// Now that was fun!
|
||||
};
|
||||
|
||||
|
||||
// Static Dummy CollisionMap; never collides
|
||||
ig.CollisionMap.staticNoCollision = { trace: function( x, y, vx, vy ) {
|
||||
return {
|
||||
collision: {x: false, y: false, slope: false},
|
||||
pos: {x: x+vx, y: y+vy},
|
||||
tile: {x: 0, y: 0}
|
||||
};
|
||||
}};
|
||||
|
||||
});
|
||||
@@ -0,0 +1,148 @@
|
||||
.ig_debug {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
background-color: #000;
|
||||
border-top: 2px solid #f57401;
|
||||
font-size: 12px;
|
||||
color: #fff;
|
||||
z-index: 1000;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
.ig_debug_panel_menu {
|
||||
height: 28px;
|
||||
background: #222;
|
||||
background: -webkit-gradient(linear, left bottom, left top, color-stop(0,#000000), color-stop(1,#333));
|
||||
background: -moz-linear-gradient(center bottom, #000000 0%, #333 100%);
|
||||
background: -o-linear-gradient(#333, #000000);
|
||||
}
|
||||
|
||||
.ig_debug_panel_menu div {
|
||||
float: left;
|
||||
height: 22px;
|
||||
padding: 6px 8px 0 8px;
|
||||
border-right: 1px solid #333;
|
||||
}
|
||||
|
||||
.ig_debug_panel_menu .ig_debug_head {
|
||||
font-weight: bold;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.ig_debug_menu_item:hover {
|
||||
cursor: pointer;
|
||||
background-color: #fff;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.ig_debug_menu_item.active, .ig_debug_menu_item.active:hover {
|
||||
background-color: #000;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.ig_debug_stats {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
float: right;
|
||||
color: #888;
|
||||
border-left: 1px solid #333;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.ig_debug_stats span {
|
||||
width: 3em;
|
||||
display:inline-block;
|
||||
color: #fff !important;
|
||||
margin-right: 0.2em;
|
||||
margin-left: 0.3em;
|
||||
font-family: bitstream vera sans mono, courier new;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.ig_debug_panel {
|
||||
height: 152px;
|
||||
overflow: auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.ig_debug_panel canvas {
|
||||
border-bottom: 1px solid #444;
|
||||
}
|
||||
|
||||
.ig_debug_panel .ig_debug_panel {
|
||||
padding: 8px;
|
||||
height: auto;
|
||||
float: left;
|
||||
background-color: #000;
|
||||
border-right: 2px solid #222;
|
||||
}
|
||||
|
||||
.ig_debug_option {
|
||||
padding: 2px 0 2px 8px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.ig_debug_option:first-child {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.ig_debug_option:hover {
|
||||
background-color: #111;
|
||||
}
|
||||
|
||||
.ig_debug_graph_mark {
|
||||
position: absolute;
|
||||
color: #888;
|
||||
left: 4px;
|
||||
font-size: 10px;
|
||||
margin-top: -12px;
|
||||
}
|
||||
|
||||
.ig_debug_legend {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.ig_debug_label_mark {
|
||||
display: inline-block;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
margin-right: 4px;
|
||||
-webkit-transition: 0.1s linear;
|
||||
-moz-transition: 0.1s linear;
|
||||
}
|
||||
|
||||
.ig_debug_legend_color {
|
||||
display: inline-block;
|
||||
width: 6px;
|
||||
height: 10px;
|
||||
margin-right: 4px;
|
||||
margin-left: 16px;
|
||||
}
|
||||
|
||||
.ig_debug_legend_number {
|
||||
width: 3em;
|
||||
display: inline-block;
|
||||
text-align: right;
|
||||
font-family: bitstream vera sans mono, courier new;
|
||||
color: #fff;
|
||||
margin-right: 0.2em;
|
||||
}
|
||||
|
||||
|
||||
.ig_debug_map_container {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border: 1px solid #888;
|
||||
}
|
||||
|
||||
.ig_debug_map_container canvas {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.ig_debug_map_screen {
|
||||
position: absolute;
|
||||
border: 1px solid #f0f;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
ig.module(
|
||||
'impact.debug.debug'
|
||||
)
|
||||
.requires(
|
||||
'impact.debug.entities-panel',
|
||||
'impact.debug.maps-panel',
|
||||
'impact.debug.graph-panel'
|
||||
)
|
||||
.defines(function(){ "use strict";
|
||||
|
||||
/* Empty module to require all debug panels */
|
||||
|
||||
});
|
||||
@@ -0,0 +1,129 @@
|
||||
ig.module(
|
||||
'impact.debug.entities-panel'
|
||||
)
|
||||
.requires(
|
||||
'impact.debug.menu',
|
||||
'impact.entity'
|
||||
)
|
||||
.defines(function(){ "use strict";
|
||||
|
||||
|
||||
ig.Entity.inject({
|
||||
colors: {
|
||||
names: '#fff',
|
||||
velocities: '#0f0',
|
||||
boxes: '#f00'
|
||||
},
|
||||
|
||||
draw: function() {
|
||||
this.parent();
|
||||
|
||||
// Collision Boxes
|
||||
if( ig.Entity._debugShowBoxes ) {
|
||||
ig.system.context.strokeStyle = this.colors.boxes;
|
||||
ig.system.context.lineWidth = 1.0;
|
||||
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
|
||||
);
|
||||
}
|
||||
|
||||
// Velocities
|
||||
if( ig.Entity._debugShowVelocities ) {
|
||||
var x = this.pos.x + this.size.x/2;
|
||||
var y = this.pos.y + this.size.y/2;
|
||||
|
||||
this._debugDrawLine( this.colors.velocities, x, y, x + this.vel.x, y + this.vel.y );
|
||||
}
|
||||
|
||||
// Names & Targets
|
||||
if( ig.Entity._debugShowNames ) {
|
||||
if( this.name ) {
|
||||
ig.system.context.fillStyle = this.colors.names;
|
||||
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)
|
||||
);
|
||||
}
|
||||
|
||||
if( typeof(this.target) == 'object' ) {
|
||||
for( var t in this.target ) {
|
||||
var ent = ig.game.getEntityByName( this.target[t] );
|
||||
if( ent ) {
|
||||
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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
_debugDrawLine: function( color, sx, sy, dx, dy ) {
|
||||
ig.system.context.strokeStyle = color;
|
||||
ig.system.context.lineWidth = 1.0;
|
||||
|
||||
ig.system.context.beginPath();
|
||||
ig.system.context.moveTo(
|
||||
ig.system.getDrawPos(sx - ig.game.screen.x),
|
||||
ig.system.getDrawPos(sy - ig.game.screen.y)
|
||||
);
|
||||
ig.system.context.lineTo(
|
||||
ig.system.getDrawPos(dx - ig.game.screen.x),
|
||||
ig.system.getDrawPos(dy - ig.game.screen.y)
|
||||
);
|
||||
ig.system.context.stroke();
|
||||
ig.system.context.closePath();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
ig.Entity._debugEnableChecks = true;
|
||||
ig.Entity._debugShowBoxes = false;
|
||||
ig.Entity._debugShowVelocities = false;
|
||||
ig.Entity._debugShowNames = false;
|
||||
|
||||
ig.Entity.oldCheckPair = ig.Entity.checkPair;
|
||||
ig.Entity.checkPair = function( a, b ) {
|
||||
if( !ig.Entity._debugEnableChecks ) {
|
||||
return;
|
||||
}
|
||||
ig.Entity.oldCheckPair( a, b );
|
||||
};
|
||||
|
||||
|
||||
ig.debug.addPanel({
|
||||
type: ig.DebugPanel,
|
||||
name: 'entities',
|
||||
label: 'Entities',
|
||||
options: [
|
||||
{
|
||||
name: 'Checks & Collisions',
|
||||
object: ig.Entity,
|
||||
property: '_debugEnableChecks'
|
||||
},
|
||||
{
|
||||
name: 'Show Collision Boxes',
|
||||
object: ig.Entity,
|
||||
property: '_debugShowBoxes'
|
||||
},
|
||||
{
|
||||
name: 'Show Velocities',
|
||||
object: ig.Entity,
|
||||
property: '_debugShowVelocities'
|
||||
},
|
||||
{
|
||||
name: 'Show Names & Targets',
|
||||
object: ig.Entity,
|
||||
property: '_debugShowNames'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
@@ -0,0 +1,198 @@
|
||||
ig.module(
|
||||
'impact.debug.graph-panel'
|
||||
)
|
||||
.requires(
|
||||
'impact.debug.menu',
|
||||
'impact.system',
|
||||
'impact.game',
|
||||
'impact.image'
|
||||
)
|
||||
.defines(function(){ "use strict";
|
||||
|
||||
|
||||
ig.Game.inject({
|
||||
draw: function() {
|
||||
ig.graph.beginClock('draw');
|
||||
this.parent();
|
||||
ig.graph.endClock('draw');
|
||||
},
|
||||
|
||||
|
||||
update: function() {
|
||||
ig.graph.beginClock('update');
|
||||
this.parent();
|
||||
ig.graph.endClock('update');
|
||||
},
|
||||
|
||||
|
||||
checkEntities: function() {
|
||||
ig.graph.beginClock('checks');
|
||||
this.parent();
|
||||
ig.graph.endClock('checks');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
ig.DebugGraphPanel = ig.DebugPanel.extend({
|
||||
clocks: {},
|
||||
marks: [],
|
||||
textY: 0,
|
||||
height: 128,
|
||||
ms: 64,
|
||||
timeBeforeRun: 0,
|
||||
|
||||
|
||||
init: function( name, label ) {
|
||||
this.parent( name, label );
|
||||
|
||||
this.mark16ms = (this.height - (this.height/this.ms) * 16).round();
|
||||
this.mark33ms = (this.height - (this.height/this.ms) * 33).round();
|
||||
this.msHeight = this.height/this.ms;
|
||||
|
||||
this.graph = ig.$new('canvas');
|
||||
this.graph.width = window.innerWidth;
|
||||
this.graph.height = this.height;
|
||||
this.container.appendChild( this.graph );
|
||||
this.ctx = this.graph.getContext('2d');
|
||||
|
||||
this.ctx.fillStyle = '#444';
|
||||
this.ctx.fillRect( 0, this.mark16ms, this.graph.width, 1 );
|
||||
this.ctx.fillRect( 0, this.mark33ms, this.graph.width, 1 );
|
||||
|
||||
this.addGraphMark( '16ms', this.mark16ms );
|
||||
this.addGraphMark( '33ms', this.mark33ms );
|
||||
|
||||
this.addClock( 'draw', 'Draw', '#13baff' );
|
||||
this.addClock( 'update', 'Entity Update', '#bb0fff' );
|
||||
this.addClock( 'checks', 'Entity Checks & Collisions', '#a2e908' );
|
||||
this.addClock( 'lag', 'System Lag', '#f26900' );
|
||||
|
||||
ig.mark = this.mark.bind(this);
|
||||
ig.graph = this;
|
||||
},
|
||||
|
||||
|
||||
addGraphMark: function( name, height ) {
|
||||
var span = ig.$new('span');
|
||||
span.className = 'ig_debug_graph_mark';
|
||||
span.textContent = name;
|
||||
span.style.top = height.round() + 'px';
|
||||
this.container.appendChild( span );
|
||||
},
|
||||
|
||||
|
||||
addClock: function( name, description, color ) {
|
||||
var mark = ig.$new('span');
|
||||
mark.className = 'ig_debug_legend_color';
|
||||
mark.style.backgroundColor = color;
|
||||
|
||||
var number = ig.$new('span');
|
||||
number.className = 'ig_debug_legend_number';
|
||||
number.appendChild( document.createTextNode('0') );
|
||||
|
||||
var legend = ig.$new('span');
|
||||
legend.className = 'ig_debug_legend';
|
||||
legend.appendChild( mark );
|
||||
legend.appendChild( document.createTextNode(description +' (') );
|
||||
legend.appendChild( number );
|
||||
legend.appendChild( document.createTextNode('ms)') );
|
||||
|
||||
this.container.appendChild( legend );
|
||||
|
||||
this.clocks[name] = {
|
||||
description: description,
|
||||
color: color,
|
||||
current: 0,
|
||||
start: Date.now(),
|
||||
avg: 0,
|
||||
html: number
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
beginClock: function( name, offset ) {
|
||||
this.clocks[name].start = Date.now() + (offset || 0);
|
||||
},
|
||||
|
||||
|
||||
endClock: function( name ) {
|
||||
var c = this.clocks[name];
|
||||
c.current = Math.round(Date.now() - c.start);
|
||||
c.avg = c.avg * 0.8 + c.current * 0.2;
|
||||
},
|
||||
|
||||
|
||||
mark: function( msg, color ) {
|
||||
if( this.active ) {
|
||||
this.marks.push( {msg:msg, color:(color||'#fff')} );
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
beforeRun: function() {
|
||||
this.endClock('lag');
|
||||
this.timeBeforeRun = Date.now();
|
||||
},
|
||||
|
||||
|
||||
afterRun: function() {
|
||||
var frameTime = Date.now() - this.timeBeforeRun;
|
||||
var nextFrameDue = (1000/ig.system.fps) - frameTime;
|
||||
this.beginClock('lag', Math.max(nextFrameDue, 0));
|
||||
|
||||
|
||||
var x = this.graph.width-1;
|
||||
var y = this.height;
|
||||
|
||||
this.ctx.drawImage( this.graph, -1, 0 );
|
||||
|
||||
this.ctx.fillStyle = '#000';
|
||||
this.ctx.fillRect( x, 0, 1, this.height );
|
||||
|
||||
this.ctx.fillStyle = '#444';
|
||||
this.ctx.fillRect( x, this.mark16ms, 1, 1 );
|
||||
|
||||
this.ctx.fillStyle = '#444';
|
||||
this.ctx.fillRect( x, this.mark33ms, 1, 1 );
|
||||
|
||||
for( var ci in this.clocks ) {
|
||||
var c = this.clocks[ci];
|
||||
c.html.textContent = c.avg.toFixed(2);
|
||||
|
||||
if( c.color && c.current > 0 ) {
|
||||
this.ctx.fillStyle = c.color;
|
||||
var h = c.current * this.msHeight;
|
||||
y -= h;
|
||||
this.ctx.fillRect( x, y, 1, h );
|
||||
c.current = 0;
|
||||
}
|
||||
}
|
||||
|
||||
this.ctx.textAlign = 'right';
|
||||
this.ctx.textBaseline = 'top';
|
||||
this.ctx.globalAlpha = 0.5;
|
||||
|
||||
for( var i = 0; i < this.marks.length; i++ ) {
|
||||
var m = this.marks[i];
|
||||
this.ctx.fillStyle = m.color;
|
||||
this.ctx.fillRect( x, 0, 1, this.height );
|
||||
if( m.msg ) {
|
||||
this.ctx.fillText( m.msg, x-1, this.textY );
|
||||
this.textY = (this.textY+8)%32;
|
||||
}
|
||||
}
|
||||
this.ctx.globalAlpha = 1;
|
||||
this.marks = [];
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
ig.debug.addPanel({
|
||||
type: ig.DebugGraphPanel,
|
||||
name: 'graph',
|
||||
label: 'Performance'
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
@@ -0,0 +1,156 @@
|
||||
ig.module(
|
||||
'impact.debug.maps-panel'
|
||||
)
|
||||
.requires(
|
||||
'impact.debug.menu',
|
||||
'impact.game',
|
||||
'impact.background-map'
|
||||
)
|
||||
.defines(function(){ "use strict";
|
||||
|
||||
|
||||
ig.Game.inject({
|
||||
loadLevel: function( data ) {
|
||||
this.parent(data);
|
||||
ig.debug.panels.maps.load(this);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
ig.DebugMapsPanel = ig.DebugPanel.extend({
|
||||
maps: [],
|
||||
mapScreens: [],
|
||||
|
||||
|
||||
init: function( name, label ) {
|
||||
this.parent( name, label );
|
||||
this.load();
|
||||
},
|
||||
|
||||
|
||||
load: function( game ) {
|
||||
this.options = [];
|
||||
this.panels = [];
|
||||
|
||||
if( !game || !game.backgroundMaps.length ) {
|
||||
this.container.innerHTML = '<em>No Maps Loaded</em>';
|
||||
return;
|
||||
}
|
||||
|
||||
this.maps = game.backgroundMaps;
|
||||
this.mapScreens = [];
|
||||
this.container.innerHTML = '';
|
||||
|
||||
for( var m = 0; m < this.maps.length; m++ ) {
|
||||
var map = this.maps[m];
|
||||
|
||||
var subPanel = new ig.DebugPanel( m, 'Layer '+m );
|
||||
|
||||
var head = new ig.$new('strong');
|
||||
head.textContent = m +': ' + map.tiles.path;
|
||||
subPanel.container.appendChild( head );
|
||||
|
||||
subPanel.addOption( new ig.DebugOption('Enabled', map, 'enabled') );
|
||||
subPanel.addOption( new ig.DebugOption('Pre Rendered', map, 'preRender') );
|
||||
subPanel.addOption( new ig.DebugOption('Show Chunks', map, 'debugChunks') );
|
||||
|
||||
this.generateMiniMap( subPanel, map, m );
|
||||
this.addPanel( subPanel );
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
generateMiniMap: function( panel, map, id ) {
|
||||
var s = ig.system.scale; // we'll need this a lot
|
||||
|
||||
// resize the tileset, so that one tile is 's' pixels wide and high
|
||||
var ts = ig.$new('canvas');
|
||||
var tsctx = ts.getContext('2d');
|
||||
|
||||
var w = map.tiles.width * s;
|
||||
var h = map.tiles.height * s;
|
||||
var ws = w / map.tilesize;
|
||||
var hs = h / map.tilesize;
|
||||
ts.width = ws;
|
||||
ts.height = hs;
|
||||
tsctx.drawImage( map.tiles.data, 0, 0, w, h, 0, 0, ws, hs );
|
||||
|
||||
// create the minimap canvas
|
||||
var mapCanvas = ig.$new('canvas');
|
||||
mapCanvas.width = map.width * s;
|
||||
mapCanvas.height = map.height * s;
|
||||
var ctx = mapCanvas.getContext('2d');
|
||||
|
||||
if( ig.game.clearColor ) {
|
||||
ctx.fillStyle = ig.game.clearColor;
|
||||
ctx.fillRect(0, 0, w, h);
|
||||
}
|
||||
|
||||
// draw the map
|
||||
var tile = 0;
|
||||
for( var x = 0; x < map.width; x++ ) {
|
||||
for( var y = 0; y < map.height; y++ ) {
|
||||
if( (tile = map.data[y][x]) ) {
|
||||
ctx.drawImage(
|
||||
ts,
|
||||
Math.floor(((tile-1) * s) % ws),
|
||||
Math.floor((tile-1) * s / ws) * s,
|
||||
s, s,
|
||||
x * s, y * s,
|
||||
s, s
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var mapContainer = ig.$new('div');
|
||||
mapContainer.className = 'ig_debug_map_container';
|
||||
mapContainer.style.width = map.width * s + 'px';
|
||||
mapContainer.style.height = map.height * s + 'px';
|
||||
|
||||
var mapScreen = ig.$new('div');
|
||||
mapScreen.className = 'ig_debug_map_screen';
|
||||
mapScreen.style.width = ((ig.system.width / map.tilesize) * s - 2) + 'px';
|
||||
mapScreen.style.height = ((ig.system.height / map.tilesize) * s - 2) + 'px';
|
||||
this.mapScreens[id] = mapScreen;
|
||||
|
||||
mapContainer.appendChild( mapCanvas );
|
||||
mapContainer.appendChild( mapScreen );
|
||||
panel.container.appendChild( mapContainer );
|
||||
},
|
||||
|
||||
|
||||
afterRun: function() {
|
||||
// Update the screen position DIV for each mini-map
|
||||
var s = ig.system.scale;
|
||||
for( var m = 0; m < this.maps.length; m++ ) {
|
||||
var map = this.maps[m];
|
||||
var screen = this.mapScreens[m];
|
||||
|
||||
if( !map || !screen ) { // Quick sanity check
|
||||
continue;
|
||||
}
|
||||
|
||||
var x = map.scroll.x / map.tilesize;
|
||||
var y = map.scroll.y / map.tilesize;
|
||||
|
||||
if( map.repeat ) {
|
||||
x %= map.width;
|
||||
y %= map.height;
|
||||
}
|
||||
|
||||
screen.style.left = (x * s) + 'px';
|
||||
screen.style.top = (y * s) + 'px';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
ig.debug.addPanel({
|
||||
type: ig.DebugMapsPanel,
|
||||
name: 'maps',
|
||||
label: 'Background Maps'
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
@@ -0,0 +1,299 @@
|
||||
ig.module(
|
||||
'impact.debug.menu'
|
||||
)
|
||||
.requires(
|
||||
'dom.ready',
|
||||
'impact.system'
|
||||
)
|
||||
.defines(function(){ "use strict";
|
||||
|
||||
|
||||
ig.System.inject({
|
||||
run: function() {
|
||||
ig.debug.beforeRun();
|
||||
this.parent();
|
||||
ig.debug.afterRun();
|
||||
},
|
||||
|
||||
setGameNow: function( gameClass ) {
|
||||
this.parent( gameClass );
|
||||
ig.debug.ready();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
ig.Debug = ig.Class.extend({
|
||||
options: {},
|
||||
panels: {},
|
||||
numbers:{},
|
||||
container: null,
|
||||
panelMenu: null,
|
||||
activePanel: null,
|
||||
|
||||
debugTime: 0,
|
||||
debugTickAvg: 0.016,
|
||||
debugRealTime: Date.now(),
|
||||
|
||||
init: function() {
|
||||
// Inject the Stylesheet
|
||||
var style = ig.$new('link');
|
||||
style.rel = 'stylesheet';
|
||||
style.type = 'text/css';
|
||||
style.href = ig.prefix + 'lib/impact/debug/debug.css';
|
||||
ig.$('body')[0].appendChild( style );
|
||||
|
||||
// Create the Debug Container
|
||||
this.container = ig.$new('div');
|
||||
this.container.className ='ig_debug';
|
||||
ig.$('body')[0].appendChild( this.container );
|
||||
|
||||
// Create and add the Menu Container
|
||||
this.panelMenu = ig.$new('div');
|
||||
this.panelMenu.innerHTML = '<div class="ig_debug_head">Impact.Debug:</div>';
|
||||
this.panelMenu.className ='ig_debug_panel_menu';
|
||||
|
||||
this.container.appendChild( this.panelMenu );
|
||||
|
||||
// Create and add the Stats Container
|
||||
this.numberContainer = ig.$new('div');
|
||||
this.numberContainer.className ='ig_debug_stats';
|
||||
this.panelMenu.appendChild( this.numberContainer );
|
||||
|
||||
// Set ig.log(), ig.assert() and ig.show()
|
||||
if( window.console && window.console.log && window.console.assert ) {
|
||||
// Can't use .bind() on native functions in IE9 :/
|
||||
ig.log = console.log.bind ? console.log.bind(console) : console.log;
|
||||
ig.assert = console.assert.bind ? console.assert.bind(console) : console.assert;
|
||||
}
|
||||
ig.show = this.showNumber.bind(this);
|
||||
},
|
||||
|
||||
|
||||
addNumber: function( name, width ) {
|
||||
var number = ig.$new('span');
|
||||
this.numberContainer.appendChild( number );
|
||||
this.numberContainer.appendChild( document.createTextNode(name) );
|
||||
|
||||
this.numbers[name] = number;
|
||||
},
|
||||
|
||||
|
||||
showNumber: function( name, number, width ) {
|
||||
if( !this.numbers[name] ) {
|
||||
this.addNumber( name, width );
|
||||
}
|
||||
this.numbers[name].textContent = number;
|
||||
},
|
||||
|
||||
|
||||
addPanel: function( panelDef ) {
|
||||
// Create the panel and options
|
||||
var panel = new (panelDef.type)( panelDef.name, panelDef.label );
|
||||
if( panelDef.options ) {
|
||||
for( var i = 0; i < panelDef.options.length; i++ ) {
|
||||
var opt = panelDef.options[i];
|
||||
panel.addOption( new ig.DebugOption(opt.name, opt.object, opt.property) );
|
||||
}
|
||||
}
|
||||
|
||||
this.panels[ panel.name ] = panel;
|
||||
panel.container.style.display = 'none';
|
||||
this.container.appendChild( panel.container );
|
||||
|
||||
|
||||
// Create the menu item
|
||||
var menuItem = ig.$new('div');
|
||||
menuItem.className = 'ig_debug_menu_item';
|
||||
menuItem.textContent = panel.label;
|
||||
menuItem.addEventListener(
|
||||
'click',
|
||||
(function(ev){ this.togglePanel(panel); }).bind(this),
|
||||
false
|
||||
);
|
||||
panel.menuItem = menuItem;
|
||||
|
||||
// Insert menu item in alphabetical order into the menu
|
||||
var inserted = false;
|
||||
for( var i = 1; i < this.panelMenu.childNodes.length; i++ ) {
|
||||
var cn = this.panelMenu.childNodes[i];
|
||||
if( cn.textContent > panel.label ) {
|
||||
this.panelMenu.insertBefore( menuItem, cn );
|
||||
inserted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( !inserted ) {
|
||||
// Not inserted? Append at the end!
|
||||
this.panelMenu.appendChild( menuItem );
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
showPanel: function( name ) {
|
||||
this.togglePanel( this.panels[name] );
|
||||
},
|
||||
|
||||
|
||||
togglePanel: function( panel ) {
|
||||
if( panel != this.activePanel && this.activePanel ) {
|
||||
this.activePanel.toggle( false );
|
||||
this.activePanel.menuItem.className = 'ig_debug_menu_item';
|
||||
this.activePanel = null;
|
||||
}
|
||||
|
||||
var dsp = panel.container.style.display;
|
||||
var active = (dsp != 'block');
|
||||
panel.toggle( active );
|
||||
panel.menuItem.className = 'ig_debug_menu_item' + (active ? ' active' : '');
|
||||
|
||||
if( active ) {
|
||||
this.activePanel = panel;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
ready: function() {
|
||||
for( var p in this.panels ) {
|
||||
this.panels[p].ready();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
beforeRun: function() {
|
||||
var timeBeforeRun = Date.now();
|
||||
this.debugTickAvg = this.debugTickAvg * 0.8 + (timeBeforeRun - this.debugRealTime) * 0.2;
|
||||
this.debugRealTime = timeBeforeRun;
|
||||
|
||||
if( this.activePanel ) {
|
||||
this.activePanel.beforeRun();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
afterRun: function() {
|
||||
var frameTime = Date.now() - this.debugRealTime;
|
||||
var nextFrameDue = (1000/ig.system.fps) - frameTime;
|
||||
|
||||
this.debugTime = this.debugTime * 0.8 + frameTime * 0.2;
|
||||
|
||||
|
||||
if( this.activePanel ) {
|
||||
this.activePanel.afterRun();
|
||||
}
|
||||
|
||||
this.showNumber( 'ms', this.debugTime.toFixed(2) );
|
||||
this.showNumber( 'fps', Math.round(1000/this.debugTickAvg) );
|
||||
this.showNumber( 'draws', ig.Image.drawCount );
|
||||
if( ig.game && ig.game.entities ) {
|
||||
this.showNumber( 'entities', ig.game.entities.length );
|
||||
}
|
||||
ig.Image.drawCount = 0;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
ig.DebugPanel = ig.Class.extend({
|
||||
active: false,
|
||||
container: null,
|
||||
options: [],
|
||||
panels: [],
|
||||
label: '',
|
||||
name: '',
|
||||
|
||||
|
||||
init: function( name, label ) {
|
||||
this.name = name;
|
||||
this.label = label;
|
||||
this.container = ig.$new('div');
|
||||
this.container.className = 'ig_debug_panel ' + this.name;
|
||||
},
|
||||
|
||||
|
||||
toggle: function( active ) {
|
||||
this.active = active;
|
||||
this.container.style.display = active ? 'block' : 'none';
|
||||
},
|
||||
|
||||
|
||||
addPanel: function( panel ) {
|
||||
this.panels.push( panel );
|
||||
this.container.appendChild( panel.container );
|
||||
},
|
||||
|
||||
|
||||
addOption: function( option ) {
|
||||
this.options.push( option );
|
||||
this.container.appendChild( option.container );
|
||||
},
|
||||
|
||||
|
||||
ready: function(){},
|
||||
beforeRun: function(){},
|
||||
afterRun: function(){}
|
||||
});
|
||||
|
||||
|
||||
|
||||
ig.DebugOption = ig.Class.extend({
|
||||
name: '',
|
||||
labelName: '',
|
||||
className: 'ig_debug_option',
|
||||
label: null,
|
||||
mark: null,
|
||||
container: null,
|
||||
active: false,
|
||||
|
||||
colors: {
|
||||
enabled: '#fff',
|
||||
disabled: '#444'
|
||||
},
|
||||
|
||||
|
||||
init: function( name, object, property ) {
|
||||
this.name = name;
|
||||
this.object = object;
|
||||
this.property = property;
|
||||
|
||||
this.active = this.object[this.property];
|
||||
|
||||
this.container = ig.$new('div');
|
||||
this.container.className = 'ig_debug_option';
|
||||
|
||||
this.label = ig.$new('span');
|
||||
this.label.className = 'ig_debug_label';
|
||||
this.label.textContent = this.name;
|
||||
|
||||
this.mark = ig.$new('span');
|
||||
this.mark.className = 'ig_debug_label_mark';
|
||||
|
||||
this.container.appendChild( this.mark );
|
||||
this.container.appendChild( this.label );
|
||||
this.container.addEventListener( 'click', this.click.bind(this), false );
|
||||
|
||||
this.setLabel();
|
||||
},
|
||||
|
||||
|
||||
setLabel: function() {
|
||||
this.mark.style.backgroundColor = this.active ? this.colors.enabled : this.colors.disabled;
|
||||
},
|
||||
|
||||
|
||||
click: function( ev ) {
|
||||
this.active = !this.active;
|
||||
this.object[this.property] = this.active;
|
||||
this.setLabel();
|
||||
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
// Create the debug instance!
|
||||
ig.debug = new ig.Debug();
|
||||
|
||||
});
|
||||
@@ -0,0 +1,60 @@
|
||||
ig.module(
|
||||
'impact.entity-pool'
|
||||
)
|
||||
.requires(
|
||||
'impact.game'
|
||||
)
|
||||
.defines(function(){ "use strict";
|
||||
|
||||
ig.EntityPool = {
|
||||
pools: {},
|
||||
|
||||
mixin: {
|
||||
staticInstantiate: function( x, y, settings ) {
|
||||
return ig.EntityPool.getFromPool( this.classId, x, y, settings );
|
||||
},
|
||||
|
||||
erase: function() {
|
||||
ig.EntityPool.putInPool( this );
|
||||
}
|
||||
},
|
||||
|
||||
enableFor: function( Class ) {
|
||||
Class.inject(this.mixin);
|
||||
},
|
||||
|
||||
getFromPool: function( classId, x, y, settings ) {
|
||||
var pool = this.pools[classId];
|
||||
if( !pool || !pool.length ) { return null; }
|
||||
|
||||
var instance = pool.pop();
|
||||
instance.reset(x, y, settings);
|
||||
return instance;
|
||||
},
|
||||
|
||||
putInPool: function( instance ) {
|
||||
if( !this.pools[instance.classId] ) {
|
||||
this.pools[instance.classId] = [instance];
|
||||
}
|
||||
else {
|
||||
this.pools[instance.classId].push(instance);
|
||||
}
|
||||
},
|
||||
|
||||
drainPool: function( classId ) {
|
||||
delete this.pools[classId];
|
||||
},
|
||||
|
||||
drainAllPools: function() {
|
||||
this.pools = {};
|
||||
}
|
||||
};
|
||||
|
||||
ig.Game.inject({
|
||||
loadLevel: function( data ) {
|
||||
ig.EntityPool.drainAllPools();
|
||||
this.parent(data);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,434 @@
|
||||
ig.module(
|
||||
'impact.entity'
|
||||
)
|
||||
.requires(
|
||||
'impact.animation',
|
||||
'impact.impact'
|
||||
)
|
||||
.defines(function(){ "use strict";
|
||||
|
||||
ig.Entity = ig.Class.extend({
|
||||
id: 0,
|
||||
settings: {},
|
||||
|
||||
size: {x: 16, y:16},
|
||||
offset: {x: 0, y: 0},
|
||||
|
||||
pos: {x: 0, y:0},
|
||||
last: {x: 0, y:0},
|
||||
vel: {x: 0, y: 0},
|
||||
accel: {x: 0, y: 0},
|
||||
friction: {x: 0, y: 0},
|
||||
maxVel: {x: 100, y: 100},
|
||||
zIndex: 0,
|
||||
gravityFactor: 1,
|
||||
standing: false,
|
||||
bounciness: 0,
|
||||
minBounceVelocity: 40,
|
||||
|
||||
anims: {},
|
||||
animSheet: null,
|
||||
currentAnim: null,
|
||||
health: 10,
|
||||
|
||||
type: 0, // TYPE.NONE
|
||||
checkAgainst: 0, // TYPE.NONE
|
||||
collides: 0, // COLLIDES.NEVER
|
||||
|
||||
_killed: false,
|
||||
|
||||
slopeStanding: {min: (44).toRad(), max: (136).toRad() },
|
||||
|
||||
init: function( x, y, settings ) {
|
||||
this.id = ++ig.Entity._lastId;
|
||||
this.pos.x = this.last.x = x;
|
||||
this.pos.y = this.last.y = y;
|
||||
|
||||
ig.merge( this, settings );
|
||||
},
|
||||
|
||||
reset: function( x, y, settings ) {
|
||||
var proto = this.constructor.prototype;
|
||||
this.pos.x = x;
|
||||
this.pos.y = y;
|
||||
this.last.x = x;
|
||||
this.last.y = y;
|
||||
this.vel.x = proto.vel.x;
|
||||
this.vel.y = proto.vel.y;
|
||||
this.accel.x = proto.accel.x;
|
||||
this.accel.y = proto.accel.y;
|
||||
this.health = proto.health;
|
||||
this._killed = proto._killed;
|
||||
this.standing = proto.standing;
|
||||
|
||||
this.type = proto.type;
|
||||
this.checkAgainst = proto.checkAgainst;
|
||||
this.collides = proto.collides;
|
||||
|
||||
ig.merge( this, settings );
|
||||
},
|
||||
|
||||
addAnim: function( name, frameTime, sequence, stop ) {
|
||||
if( !this.animSheet ) {
|
||||
throw( 'No animSheet to add the animation '+name+' to.' );
|
||||
}
|
||||
var a = new ig.Animation( this.animSheet, frameTime, sequence, stop );
|
||||
this.anims[name] = a;
|
||||
if( !this.currentAnim ) {
|
||||
this.currentAnim = a;
|
||||
}
|
||||
|
||||
return a;
|
||||
},
|
||||
|
||||
update: function() {
|
||||
this.last.x = this.pos.x;
|
||||
this.last.y = this.pos.y;
|
||||
this.vel.y += ig.game.gravity * ig.system.tick * this.gravityFactor;
|
||||
|
||||
this.vel.x = this.getNewVelocity( this.vel.x, this.accel.x, this.friction.x, this.maxVel.x );
|
||||
this.vel.y = this.getNewVelocity( this.vel.y, this.accel.y, this.friction.y, this.maxVel.y );
|
||||
|
||||
// movement & collision
|
||||
var mx = this.vel.x * ig.system.tick;
|
||||
var my = this.vel.y * ig.system.tick;
|
||||
var res = ig.game.collisionMap.trace(
|
||||
this.pos.x, this.pos.y, mx, my, this.size.x, this.size.y
|
||||
);
|
||||
this.handleMovementTrace( res );
|
||||
|
||||
if( this.currentAnim ) {
|
||||
this.currentAnim.update();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
getNewVelocity: function( vel, accel, friction, max ) {
|
||||
if( accel ) {
|
||||
return ( vel + accel * ig.system.tick ).limit( -max, max );
|
||||
}
|
||||
else if( friction ) {
|
||||
var delta = friction * ig.system.tick;
|
||||
|
||||
if( vel - delta > 0) {
|
||||
return vel - delta;
|
||||
}
|
||||
else if( vel + delta < 0 ) {
|
||||
return vel + delta;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return vel.limit( -max, max );
|
||||
},
|
||||
|
||||
|
||||
handleMovementTrace: function( res ) {
|
||||
this.standing = false;
|
||||
|
||||
if( res.collision.y ) {
|
||||
if( this.bounciness > 0 && Math.abs(this.vel.y) > this.minBounceVelocity ) {
|
||||
this.vel.y *= -this.bounciness;
|
||||
}
|
||||
else {
|
||||
if( this.vel.y > 0 ) {
|
||||
this.standing = true;
|
||||
}
|
||||
this.vel.y = 0;
|
||||
}
|
||||
}
|
||||
if( res.collision.x ) {
|
||||
if( this.bounciness > 0 && Math.abs(this.vel.x) > this.minBounceVelocity ) {
|
||||
this.vel.x *= -this.bounciness;
|
||||
}
|
||||
else {
|
||||
this.vel.x = 0;
|
||||
}
|
||||
}
|
||||
if( res.collision.slope ) {
|
||||
var s = res.collision.slope;
|
||||
|
||||
if( this.bounciness > 0 ) {
|
||||
var proj = this.vel.x * s.nx + this.vel.y * s.ny;
|
||||
|
||||
this.vel.x = (this.vel.x - s.nx * proj * 2) * this.bounciness;
|
||||
this.vel.y = (this.vel.y - s.ny * proj * 2) * this.bounciness;
|
||||
}
|
||||
else {
|
||||
var lengthSquared = s.x * s.x + s.y * s.y;
|
||||
var dot = (this.vel.x * s.x + this.vel.y * s.y)/lengthSquared;
|
||||
|
||||
this.vel.x = s.x * dot;
|
||||
this.vel.y = s.y * dot;
|
||||
|
||||
var angle = Math.atan2( s.x, s.y );
|
||||
if( angle > this.slopeStanding.min && angle < this.slopeStanding.max ) {
|
||||
this.standing = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.pos = res.pos;
|
||||
},
|
||||
|
||||
|
||||
draw: function() {
|
||||
if( this.currentAnim ) {
|
||||
this.currentAnim.draw(
|
||||
this.pos.x - this.offset.x - ig.game._rscreen.x,
|
||||
this.pos.y - this.offset.y - ig.game._rscreen.y
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
kill: function() {
|
||||
ig.game.removeEntity( this );
|
||||
},
|
||||
|
||||
|
||||
receiveDamage: function( amount, from ) {
|
||||
this.health -= amount;
|
||||
if( this.health <= 0 ) {
|
||||
this.kill();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
touches: function( other ) {
|
||||
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
|
||||
);
|
||||
},
|
||||
|
||||
|
||||
distanceTo: function( other ) {
|
||||
var xd = (this.pos.x + this.size.x/2) - (other.pos.x + other.size.x/2);
|
||||
var yd = (this.pos.y + this.size.y/2) - (other.pos.y + other.size.y/2);
|
||||
return Math.sqrt( xd*xd + yd*yd );
|
||||
},
|
||||
|
||||
|
||||
angleTo: function( other ) {
|
||||
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)
|
||||
);
|
||||
},
|
||||
|
||||
|
||||
check: function( other ) {},
|
||||
collideWith: function( other, axis ) {},
|
||||
ready: function() {},
|
||||
erase: function() {}
|
||||
});
|
||||
|
||||
|
||||
// Last used entity id; incremented with each spawned entity
|
||||
|
||||
ig.Entity._lastId = 0;
|
||||
|
||||
|
||||
// Collision Types - Determine if and how entities collide with each other
|
||||
|
||||
// In ACTIVE vs. LITE or FIXED vs. ANY collisions, only the "weak" entity moves,
|
||||
// while the other one stays fixed. In ACTIVE vs. ACTIVE and ACTIVE vs. PASSIVE
|
||||
// collisions, both entities are moved. LITE or PASSIVE entities don't collide
|
||||
// with other LITE or PASSIVE entities at all. The behaiviour for FIXED vs.
|
||||
// FIXED collisions is undefined.
|
||||
|
||||
ig.Entity.COLLIDES = {
|
||||
NEVER: 0,
|
||||
LITE: 1,
|
||||
PASSIVE: 2,
|
||||
ACTIVE: 4,
|
||||
FIXED: 8
|
||||
};
|
||||
|
||||
|
||||
// Entity Types - used for checks
|
||||
|
||||
ig.Entity.TYPE = {
|
||||
NONE: 0,
|
||||
A: 1,
|
||||
B: 2,
|
||||
BOTH: 3
|
||||
};
|
||||
|
||||
|
||||
|
||||
ig.Entity.checkPair = function( a, b ) {
|
||||
|
||||
// Do these entities want checks?
|
||||
if( a.checkAgainst & b.type ) {
|
||||
a.check( b );
|
||||
}
|
||||
|
||||
if( b.checkAgainst & a.type ) {
|
||||
b.check( a );
|
||||
}
|
||||
|
||||
// If this pair allows collision, solve it! At least one entity must
|
||||
// collide ACTIVE or FIXED, while the other one must not collide NEVER.
|
||||
if(
|
||||
a.collides && b.collides &&
|
||||
a.collides + b.collides > ig.Entity.COLLIDES.ACTIVE
|
||||
) {
|
||||
ig.Entity.solveCollision( a, b );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
ig.Entity.solveCollision = function( a, b ) {
|
||||
|
||||
// If one entity is FIXED, or the other entity is LITE, the weak
|
||||
// (FIXED/NON-LITE) entity won't move in collision response
|
||||
var weak = null;
|
||||
if(
|
||||
a.collides == ig.Entity.COLLIDES.LITE ||
|
||||
b.collides == ig.Entity.COLLIDES.FIXED
|
||||
) {
|
||||
weak = a;
|
||||
}
|
||||
else if(
|
||||
b.collides == ig.Entity.COLLIDES.LITE ||
|
||||
a.collides == ig.Entity.COLLIDES.FIXED
|
||||
) {
|
||||
weak = b;
|
||||
}
|
||||
|
||||
|
||||
// Did they already overlap on the X-axis in the last frame? If so,
|
||||
// this must be a vertical collision!
|
||||
if(
|
||||
a.last.x + a.size.x > b.last.x &&
|
||||
a.last.x < b.last.x + b.size.x
|
||||
) {
|
||||
// Which one is on top?
|
||||
if( a.last.y < b.last.y ) {
|
||||
ig.Entity.seperateOnYAxis( a, b, weak );
|
||||
}
|
||||
else {
|
||||
ig.Entity.seperateOnYAxis( b, a, weak );
|
||||
}
|
||||
a.collideWith( b, 'y' );
|
||||
b.collideWith( a, 'y' );
|
||||
}
|
||||
|
||||
// Horizontal collision
|
||||
else if(
|
||||
a.last.y + a.size.y > b.last.y &&
|
||||
a.last.y < b.last.y + b.size.y
|
||||
){
|
||||
// Which one is on the left?
|
||||
if( a.last.x < b.last.x ) {
|
||||
ig.Entity.seperateOnXAxis( a, b, weak );
|
||||
}
|
||||
else {
|
||||
ig.Entity.seperateOnXAxis( b, a, weak );
|
||||
}
|
||||
a.collideWith( b, 'x' );
|
||||
b.collideWith( a, 'x' );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// FIXME: This is a mess. Instead of doing all the movements here, the entities
|
||||
// should get notified of the collision (with all details) and resolve it
|
||||
// themselfs.
|
||||
|
||||
ig.Entity.seperateOnXAxis = function( left, right, weak ) {
|
||||
var nudge = (left.pos.x + left.size.x - right.pos.x);
|
||||
|
||||
// We have a weak entity, so just move this one
|
||||
if( weak ) {
|
||||
var strong = left === weak ? right : left;
|
||||
weak.vel.x = -weak.vel.x * weak.bounciness + strong.vel.x;
|
||||
|
||||
var resWeak = ig.game.collisionMap.trace(
|
||||
weak.pos.x, weak.pos.y, weak == left ? -nudge : nudge, 0, weak.size.x, weak.size.y
|
||||
);
|
||||
weak.pos.x = resWeak.pos.x;
|
||||
}
|
||||
|
||||
// Normal collision - both move
|
||||
else {
|
||||
var v2 = (left.vel.x - right.vel.x)/2;
|
||||
left.vel.x = -v2;
|
||||
right.vel.x = v2;
|
||||
|
||||
var resLeft = ig.game.collisionMap.trace(
|
||||
left.pos.x, left.pos.y, -nudge/2, 0, left.size.x, left.size.y
|
||||
);
|
||||
left.pos.x = Math.floor(resLeft.pos.x);
|
||||
|
||||
var resRight = ig.game.collisionMap.trace(
|
||||
right.pos.x, right.pos.y, nudge/2, 0, right.size.x, right.size.y
|
||||
);
|
||||
right.pos.x = Math.ceil(resRight.pos.x);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
ig.Entity.seperateOnYAxis = function( top, bottom, weak ) {
|
||||
var nudge = (top.pos.y + top.size.y - bottom.pos.y);
|
||||
|
||||
// We have a weak entity, so just move this one
|
||||
if( weak ) {
|
||||
var strong = top === weak ? bottom : top;
|
||||
weak.vel.y = -weak.vel.y * weak.bounciness + strong.vel.y;
|
||||
|
||||
// Riding on a platform?
|
||||
var nudgeX = 0;
|
||||
if( weak == top && Math.abs(weak.vel.y - strong.vel.y) < weak.minBounceVelocity ) {
|
||||
weak.standing = true;
|
||||
nudgeX = strong.vel.x * ig.system.tick;
|
||||
}
|
||||
|
||||
var resWeak = ig.game.collisionMap.trace(
|
||||
weak.pos.x, weak.pos.y, nudgeX, weak == top ? -nudge : nudge, weak.size.x, weak.size.y
|
||||
);
|
||||
weak.pos.y = resWeak.pos.y;
|
||||
weak.pos.x = resWeak.pos.x;
|
||||
}
|
||||
|
||||
// Bottom entity is standing - just bounce the top one
|
||||
else if( ig.game.gravity && (bottom.standing || top.vel.y > 0) ) {
|
||||
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
|
||||
);
|
||||
top.pos.y = resTop.pos.y;
|
||||
|
||||
if( top.bounciness > 0 && top.vel.y > top.minBounceVelocity ) {
|
||||
top.vel.y *= -top.bounciness;
|
||||
}
|
||||
else {
|
||||
top.standing = true;
|
||||
top.vel.y = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Normal collision - both move
|
||||
else {
|
||||
var v2 = (top.vel.y - bottom.vel.y)/2;
|
||||
top.vel.y = -v2;
|
||||
bottom.vel.y = v2;
|
||||
|
||||
var nudgeX = bottom.vel.x * ig.system.tick;
|
||||
var resTop = ig.game.collisionMap.trace(
|
||||
top.pos.x, top.pos.y, nudgeX, -nudge/2, top.size.x, top.size.y
|
||||
);
|
||||
top.pos.y = resTop.pos.y;
|
||||
|
||||
var resBottom = ig.game.collisionMap.trace(
|
||||
bottom.pos.x, bottom.pos.y, 0, nudge/2, bottom.size.x, bottom.size.y
|
||||
);
|
||||
bottom.pos.y = resBottom.pos.y;
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
@@ -0,0 +1,152 @@
|
||||
ig.module(
|
||||
'impact.font'
|
||||
)
|
||||
.requires(
|
||||
'impact.image'
|
||||
)
|
||||
.defines(function(){ "use strict";
|
||||
|
||||
|
||||
ig.Font = ig.Image.extend({
|
||||
widthMap: [],
|
||||
indices: [],
|
||||
firstChar: 32,
|
||||
alpha: 1,
|
||||
letterSpacing: 1,
|
||||
lineSpacing: 0,
|
||||
|
||||
|
||||
onload: function( ev ) {
|
||||
this._loadMetrics( this.data );
|
||||
this.parent( ev );
|
||||
},
|
||||
|
||||
|
||||
widthForString: function( text ) {
|
||||
// Multiline?
|
||||
if( text.indexOf('\n') !== -1 ) {
|
||||
var lines = text.split( '\n' );
|
||||
var width = 0;
|
||||
for( var i = 0; i < lines.length; i++ ) {
|
||||
width = Math.max( width, this._widthForLine(lines[i]) );
|
||||
}
|
||||
return width;
|
||||
}
|
||||
else {
|
||||
return this._widthForLine( text );
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
_widthForLine: function( text ) {
|
||||
var width = 0;
|
||||
for( var i = 0; i < text.length; i++ ) {
|
||||
width += this.widthMap[text.charCodeAt(i) - this.firstChar] + this.letterSpacing;
|
||||
}
|
||||
return width;
|
||||
},
|
||||
|
||||
|
||||
heightForString: function( text ) {
|
||||
return text.split('\n').length * (this.height + this.lineSpacing);
|
||||
},
|
||||
|
||||
|
||||
draw: function( text, x, y, align ) {
|
||||
if( typeof(text) != 'string' ) {
|
||||
text = text.toString();
|
||||
}
|
||||
|
||||
// Multiline?
|
||||
if( text.indexOf('\n') !== -1 ) {
|
||||
var lines = text.split( '\n' );
|
||||
var lineHeight = this.height + this.lineSpacing;
|
||||
for( var i = 0; i < lines.length; i++ ) {
|
||||
this.draw( lines[i], x, y + i * lineHeight, align );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if( align == ig.Font.ALIGN.RIGHT || align == ig.Font.ALIGN.CENTER ) {
|
||||
var width = this._widthForLine( text );
|
||||
x -= align == ig.Font.ALIGN.CENTER ? width/2 : width;
|
||||
}
|
||||
|
||||
|
||||
if( this.alpha !== 1 ) {
|
||||
ig.system.context.globalAlpha = this.alpha;
|
||||
}
|
||||
|
||||
for( var i = 0; i < text.length; i++ ) {
|
||||
var c = text.charCodeAt(i);
|
||||
x += this._drawChar( c - this.firstChar, x, y );
|
||||
}
|
||||
|
||||
if( this.alpha !== 1 ) {
|
||||
ig.system.context.globalAlpha = 1;
|
||||
}
|
||||
ig.Image.drawCount += text.length;
|
||||
},
|
||||
|
||||
|
||||
_drawChar: function( c, targetX, targetY ) {
|
||||
if( !this.loaded || c < 0 || c >= this.indices.length ) { return 0; }
|
||||
|
||||
var scale = ig.system.scale;
|
||||
|
||||
|
||||
var charX = this.indices[c] * scale;
|
||||
var charY = 0;
|
||||
var charWidth = this.widthMap[c] * scale;
|
||||
var charHeight = (this.height-2) * scale;
|
||||
|
||||
ig.system.context.drawImage(
|
||||
this.data,
|
||||
charX, charY,
|
||||
charWidth, charHeight,
|
||||
ig.system.getDrawPos(targetX), ig.system.getDrawPos(targetY),
|
||||
charWidth, charHeight
|
||||
);
|
||||
|
||||
return this.widthMap[c] + this.letterSpacing;
|
||||
},
|
||||
|
||||
|
||||
_loadMetrics: function( image ) {
|
||||
// Draw the bottommost line of this font image into an offscreen canvas
|
||||
// and analyze it pixel by pixel.
|
||||
// A run of non-transparent pixels represents a character and its width
|
||||
|
||||
this.height = image.height-1;
|
||||
this.widthMap = [];
|
||||
this.indices = [];
|
||||
|
||||
var px = ig.getImagePixels( image, 0, image.height-1, image.width, 1 );
|
||||
|
||||
var currentChar = 0;
|
||||
var currentWidth = 0;
|
||||
for( var x = 0; x < image.width; x++ ) {
|
||||
var index = x * 4 + 3; // alpha component of this pixel
|
||||
if( px.data[index] > 127 ) {
|
||||
currentWidth++;
|
||||
}
|
||||
else if( px.data[index] < 128 && currentWidth ) {
|
||||
this.widthMap.push( currentWidth );
|
||||
this.indices.push( x-currentWidth );
|
||||
currentChar++;
|
||||
currentWidth = 0;
|
||||
}
|
||||
}
|
||||
this.widthMap.push( currentWidth );
|
||||
this.indices.push( x-currentWidth );
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
ig.Font.ALIGN = {
|
||||
LEFT: 0,
|
||||
RIGHT: 1,
|
||||
CENTER: 2
|
||||
};
|
||||
|
||||
});
|
||||
@@ -0,0 +1,326 @@
|
||||
ig.module(
|
||||
'impact.game'
|
||||
)
|
||||
.requires(
|
||||
'impact.impact',
|
||||
'impact.entity',
|
||||
'impact.collision-map',
|
||||
'impact.background-map'
|
||||
)
|
||||
.defines(function(){ "use strict";
|
||||
|
||||
ig.Game = ig.Class.extend({
|
||||
|
||||
clearColor: '#000000',
|
||||
gravity: 0,
|
||||
screen: {x: 0, y: 0},
|
||||
_rscreen: {x: 0, y: 0},
|
||||
|
||||
entities: [],
|
||||
|
||||
namedEntities: {},
|
||||
collisionMap: ig.CollisionMap.staticNoCollision,
|
||||
backgroundMaps: [],
|
||||
backgroundAnims: {},
|
||||
|
||||
autoSort: false,
|
||||
sortBy: null,
|
||||
|
||||
cellSize: 64,
|
||||
|
||||
_deferredKill: [],
|
||||
_levelToLoad: null,
|
||||
_doSortEntities: false,
|
||||
|
||||
|
||||
staticInstantiate: function() {
|
||||
this.sortBy = this.sortBy || ig.Game.SORT.Z_INDEX;
|
||||
ig.game = this;
|
||||
return null;
|
||||
},
|
||||
|
||||
|
||||
loadLevel: function( data ) {
|
||||
this.screen = {x: 0, y: 0};
|
||||
|
||||
// Entities
|
||||
this.entities = [];
|
||||
this.namedEntities = {};
|
||||
for( var i = 0; i < data.entities.length; i++ ) {
|
||||
var ent = data.entities[i];
|
||||
this.spawnEntity( ent.type, ent.x, ent.y, ent.settings );
|
||||
}
|
||||
this.sortEntities();
|
||||
|
||||
// Map Layer
|
||||
this.collisionMap = ig.CollisionMap.staticNoCollision;
|
||||
this.backgroundMaps = [];
|
||||
for( var i = 0; i < data.layer.length; i++ ) {
|
||||
var ld = data.layer[i];
|
||||
if( ld.name == 'collision' ) {
|
||||
this.collisionMap = new ig.CollisionMap(ld.tilesize, ld.data );
|
||||
}
|
||||
else {
|
||||
var newMap = new ig.BackgroundMap(ld.tilesize, ld.data, ld.tilesetName);
|
||||
newMap.anims = this.backgroundAnims[ld.tilesetName] || {};
|
||||
newMap.repeat = ld.repeat;
|
||||
newMap.distance = ld.distance;
|
||||
newMap.foreground = !!ld.foreground;
|
||||
newMap.preRender = !!ld.preRender;
|
||||
newMap.name = ld.name;
|
||||
this.backgroundMaps.push( newMap );
|
||||
}
|
||||
}
|
||||
|
||||
// Call post-init ready function on all entities
|
||||
for( var i = 0; i < this.entities.length; i++ ) {
|
||||
this.entities[i].ready();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
loadLevelDeferred: function( data ) {
|
||||
this._levelToLoad = data;
|
||||
},
|
||||
|
||||
|
||||
getMapByName: function( name ) {
|
||||
if( name == 'collision' ) {
|
||||
return this.collisionMap;
|
||||
}
|
||||
|
||||
for( var i = 0; i < this.backgroundMaps.length; i++ ) {
|
||||
if( this.backgroundMaps[i].name == name ) {
|
||||
return this.backgroundMaps[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
|
||||
getEntityByName: function( name ) {
|
||||
return this.namedEntities[name];
|
||||
},
|
||||
|
||||
|
||||
getEntitiesByType: function( type ) {
|
||||
var entityClass = typeof(type) === 'string'
|
||||
? ig.global[type]
|
||||
: type;
|
||||
|
||||
var a = [];
|
||||
for( var i = 0; i < this.entities.length; i++ ) {
|
||||
var ent = this.entities[i];
|
||||
if( ent instanceof entityClass && !ent._killed ) {
|
||||
a.push( ent );
|
||||
}
|
||||
}
|
||||
return a;
|
||||
},
|
||||
|
||||
|
||||
spawnEntity: function( type, x, y, settings ) {
|
||||
var entityClass = typeof(type) === 'string'
|
||||
? ig.global[type]
|
||||
: type;
|
||||
|
||||
if( !entityClass ) {
|
||||
throw("Can't spawn entity of type " + type);
|
||||
}
|
||||
var ent = new (entityClass)( x, y, settings || {} );
|
||||
this.entities.push( ent );
|
||||
if( ent.name ) {
|
||||
this.namedEntities[ent.name] = ent;
|
||||
}
|
||||
return ent;
|
||||
},
|
||||
|
||||
|
||||
sortEntities: function() {
|
||||
this.entities.sort( this.sortBy );
|
||||
},
|
||||
|
||||
|
||||
sortEntitiesDeferred: function() {
|
||||
this._doSortEntities = true;
|
||||
},
|
||||
|
||||
|
||||
removeEntity: function( ent ) {
|
||||
// Remove this entity from the named entities
|
||||
if( ent.name ) {
|
||||
delete this.namedEntities[ent.name];
|
||||
}
|
||||
|
||||
// We can not remove the entity from the entities[] array in the midst
|
||||
// of an update cycle, so remember all killed entities and remove
|
||||
// them later.
|
||||
// Also make sure this entity doesn't collide anymore and won't get
|
||||
// updated or checked
|
||||
ent._killed = true;
|
||||
ent.type = ig.Entity.TYPE.NONE;
|
||||
ent.checkAgainst = ig.Entity.TYPE.NONE;
|
||||
ent.collides = ig.Entity.COLLIDES.NEVER;
|
||||
this._deferredKill.push( ent );
|
||||
},
|
||||
|
||||
|
||||
run: function() {
|
||||
this.update();
|
||||
this.draw();
|
||||
},
|
||||
|
||||
|
||||
update: function(){
|
||||
// load new level?
|
||||
if( this._levelToLoad ) {
|
||||
this.loadLevel( this._levelToLoad );
|
||||
this._levelToLoad = null;
|
||||
}
|
||||
|
||||
// update entities
|
||||
this.updateEntities();
|
||||
this.checkEntities();
|
||||
|
||||
// remove all killed entities
|
||||
for( var i = 0; i < this._deferredKill.length; i++ ) {
|
||||
this._deferredKill[i].erase();
|
||||
this.entities.erase( this._deferredKill[i] );
|
||||
}
|
||||
this._deferredKill = [];
|
||||
|
||||
// sort entities?
|
||||
if( this._doSortEntities || this.autoSort ) {
|
||||
this.sortEntities();
|
||||
this._doSortEntities = false;
|
||||
}
|
||||
|
||||
// update background animations
|
||||
for( var tileset in this.backgroundAnims ) {
|
||||
var anims = this.backgroundAnims[tileset];
|
||||
for( var a in anims ) {
|
||||
anims[a].update();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
updateEntities: function() {
|
||||
for( var i = 0; i < this.entities.length; i++ ) {
|
||||
var ent = this.entities[i];
|
||||
if( !ent._killed ) {
|
||||
ent.update();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
draw: function(){
|
||||
if( this.clearColor ) {
|
||||
ig.system.clear( this.clearColor );
|
||||
}
|
||||
|
||||
// This is a bit of a circle jerk. Entities reference game._rscreen
|
||||
// instead of game.screen when drawing themselfs in order to be
|
||||
// "synchronized" to the rounded(?) screen position
|
||||
this._rscreen.x = ig.system.getDrawPos(this.screen.x)/ig.system.scale;
|
||||
this._rscreen.y = ig.system.getDrawPos(this.screen.y)/ig.system.scale;
|
||||
|
||||
|
||||
var mapIndex;
|
||||
for( mapIndex = 0; mapIndex < this.backgroundMaps.length; mapIndex++ ) {
|
||||
var map = this.backgroundMaps[mapIndex];
|
||||
if( map.foreground ) {
|
||||
// All foreground layers are drawn after the entities
|
||||
break;
|
||||
}
|
||||
map.setScreenPos( this.screen.x, this.screen.y );
|
||||
map.draw();
|
||||
}
|
||||
|
||||
|
||||
this.drawEntities();
|
||||
|
||||
|
||||
for( mapIndex; mapIndex < this.backgroundMaps.length; mapIndex++ ) {
|
||||
var map = this.backgroundMaps[mapIndex];
|
||||
map.setScreenPos( this.screen.x, this.screen.y );
|
||||
map.draw();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
drawEntities: function() {
|
||||
for( var i = 0; i < this.entities.length; i++ ) {
|
||||
this.entities[i].draw();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
checkEntities: function() {
|
||||
// Insert all entities into a spatial hash and check them against any
|
||||
// other entity that already resides in the same cell. Entities that are
|
||||
// bigger than a single cell, are inserted into each one they intersect
|
||||
// with.
|
||||
|
||||
// A list of entities, which the current one was already checked with,
|
||||
// is maintained for each entity.
|
||||
|
||||
var hash = {};
|
||||
for( var e = 0; e < this.entities.length; e++ ) {
|
||||
var entity = this.entities[e];
|
||||
|
||||
// Skip entities that don't check, don't get checked and don't collide
|
||||
if(
|
||||
entity.type == ig.Entity.TYPE.NONE &&
|
||||
entity.checkAgainst == ig.Entity.TYPE.NONE &&
|
||||
entity.collides == ig.Entity.COLLIDES.NEVER
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var checked = {},
|
||||
xmin = Math.floor( entity.pos.x/this.cellSize ),
|
||||
ymin = Math.floor( entity.pos.y/this.cellSize ),
|
||||
xmax = Math.floor( (entity.pos.x+entity.size.x)/this.cellSize ) + 1,
|
||||
ymax = Math.floor( (entity.pos.y+entity.size.y)/this.cellSize ) + 1;
|
||||
|
||||
for( var x = xmin; x < xmax; x++ ) {
|
||||
for( var y = ymin; y < ymax; y++ ) {
|
||||
|
||||
// Current cell is empty - create it and insert!
|
||||
if( !hash[x] ) {
|
||||
hash[x] = {};
|
||||
hash[x][y] = [entity];
|
||||
}
|
||||
else if( !hash[x][y] ) {
|
||||
hash[x][y] = [entity];
|
||||
}
|
||||
|
||||
// Check against each entity in this cell, then insert
|
||||
else {
|
||||
var cell = hash[x][y];
|
||||
for( var c = 0; c < cell.length; c++ ) {
|
||||
|
||||
// Intersects and wasn't already checkd?
|
||||
if( entity.touches(cell[c]) && !checked[cell[c].id] ) {
|
||||
checked[cell[c].id] = true;
|
||||
ig.Entity.checkPair( entity, cell[c] );
|
||||
}
|
||||
}
|
||||
cell.push(entity);
|
||||
}
|
||||
} // end for y size
|
||||
} // end for x size
|
||||
} // end for entities
|
||||
}
|
||||
});
|
||||
|
||||
ig.Game.SORT = {
|
||||
Z_INDEX: function( a, b ){ return a.zIndex - b.zIndex; },
|
||||
POS_X: function( a, b ){ return (a.pos.x+a.size.x) - (b.pos.x+b.size.x); },
|
||||
POS_Y: function( a, b ){ return (a.pos.y+a.size.y) - (b.pos.y+b.size.y); }
|
||||
};
|
||||
|
||||
});
|
||||
@@ -0,0 +1,178 @@
|
||||
ig.module(
|
||||
'impact.image'
|
||||
)
|
||||
.defines(function(){ "use strict";
|
||||
|
||||
ig.Image = ig.Class.extend({
|
||||
data: null,
|
||||
width: 0,
|
||||
height: 0,
|
||||
loaded: false,
|
||||
failed: false,
|
||||
loadCallback: null,
|
||||
path: '',
|
||||
|
||||
|
||||
staticInstantiate: function( path ) {
|
||||
return ig.Image.cache[path] || null;
|
||||
},
|
||||
|
||||
|
||||
init: function( path ) {
|
||||
this.path = path;
|
||||
this.load();
|
||||
},
|
||||
|
||||
|
||||
load: function( loadCallback ) {
|
||||
if( this.loaded ) {
|
||||
if( loadCallback ) {
|
||||
loadCallback( this.path, true );
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if( !this.loaded && ig.ready ) {
|
||||
this.loadCallback = loadCallback || null;
|
||||
|
||||
this.data = new Image();
|
||||
this.data.onload = this.onload.bind(this);
|
||||
this.data.onerror = this.onerror.bind(this);
|
||||
this.data.src = ig.prefix + this.path + ig.nocache;
|
||||
}
|
||||
else {
|
||||
ig.addResource( this );
|
||||
}
|
||||
|
||||
ig.Image.cache[this.path] = this;
|
||||
},
|
||||
|
||||
|
||||
reload: function() {
|
||||
this.loaded = false;
|
||||
this.data = new Image();
|
||||
this.data.onload = this.onload.bind(this);
|
||||
this.data.src = this.path + '?' + Date.now();
|
||||
},
|
||||
|
||||
|
||||
onload: function( event ) {
|
||||
this.width = this.data.width;
|
||||
this.height = this.data.height;
|
||||
this.loaded = true;
|
||||
|
||||
if( ig.system.scale != 1 ) {
|
||||
this.resize( ig.system.scale );
|
||||
}
|
||||
|
||||
if( this.loadCallback ) {
|
||||
this.loadCallback( this.path, true );
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
onerror: function( event ) {
|
||||
this.failed = true;
|
||||
|
||||
if( this.loadCallback ) {
|
||||
this.loadCallback( this.path, false );
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
resize: function( scale ) {
|
||||
// Nearest-Neighbor scaling
|
||||
|
||||
// The original image is drawn into an offscreen canvas of the same size
|
||||
// and copied into another offscreen canvas with the new size.
|
||||
// The scaled offscreen canvas becomes the image (data) of this object.
|
||||
|
||||
var origPixels = ig.getImagePixels( this.data, 0, 0, this.width, this.height );
|
||||
|
||||
var widthScaled = this.width * scale;
|
||||
var heightScaled = this.height * scale;
|
||||
|
||||
var scaled = ig.$new('canvas');
|
||||
scaled.width = widthScaled;
|
||||
scaled.height = heightScaled;
|
||||
var scaledCtx = scaled.getContext('2d');
|
||||
var scaledPixels = scaledCtx.getImageData( 0, 0, widthScaled, heightScaled );
|
||||
|
||||
for( var y = 0; y < heightScaled; y++ ) {
|
||||
for( var x = 0; x < widthScaled; x++ ) {
|
||||
var index = (Math.floor(y / scale) * this.width + Math.floor(x / scale)) * 4;
|
||||
var indexScaled = (y * widthScaled + x) * 4;
|
||||
scaledPixels.data[ indexScaled ] = origPixels.data[ index ];
|
||||
scaledPixels.data[ indexScaled+1 ] = origPixels.data[ index+1 ];
|
||||
scaledPixels.data[ indexScaled+2 ] = origPixels.data[ index+2 ];
|
||||
scaledPixels.data[ indexScaled+3 ] = origPixels.data[ index+3 ];
|
||||
}
|
||||
}
|
||||
scaledCtx.putImageData( scaledPixels, 0, 0 );
|
||||
this.data = scaled;
|
||||
},
|
||||
|
||||
|
||||
draw: function( targetX, targetY, sourceX, sourceY, width, height ) {
|
||||
if( !this.loaded ) { return; }
|
||||
|
||||
var scale = ig.system.scale;
|
||||
sourceX = sourceX ? sourceX * scale : 0;
|
||||
sourceY = sourceY ? sourceY * scale : 0;
|
||||
width = (width ? width : this.width) * scale;
|
||||
height = (height ? height : this.height) * scale;
|
||||
|
||||
ig.system.context.drawImage(
|
||||
this.data, sourceX, sourceY, width, height,
|
||||
ig.system.getDrawPos(targetX),
|
||||
ig.system.getDrawPos(targetY),
|
||||
width, height
|
||||
);
|
||||
|
||||
ig.Image.drawCount++;
|
||||
},
|
||||
|
||||
|
||||
drawTile: function( targetX, targetY, tile, tileWidth, tileHeight, flipX, flipY ) {
|
||||
tileHeight = tileHeight ? tileHeight : tileWidth;
|
||||
|
||||
if( !this.loaded || tileWidth > this.width || tileHeight > this.height ) { return; }
|
||||
|
||||
var scale = ig.system.scale;
|
||||
var tileWidthScaled = Math.floor(tileWidth * scale);
|
||||
var tileHeightScaled = Math.floor(tileHeight * scale);
|
||||
|
||||
var scaleX = flipX ? -1 : 1;
|
||||
var scaleY = flipY ? -1 : 1;
|
||||
|
||||
if( flipX || flipY ) {
|
||||
ig.system.context.save();
|
||||
ig.system.context.scale( scaleX, scaleY );
|
||||
}
|
||||
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
|
||||
);
|
||||
if( flipX || flipY ) {
|
||||
ig.system.context.restore();
|
||||
}
|
||||
|
||||
ig.Image.drawCount++;
|
||||
}
|
||||
});
|
||||
|
||||
ig.Image.drawCount = 0;
|
||||
ig.Image.cache = {};
|
||||
ig.Image.reloadCache = function() {
|
||||
for( var path in ig.Image.cache ) {
|
||||
ig.Image.cache[path].reload();
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
@@ -0,0 +1,590 @@
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Impact Game Engine 1.24
|
||||
// http://impactjs.com/
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
(function(window){ "use strict";
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Native Object extensions
|
||||
|
||||
Number.prototype.map = function(istart, istop, ostart, ostop) {
|
||||
return ostart + (ostop - ostart) * ((this - istart) / (istop - istart));
|
||||
};
|
||||
|
||||
Number.prototype.limit = function(min, max) {
|
||||
return Math.min(max, Math.max(min, this));
|
||||
};
|
||||
|
||||
Number.prototype.round = function(precision) {
|
||||
precision = Math.pow(10, precision || 0);
|
||||
return Math.round(this * precision) / precision;
|
||||
};
|
||||
|
||||
Number.prototype.floor = function() {
|
||||
return Math.floor(this);
|
||||
};
|
||||
|
||||
Number.prototype.ceil = function() {
|
||||
return Math.ceil(this);
|
||||
};
|
||||
|
||||
Number.prototype.toInt = function() {
|
||||
return (this | 0);
|
||||
};
|
||||
|
||||
Number.prototype.toRad = function() {
|
||||
return (this / 180) * Math.PI;
|
||||
};
|
||||
|
||||
Number.prototype.toDeg = function() {
|
||||
return (this * 180) / Math.PI;
|
||||
};
|
||||
|
||||
Object.defineProperty(Array.prototype, 'erase', {value: function(item) {
|
||||
for( var i = this.length; i--; ) {
|
||||
if( this[i] === item ) {
|
||||
this.splice(i, 1);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}});
|
||||
|
||||
Object.defineProperty(Array.prototype, 'random', {value: function(item) {
|
||||
return this[ Math.floor(Math.random() * this.length) ];
|
||||
}});
|
||||
|
||||
Function.prototype.bind = Function.prototype.bind || function (oThis) {
|
||||
if( typeof this !== "function" ) {
|
||||
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
|
||||
}
|
||||
|
||||
var aArgs = Array.prototype.slice.call(arguments, 1),
|
||||
fToBind = this,
|
||||
fNOP = function () {},
|
||||
fBound = function () {
|
||||
return fToBind.apply(
|
||||
(this instanceof fNOP && oThis ? this : oThis),
|
||||
aArgs.concat(Array.prototype.slice.call(arguments))
|
||||
);
|
||||
};
|
||||
|
||||
fNOP.prototype = this.prototype;
|
||||
fBound.prototype = new fNOP();
|
||||
|
||||
return fBound;
|
||||
};
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// ig Namespace
|
||||
|
||||
window.ig = {
|
||||
game: null,
|
||||
debug: null,
|
||||
version: '1.24',
|
||||
global: window,
|
||||
modules: {},
|
||||
resources: [],
|
||||
ready: false,
|
||||
baked: false,
|
||||
nocache: '',
|
||||
ua: {},
|
||||
prefix: (window.ImpactPrefix || ''),
|
||||
lib: 'lib/',
|
||||
|
||||
_current: null,
|
||||
_loadQueue: [],
|
||||
_waitForOnload: 0,
|
||||
|
||||
|
||||
$: function( selector ) {
|
||||
return selector.charAt(0) == '#'
|
||||
? document.getElementById( selector.substr(1) )
|
||||
: document.getElementsByTagName( selector );
|
||||
},
|
||||
|
||||
|
||||
$new: function( name ) {
|
||||
return document.createElement( name );
|
||||
},
|
||||
|
||||
|
||||
copy: function( object ) {
|
||||
if(
|
||||
!object || typeof(object) != 'object' ||
|
||||
object instanceof HTMLElement ||
|
||||
object instanceof ig.Class
|
||||
) {
|
||||
return object;
|
||||
}
|
||||
else if( object instanceof Array ) {
|
||||
var c = [];
|
||||
for( var i = 0, l = object.length; i < l; i++) {
|
||||
c[i] = ig.copy(object[i]);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
else {
|
||||
var c = {};
|
||||
for( var i in object ) {
|
||||
c[i] = ig.copy(object[i]);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
merge: function( original, extended ) {
|
||||
for( var key in extended ) {
|
||||
var ext = extended[key];
|
||||
if(
|
||||
typeof(ext) != 'object' ||
|
||||
ext instanceof HTMLElement ||
|
||||
ext instanceof ig.Class ||
|
||||
ext === null
|
||||
) {
|
||||
original[key] = ext;
|
||||
}
|
||||
else {
|
||||
if( !original[key] || typeof(original[key]) != 'object' ) {
|
||||
original[key] = (ext instanceof Array) ? [] : {};
|
||||
}
|
||||
ig.merge( original[key], ext );
|
||||
}
|
||||
}
|
||||
return original;
|
||||
},
|
||||
|
||||
|
||||
ksort: function( obj ) {
|
||||
if( !obj || typeof(obj) != 'object' ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
var keys = [], values = [];
|
||||
for( var i in obj ) {
|
||||
keys.push(i);
|
||||
}
|
||||
|
||||
keys.sort();
|
||||
for( var i = 0; i < keys.length; i++ ) {
|
||||
values.push( obj[keys[i]] );
|
||||
}
|
||||
|
||||
return values;
|
||||
},
|
||||
|
||||
// Ah, yes. I love vendor prefixes. So much fun!
|
||||
setVendorAttribute: function( el, attr, val ) {
|
||||
var uc = attr.charAt(0).toUpperCase() + attr.substr(1);
|
||||
el[attr] = el['ms'+uc] = el['moz'+uc] = el['webkit'+uc] = el['o'+uc] = val;
|
||||
},
|
||||
|
||||
|
||||
getVendorAttribute: function( el, attr ) {
|
||||
var uc = attr.charAt(0).toUpperCase() + attr.substr(1);
|
||||
return el[attr] || el['ms'+uc] || el['moz'+uc] || el['webkit'+uc] || el['o'+uc];
|
||||
},
|
||||
|
||||
|
||||
normalizeVendorAttribute: function( el, attr ) {
|
||||
var prefixedVal = ig.getVendorAttribute( el, attr );
|
||||
if( !el[attr] && prefixedVal ) {
|
||||
el[attr] = prefixedVal;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// This function normalizes getImageData to extract the real, actual
|
||||
// pixels from an image. The naive method recently failed on retina
|
||||
// devices with a backgingStoreRatio != 1
|
||||
getImagePixels: function( image, x, y, width, height ) {
|
||||
var canvas = ig.$new('canvas');
|
||||
canvas.width = image.width;
|
||||
canvas.height = image.height;
|
||||
var ctx = canvas.getContext('2d');
|
||||
|
||||
// Try to draw pixels as accurately as possible
|
||||
ig.System.SCALE.CRISP(canvas, ctx);
|
||||
|
||||
var ratio = ig.getVendorAttribute( ctx, 'backingStorePixelRatio' ) || 1;
|
||||
ig.normalizeVendorAttribute( ctx, 'getImageDataHD' );
|
||||
|
||||
var realWidth = image.width / ratio,
|
||||
realHeight = image.height / ratio;
|
||||
|
||||
canvas.width = Math.ceil( realWidth );
|
||||
canvas.height = Math.ceil( realHeight );
|
||||
|
||||
ctx.drawImage( image, 0, 0, realWidth, realHeight );
|
||||
|
||||
return (ratio === 1)
|
||||
? ctx.getImageData( x, y, width, height )
|
||||
: ctx.getImageDataHD( x, y, width, height );
|
||||
},
|
||||
|
||||
|
||||
module: function( name ) {
|
||||
if( ig._current ) {
|
||||
throw( "Module '"+ig._current.name+"' defines nothing" );
|
||||
}
|
||||
if( ig.modules[name] && ig.modules[name].body ) {
|
||||
throw( "Module '"+name+"' is already defined" );
|
||||
}
|
||||
|
||||
ig._current = {name: name, requires: [], loaded: false, body: null};
|
||||
ig.modules[name] = ig._current;
|
||||
ig._loadQueue.push(ig._current);
|
||||
return ig;
|
||||
},
|
||||
|
||||
|
||||
requires: function() {
|
||||
ig._current.requires = Array.prototype.slice.call(arguments);
|
||||
return ig;
|
||||
},
|
||||
|
||||
|
||||
defines: function( body ) {
|
||||
ig._current.body = body;
|
||||
ig._current = null;
|
||||
ig._initDOMReady();
|
||||
},
|
||||
|
||||
|
||||
addResource: function( resource ) {
|
||||
ig.resources.push( resource );
|
||||
},
|
||||
|
||||
|
||||
setNocache: function( set ) {
|
||||
ig.nocache = set
|
||||
? '?' + Date.now()
|
||||
: '';
|
||||
},
|
||||
|
||||
|
||||
// Stubs for ig.Debug
|
||||
log: function() {},
|
||||
assert: function( condition, msg ) {},
|
||||
show: function( name, number ) {},
|
||||
mark: function( msg, color ) {},
|
||||
|
||||
|
||||
_loadScript: function( name, requiredFrom ) {
|
||||
ig.modules[name] = {name: name, requires:[], loaded: false, body: null};
|
||||
ig._waitForOnload++;
|
||||
|
||||
var path = ig.prefix + ig.lib + name.replace(/\./g, '/') + '.js' + ig.nocache;
|
||||
var script = ig.$new('script');
|
||||
script.type = 'text/javascript';
|
||||
script.src = path;
|
||||
script.onload = function() {
|
||||
ig._waitForOnload--;
|
||||
ig._execModules();
|
||||
};
|
||||
script.onerror = function() {
|
||||
throw(
|
||||
'Failed to load module '+name+' at ' + path + ' ' +
|
||||
'required from ' + requiredFrom
|
||||
);
|
||||
};
|
||||
ig.$('head')[0].appendChild(script);
|
||||
},
|
||||
|
||||
|
||||
_execModules: function() {
|
||||
var modulesLoaded = false;
|
||||
for( var i = 0; i < ig._loadQueue.length; i++ ) {
|
||||
var m = ig._loadQueue[i];
|
||||
var dependenciesLoaded = true;
|
||||
|
||||
for( var j = 0; j < m.requires.length; j++ ) {
|
||||
var name = m.requires[j];
|
||||
if( !ig.modules[name] ) {
|
||||
dependenciesLoaded = false;
|
||||
ig._loadScript( name, m.name );
|
||||
}
|
||||
else if( !ig.modules[name].loaded ) {
|
||||
dependenciesLoaded = false;
|
||||
}
|
||||
}
|
||||
|
||||
if( dependenciesLoaded && m.body ) {
|
||||
ig._loadQueue.splice(i, 1);
|
||||
m.loaded = true;
|
||||
m.body();
|
||||
modulesLoaded = true;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
if( modulesLoaded ) {
|
||||
ig._execModules();
|
||||
}
|
||||
|
||||
// No modules executed, no more files to load but loadQueue not empty?
|
||||
// Must be some unresolved dependencies!
|
||||
else if( !ig.baked && ig._waitForOnload == 0 && ig._loadQueue.length != 0 ) {
|
||||
var unresolved = [];
|
||||
for( var i = 0; i < ig._loadQueue.length; i++ ) {
|
||||
|
||||
// Which dependencies aren't loaded?
|
||||
var unloaded = [];
|
||||
var requires = ig._loadQueue[i].requires;
|
||||
for( var j = 0; j < requires.length; j++ ) {
|
||||
var m = ig.modules[ requires[j] ];
|
||||
if( !m || !m.loaded ) {
|
||||
unloaded.push( requires[j] );
|
||||
}
|
||||
}
|
||||
unresolved.push( ig._loadQueue[i].name + ' (requires: ' + unloaded.join(', ') + ')');
|
||||
}
|
||||
|
||||
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')
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
_DOMReady: function() {
|
||||
if( !ig.modules['dom.ready'].loaded ) {
|
||||
if ( !document.body ) {
|
||||
return setTimeout( ig._DOMReady, 13 );
|
||||
}
|
||||
ig.modules['dom.ready'].loaded = true;
|
||||
ig._waitForOnload--;
|
||||
ig._execModules();
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
|
||||
|
||||
_boot: function() {
|
||||
if( document.location.href.match(/\?nocache/) ) {
|
||||
ig.setNocache( true );
|
||||
}
|
||||
|
||||
// Probe user agent string
|
||||
ig.ua.pixelRatio = window.devicePixelRatio || 1;
|
||||
ig.ua.viewport = {
|
||||
width: window.innerWidth,
|
||||
height: window.innerHeight
|
||||
};
|
||||
ig.ua.screen = {
|
||||
width: window.screen.availWidth * ig.ua.pixelRatio,
|
||||
height: window.screen.availHeight * ig.ua.pixelRatio
|
||||
};
|
||||
|
||||
ig.ua.iPhone = /iPhone/i.test(navigator.userAgent);
|
||||
ig.ua.iPhone4 = (ig.ua.iPhone && ig.ua.pixelRatio == 2);
|
||||
ig.ua.iPad = /iPad/i.test(navigator.userAgent);
|
||||
ig.ua.android = /android/i.test(navigator.userAgent);
|
||||
ig.ua.winPhone = /Windows Phone/i.test(navigator.userAgent);
|
||||
ig.ua.iOS = ig.ua.iPhone || ig.ua.iPad;
|
||||
ig.ua.mobile = ig.ua.iOS || ig.ua.android || ig.ua.winPhone || /mobile/i.test(navigator.userAgent);
|
||||
ig.ua.touchDevice = (('ontouchstart' in window) || (window.navigator.msMaxTouchPoints));
|
||||
},
|
||||
|
||||
|
||||
_initDOMReady: function() {
|
||||
if( ig.modules['dom.ready'] ) {
|
||||
ig._execModules();
|
||||
return;
|
||||
}
|
||||
|
||||
ig._boot();
|
||||
|
||||
|
||||
ig.modules['dom.ready'] = { requires: [], loaded: false, body: null };
|
||||
ig._waitForOnload++;
|
||||
if ( document.readyState === 'complete' ) {
|
||||
ig._DOMReady();
|
||||
}
|
||||
else {
|
||||
document.addEventListener( 'DOMContentLoaded', ig._DOMReady, false );
|
||||
window.addEventListener( 'load', ig._DOMReady, false );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Provide ig.setAnimation and ig.clearAnimation as a compatible way to use
|
||||
// requestAnimationFrame if available or setInterval otherwise
|
||||
|
||||
// Use requestAnimationFrame if available
|
||||
ig.normalizeVendorAttribute( window, 'requestAnimationFrame' );
|
||||
if( window.requestAnimationFrame ) {
|
||||
var next = 1,
|
||||
anims = {};
|
||||
|
||||
window.ig.setAnimation = function( callback, element ) {
|
||||
var current = next++;
|
||||
anims[current] = true;
|
||||
|
||||
var animate = function() {
|
||||
if( !anims[current] ) { return; } // deleted?
|
||||
window.requestAnimationFrame( animate, element );
|
||||
callback();
|
||||
};
|
||||
window.requestAnimationFrame( animate, element );
|
||||
return current;
|
||||
};
|
||||
|
||||
window.ig.clearAnimation = function( id ) {
|
||||
delete anims[id];
|
||||
};
|
||||
}
|
||||
|
||||
// [set/clear]Interval fallback
|
||||
else {
|
||||
window.ig.setAnimation = function( callback, element ) {
|
||||
return window.setInterval( callback, 1000/60 );
|
||||
};
|
||||
window.ig.clearAnimation = function( id ) {
|
||||
window.clearInterval( id );
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Class object based on John Resigs code; inspired by base2 and Prototype
|
||||
// http://ejohn.org/blog/simple-javascript-inheritance/
|
||||
|
||||
var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\bparent\b/ : /.*/;
|
||||
var lastClassId = 0;
|
||||
|
||||
window.ig.Class = function(){};
|
||||
var inject = function(prop) {
|
||||
var proto = this.prototype;
|
||||
var parent = {};
|
||||
for( var name in prop ) {
|
||||
if(
|
||||
typeof(prop[name]) == "function" &&
|
||||
typeof(proto[name]) == "function" &&
|
||||
fnTest.test(prop[name])
|
||||
) {
|
||||
parent[name] = proto[name]; // save original function
|
||||
proto[name] = (function(name, fn){
|
||||
return function() {
|
||||
var tmp = this.parent;
|
||||
this.parent = parent[name];
|
||||
var ret = fn.apply(this, arguments);
|
||||
this.parent = tmp;
|
||||
return ret;
|
||||
};
|
||||
})( name, prop[name] );
|
||||
}
|
||||
else {
|
||||
proto[name] = prop[name];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
window.ig.Class.extend = function(prop) {
|
||||
var parent = this.prototype;
|
||||
|
||||
initializing = true;
|
||||
var prototype = new this();
|
||||
initializing = false;
|
||||
|
||||
for( var name in prop ) {
|
||||
if(
|
||||
typeof(prop[name]) == "function" &&
|
||||
typeof(parent[name]) == "function" &&
|
||||
fnTest.test(prop[name])
|
||||
) {
|
||||
prototype[name] = (function(name, fn){
|
||||
return function() {
|
||||
var tmp = this.parent;
|
||||
this.parent = parent[name];
|
||||
var ret = fn.apply(this, arguments);
|
||||
this.parent = tmp;
|
||||
return ret;
|
||||
};
|
||||
})( name, prop[name] );
|
||||
}
|
||||
else {
|
||||
prototype[name] = prop[name];
|
||||
}
|
||||
}
|
||||
|
||||
function Class() {
|
||||
if( !initializing ) {
|
||||
|
||||
// If this class has a staticInstantiate method, invoke it
|
||||
// and check if we got something back. If not, the normal
|
||||
// constructor (init) is called.
|
||||
if( this.staticInstantiate ) {
|
||||
var obj = this.staticInstantiate.apply(this, arguments);
|
||||
if( obj ) {
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
for( var p in this ) {
|
||||
if( typeof(this[p]) == 'object' ) {
|
||||
this[p] = ig.copy(this[p]); // deep copy!
|
||||
}
|
||||
}
|
||||
if( this.init ) {
|
||||
this.init.apply(this, arguments);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
Class.prototype = prototype;
|
||||
Class.prototype.constructor = Class;
|
||||
Class.extend = window.ig.Class.extend;
|
||||
Class.inject = inject;
|
||||
Class.classId = prototype.classId = ++lastClassId;
|
||||
|
||||
return Class;
|
||||
};
|
||||
|
||||
// Merge the ImpactMixin - if present - into the 'ig' namespace. This gives other
|
||||
// code the chance to modify 'ig' before it's doing any work.
|
||||
if( window.ImpactMixin ) {
|
||||
ig.merge(ig, window.ImpactMixin);
|
||||
}
|
||||
|
||||
})(window);
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// The main() function creates the system, input, sound and game objects,
|
||||
// creates a preloader and starts the run loop
|
||||
|
||||
ig.module(
|
||||
'impact.impact'
|
||||
)
|
||||
.requires(
|
||||
'dom.ready',
|
||||
'impact.loader',
|
||||
'impact.system',
|
||||
'impact.input',
|
||||
'impact.sound'
|
||||
)
|
||||
.defines(function(){ "use strict";
|
||||
|
||||
ig.main = function( canvasId, gameClass, fps, width, height, scale, loaderClass ) {
|
||||
ig.system = new ig.System( canvasId, fps, width, height, scale || 1 );
|
||||
ig.input = new ig.Input();
|
||||
ig.soundManager = new ig.SoundManager();
|
||||
ig.music = new ig.Music();
|
||||
ig.ready = true;
|
||||
|
||||
var loader = new (loaderClass || ig.Loader)( gameClass, ig.resources );
|
||||
loader.load();
|
||||
};
|
||||
|
||||
});
|
||||
@@ -0,0 +1,321 @@
|
||||
ig.module(
|
||||
'impact.input'
|
||||
)
|
||||
.defines(function(){ "use strict";
|
||||
|
||||
ig.KEY = {
|
||||
'MOUSE1': -1,
|
||||
'MOUSE2': -3,
|
||||
'MWHEEL_UP': -4,
|
||||
'MWHEEL_DOWN': -5,
|
||||
|
||||
'BACKSPACE': 8,
|
||||
'TAB': 9,
|
||||
'ENTER': 13,
|
||||
'PAUSE': 19,
|
||||
'CAPS': 20,
|
||||
'ESC': 27,
|
||||
'SPACE': 32,
|
||||
'PAGE_UP': 33,
|
||||
'PAGE_DOWN': 34,
|
||||
'END': 35,
|
||||
'HOME': 36,
|
||||
'LEFT_ARROW': 37,
|
||||
'UP_ARROW': 38,
|
||||
'RIGHT_ARROW': 39,
|
||||
'DOWN_ARROW': 40,
|
||||
'INSERT': 45,
|
||||
'DELETE': 46,
|
||||
'_0': 48,
|
||||
'_1': 49,
|
||||
'_2': 50,
|
||||
'_3': 51,
|
||||
'_4': 52,
|
||||
'_5': 53,
|
||||
'_6': 54,
|
||||
'_7': 55,
|
||||
'_8': 56,
|
||||
'_9': 57,
|
||||
'A': 65,
|
||||
'B': 66,
|
||||
'C': 67,
|
||||
'D': 68,
|
||||
'E': 69,
|
||||
'F': 70,
|
||||
'G': 71,
|
||||
'H': 72,
|
||||
'I': 73,
|
||||
'J': 74,
|
||||
'K': 75,
|
||||
'L': 76,
|
||||
'M': 77,
|
||||
'N': 78,
|
||||
'O': 79,
|
||||
'P': 80,
|
||||
'Q': 81,
|
||||
'R': 82,
|
||||
'S': 83,
|
||||
'T': 84,
|
||||
'U': 85,
|
||||
'V': 86,
|
||||
'W': 87,
|
||||
'X': 88,
|
||||
'Y': 89,
|
||||
'Z': 90,
|
||||
'NUMPAD_0': 96,
|
||||
'NUMPAD_1': 97,
|
||||
'NUMPAD_2': 98,
|
||||
'NUMPAD_3': 99,
|
||||
'NUMPAD_4': 100,
|
||||
'NUMPAD_5': 101,
|
||||
'NUMPAD_6': 102,
|
||||
'NUMPAD_7': 103,
|
||||
'NUMPAD_8': 104,
|
||||
'NUMPAD_9': 105,
|
||||
'MULTIPLY': 106,
|
||||
'ADD': 107,
|
||||
'SUBSTRACT': 109,
|
||||
'DECIMAL': 110,
|
||||
'DIVIDE': 111,
|
||||
'F1': 112,
|
||||
'F2': 113,
|
||||
'F3': 114,
|
||||
'F4': 115,
|
||||
'F5': 116,
|
||||
'F6': 117,
|
||||
'F7': 118,
|
||||
'F8': 119,
|
||||
'F9': 120,
|
||||
'F10': 121,
|
||||
'F11': 122,
|
||||
'F12': 123,
|
||||
'SHIFT': 16,
|
||||
'CTRL': 17,
|
||||
'ALT': 18,
|
||||
'PLUS': 187,
|
||||
'COMMA': 188,
|
||||
'MINUS': 189,
|
||||
'PERIOD': 190
|
||||
};
|
||||
|
||||
|
||||
ig.Input = ig.Class.extend({
|
||||
bindings: {},
|
||||
actions: {},
|
||||
presses: {},
|
||||
locks: {},
|
||||
delayedKeyup: {},
|
||||
|
||||
isUsingMouse: false,
|
||||
isUsingKeyboard: false,
|
||||
isUsingAccelerometer: false,
|
||||
mouse: {x: 0, y: 0},
|
||||
accel: {x: 0, y: 0, z: 0},
|
||||
|
||||
|
||||
initMouse: function() {
|
||||
if( this.isUsingMouse ) { return; }
|
||||
this.isUsingMouse = true;
|
||||
var mouseWheelBound = this.mousewheel.bind(this);
|
||||
ig.system.canvas.addEventListener('mousewheel', mouseWheelBound, false );
|
||||
ig.system.canvas.addEventListener('DOMMouseScroll', mouseWheelBound, false );
|
||||
|
||||
ig.system.canvas.addEventListener('contextmenu', this.contextmenu.bind(this), false );
|
||||
ig.system.canvas.addEventListener('mousedown', this.keydown.bind(this), false );
|
||||
ig.system.canvas.addEventListener('mouseup', this.keyup.bind(this), false );
|
||||
ig.system.canvas.addEventListener('mousemove', this.mousemove.bind(this), false );
|
||||
|
||||
if( ig.ua.touchDevice ) {
|
||||
// Standard
|
||||
ig.system.canvas.addEventListener('touchstart', this.keydown.bind(this), false );
|
||||
ig.system.canvas.addEventListener('touchend', this.keyup.bind(this), false );
|
||||
ig.system.canvas.addEventListener('touchmove', this.mousemove.bind(this), false );
|
||||
|
||||
// MS
|
||||
ig.system.canvas.addEventListener('MSPointerDown', this.keydown.bind(this), false );
|
||||
ig.system.canvas.addEventListener('MSPointerUp', this.keyup.bind(this), false );
|
||||
ig.system.canvas.addEventListener('MSPointerMove', this.mousemove.bind(this), false );
|
||||
ig.system.canvas.style.msTouchAction = 'none';
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
initKeyboard: function() {
|
||||
if( this.isUsingKeyboard ) { return; }
|
||||
this.isUsingKeyboard = true;
|
||||
window.addEventListener('keydown', this.keydown.bind(this), false );
|
||||
window.addEventListener('keyup', this.keyup.bind(this), false );
|
||||
},
|
||||
|
||||
|
||||
initAccelerometer: function() {
|
||||
if( this.isUsingAccelerometer ) { return; }
|
||||
this.isUsingAccelerometer = true;
|
||||
window.addEventListener('devicemotion', this.devicemotion.bind(this), false );
|
||||
},
|
||||
|
||||
|
||||
mousewheel: function( event ) {
|
||||
var delta = event.wheelDelta ? event.wheelDelta : (event.detail * -1);
|
||||
var code = delta > 0 ? ig.KEY.MWHEEL_UP : ig.KEY.MWHEEL_DOWN;
|
||||
var action = this.bindings[code];
|
||||
if( action ) {
|
||||
this.actions[action] = true;
|
||||
this.presses[action] = true;
|
||||
this.delayedKeyup[action] = true;
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
mousemove: function( event ) {
|
||||
var internalWidth = parseInt(ig.system.canvas.offsetWidth) || ig.system.realWidth;
|
||||
var scale = ig.system.scale * (internalWidth / ig.system.realWidth);
|
||||
|
||||
var pos = {left: 0, top: 0};
|
||||
if( ig.system.canvas.getBoundingClientRect ) {
|
||||
pos = ig.system.canvas.getBoundingClientRect();
|
||||
}
|
||||
|
||||
var ev = event.touches ? event.touches[0] : event;
|
||||
this.mouse.x = (ev.clientX - pos.left) / scale;
|
||||
this.mouse.y = (ev.clientY - pos.top) / scale;
|
||||
},
|
||||
|
||||
|
||||
contextmenu: function( event ) {
|
||||
if( this.bindings[ig.KEY.MOUSE2] ) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
keydown: function( event ) {
|
||||
var tag = event.target.tagName;
|
||||
if( tag == 'INPUT' || tag == 'TEXTAREA' ) { return; }
|
||||
|
||||
var code = event.type == 'keydown'
|
||||
? event.keyCode
|
||||
: (event.button == 2 ? ig.KEY.MOUSE2 : ig.KEY.MOUSE1);
|
||||
|
||||
// Focus window element for mouse clicks. Prevents issues when
|
||||
// running the game in an iframe.
|
||||
if( code < 0 && !ig.ua.mobile ) {
|
||||
window.focus();
|
||||
}
|
||||
|
||||
if( event.type == 'touchstart' || event.type == 'mousedown' ) {
|
||||
this.mousemove( event );
|
||||
}
|
||||
|
||||
var action = this.bindings[code];
|
||||
if( action ) {
|
||||
this.actions[action] = true;
|
||||
if( !this.locks[action] ) {
|
||||
this.presses[action] = true;
|
||||
this.locks[action] = true;
|
||||
}
|
||||
event.preventDefault();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
keyup: function( event ) {
|
||||
var tag = event.target.tagName;
|
||||
if( tag == 'INPUT' || tag == 'TEXTAREA' ) { return; }
|
||||
|
||||
var code = event.type == 'keyup'
|
||||
? event.keyCode
|
||||
: (event.button == 2 ? ig.KEY.MOUSE2 : ig.KEY.MOUSE1);
|
||||
|
||||
var action = this.bindings[code];
|
||||
if( action ) {
|
||||
this.delayedKeyup[action] = true;
|
||||
event.preventDefault();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
devicemotion: function( event ) {
|
||||
this.accel = event.accelerationIncludingGravity;
|
||||
},
|
||||
|
||||
|
||||
bind: function( key, action ) {
|
||||
if( key < 0 ) { this.initMouse(); }
|
||||
else if( key > 0 ) { this.initKeyboard(); }
|
||||
this.bindings[key] = action;
|
||||
},
|
||||
|
||||
|
||||
bindTouch: function( selector, action ) {
|
||||
var element = ig.$( selector );
|
||||
|
||||
var that = this;
|
||||
element.addEventListener('touchstart', function(ev) {that.touchStart( ev, action );}, false);
|
||||
element.addEventListener('touchend', function(ev) {that.touchEnd( ev, action );}, false);
|
||||
element.addEventListener('MSPointerDown', function(ev) {that.touchStart( ev, action );}, false);
|
||||
element.addEventListener('MSPointerUp', function(ev) {that.touchEnd( ev, action );}, false);
|
||||
},
|
||||
|
||||
|
||||
unbind: function( key ) {
|
||||
var action = this.bindings[key];
|
||||
this.delayedKeyup[action] = true;
|
||||
|
||||
this.bindings[key] = null;
|
||||
},
|
||||
|
||||
|
||||
unbindAll: function() {
|
||||
this.bindings = {};
|
||||
this.actions = {};
|
||||
this.presses = {};
|
||||
this.locks = {};
|
||||
this.delayedKeyup = {};
|
||||
},
|
||||
|
||||
|
||||
state: function( action ) {
|
||||
return this.actions[action];
|
||||
},
|
||||
|
||||
|
||||
pressed: function( action ) {
|
||||
return this.presses[action];
|
||||
},
|
||||
|
||||
released: function( action ) {
|
||||
return !!this.delayedKeyup[action];
|
||||
},
|
||||
|
||||
clearPressed: function() {
|
||||
for( var action in this.delayedKeyup ) {
|
||||
this.actions[action] = false;
|
||||
this.locks[action] = false;
|
||||
}
|
||||
this.delayedKeyup = {};
|
||||
this.presses = {};
|
||||
},
|
||||
|
||||
touchStart: function( event, action ) {
|
||||
this.actions[action] = true;
|
||||
this.presses[action] = true;
|
||||
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
return false;
|
||||
},
|
||||
|
||||
|
||||
touchEnd: function( event, action ) {
|
||||
this.delayedKeyup[action] = true;
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,101 @@
|
||||
ig.module(
|
||||
'impact.loader'
|
||||
)
|
||||
.requires(
|
||||
'impact.image',
|
||||
'impact.font',
|
||||
'impact.sound'
|
||||
)
|
||||
.defines(function(){ "use strict";
|
||||
|
||||
ig.Loader = ig.Class.extend({
|
||||
resources: [],
|
||||
|
||||
gameClass: null,
|
||||
status: 0,
|
||||
done: false,
|
||||
|
||||
_unloaded: [],
|
||||
_drawStatus: 0,
|
||||
_intervalId: 0,
|
||||
_loadCallbackBound: null,
|
||||
|
||||
|
||||
init: function( gameClass, resources ) {
|
||||
this.gameClass = gameClass;
|
||||
this.resources = resources;
|
||||
this._loadCallbackBound = this._loadCallback.bind(this);
|
||||
|
||||
for( var i = 0; i < this.resources.length; i++ ) {
|
||||
this._unloaded.push( this.resources[i].path );
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
load: function() {
|
||||
ig.system.clear( '#000' );
|
||||
|
||||
if( !this.resources.length ) {
|
||||
this.end();
|
||||
return;
|
||||
}
|
||||
|
||||
for( var i = 0; i < this.resources.length; i++ ) {
|
||||
this.loadResource( this.resources[i] );
|
||||
}
|
||||
this._intervalId = setInterval( this.draw.bind(this), 16 );
|
||||
},
|
||||
|
||||
|
||||
loadResource: function( res ) {
|
||||
res.load( this._loadCallbackBound );
|
||||
},
|
||||
|
||||
|
||||
end: function() {
|
||||
if( this.done ) { return; }
|
||||
|
||||
this.done = true;
|
||||
clearInterval( this._intervalId );
|
||||
ig.system.setGame( this.gameClass );
|
||||
},
|
||||
|
||||
|
||||
draw: function() {
|
||||
this._drawStatus += (this.status - this._drawStatus)/5;
|
||||
var s = ig.system.scale;
|
||||
var w = ig.system.width * 0.6;
|
||||
var h = ig.system.height * 0.1;
|
||||
var x = ig.system.width * 0.5-w/2;
|
||||
var y = ig.system.height * 0.5-h/2;
|
||||
|
||||
ig.system.context.fillStyle = '#000';
|
||||
ig.system.context.fillRect( 0, 0, 480, 320 );
|
||||
|
||||
ig.system.context.fillStyle = '#fff';
|
||||
ig.system.context.fillRect( x*s, y*s, w*s, h*s );
|
||||
|
||||
ig.system.context.fillStyle = '#000';
|
||||
ig.system.context.fillRect( x*s+s, y*s+s, w*s-s-s, h*s-s-s );
|
||||
|
||||
ig.system.context.fillStyle = '#fff';
|
||||
ig.system.context.fillRect( x*s, y*s, w*s*this._drawStatus, h*s );
|
||||
},
|
||||
|
||||
|
||||
_loadCallback: function( path, status ) {
|
||||
if( status ) {
|
||||
this._unloaded.erase( path );
|
||||
}
|
||||
else {
|
||||
throw( 'Failed to load resource: ' + path );
|
||||
}
|
||||
|
||||
this.status = 1 - (this._unloaded.length / this.resources.length);
|
||||
if( this._unloaded.length == 0 ) { // all done?
|
||||
setTimeout( this.end.bind(this), 250 );
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,52 @@
|
||||
ig.module(
|
||||
'impact.map'
|
||||
)
|
||||
.defines(function(){ "use strict";
|
||||
|
||||
ig.Map = ig.Class.extend({
|
||||
tilesize: 8,
|
||||
width: 1,
|
||||
height: 1,
|
||||
data: [[]],
|
||||
name: null,
|
||||
|
||||
|
||||
init: function( tilesize, data ) {
|
||||
this.tilesize = tilesize;
|
||||
this.data = data;
|
||||
this.height = data.length;
|
||||
this.width = data[0].length;
|
||||
|
||||
this.pxWidth = this.width * this.tilesize;
|
||||
this.pxHeight = this.height * this.tilesize;
|
||||
},
|
||||
|
||||
|
||||
getTile: function( x, y ) {
|
||||
var tx = Math.floor( x / this.tilesize );
|
||||
var ty = Math.floor( y / this.tilesize );
|
||||
if(
|
||||
(tx >= 0 && tx < this.width) &&
|
||||
(ty >= 0 && ty < this.height)
|
||||
) {
|
||||
return this.data[ty][tx];
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
setTile: function( x, y, tile ) {
|
||||
var tx = Math.floor( x / this.tilesize );
|
||||
var ty = Math.floor( y / this.tilesize );
|
||||
if(
|
||||
(tx >= 0 && tx < this.width) &&
|
||||
(ty >= 0 && ty < this.height)
|
||||
) {
|
||||
this.data[ty][tx] = tile;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,516 @@
|
||||
ig.module(
|
||||
'impact.sound'
|
||||
)
|
||||
.defines(function(){ "use strict";
|
||||
|
||||
ig.SoundManager = ig.Class.extend({
|
||||
clips: {},
|
||||
volume: 1,
|
||||
format: null,
|
||||
|
||||
init: function() {
|
||||
// Quick sanity check if the Browser supports the Audio tag
|
||||
if( !ig.Sound.enabled || !window.Audio ) {
|
||||
ig.Sound.enabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Probe sound formats and determine the file extension to load
|
||||
var probe = new Audio();
|
||||
for( var i = 0; i < ig.Sound.use.length; i++ ) {
|
||||
var format = ig.Sound.use[i];
|
||||
if( probe.canPlayType(format.mime) ) {
|
||||
this.format = format;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// No compatible format found? -> Disable sound
|
||||
if( !this.format ) {
|
||||
ig.Sound.enabled = false;
|
||||
}
|
||||
|
||||
// Create WebAudio Context
|
||||
if( ig.Sound.enabled && ig.Sound.useWebAudio ) {
|
||||
this.audioContext = new AudioContext();
|
||||
this.boundWebAudioUnlock = this.unlockWebAudio.bind(this);
|
||||
document.addEventListener('touchstart', this.boundWebAudioUnlock, false);
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
unlockWebAudio: function() {
|
||||
document.removeEventListener('touchstart', this.boundWebAudioUnlock, false);
|
||||
|
||||
// create empty buffer
|
||||
var buffer = this.audioContext.createBuffer(1, 1, 22050);
|
||||
var source = this.audioContext.createBufferSource();
|
||||
source.buffer = buffer;
|
||||
|
||||
source.connect(this.audioContext.destination);
|
||||
source.start(0);
|
||||
},
|
||||
|
||||
load: function( path, multiChannel, loadCallback ) {
|
||||
if( multiChannel && ig.Sound.useWebAudio ) {
|
||||
// Requested as Multichannel and we're using WebAudio?
|
||||
return this.loadWebAudio( path, multiChannel, loadCallback );
|
||||
}
|
||||
else {
|
||||
// Oldschool HTML5 Audio - always used for Music
|
||||
return this.loadHTML5Audio( path, multiChannel, loadCallback );
|
||||
}
|
||||
},
|
||||
|
||||
loadWebAudio: function( path, multiChannel, loadCallback ) {
|
||||
// Path to the soundfile with the right extension (.ogg or .mp3)
|
||||
var realPath = ig.prefix + path.replace(/[^\.]+$/, this.format.ext) + ig.nocache;
|
||||
|
||||
if( this.clips[path] ) {
|
||||
return this.clips[path];
|
||||
}
|
||||
|
||||
var audioSource = new ig.Sound.WebAudioSource()
|
||||
this.clips[path] = audioSource;
|
||||
|
||||
var request = new XMLHttpRequest();
|
||||
request.open('GET', realPath, true);
|
||||
request.responseType = 'arraybuffer';
|
||||
|
||||
|
||||
var that = this;
|
||||
request.onload = function(ev) {
|
||||
that.audioContext.decodeAudioData(request.response,
|
||||
function(buffer) {
|
||||
audioSource.buffer = buffer;
|
||||
loadCallback( path, true, ev );
|
||||
},
|
||||
function(ev) {
|
||||
loadCallback( path, false, ev );
|
||||
}
|
||||
);
|
||||
};
|
||||
request.onerror = function(ev) {
|
||||
loadCallback( path, false, ev );
|
||||
};
|
||||
request.send();
|
||||
|
||||
return audioSource;
|
||||
},
|
||||
|
||||
loadHTML5Audio: function( path, multiChannel, loadCallback ) {
|
||||
|
||||
// Path to the soundfile with the right extension (.ogg or .mp3)
|
||||
var realPath = ig.prefix + path.replace(/[^\.]+$/, this.format.ext) + ig.nocache;
|
||||
|
||||
// Sound file already loaded?
|
||||
if( this.clips[path] ) {
|
||||
// Loaded as WebAudio, but now requested as HTML5 Audio? Probably Music?
|
||||
if( this.clips[path] instanceof ig.Sound.WebAudioSource ) {
|
||||
return this.clips[path];
|
||||
}
|
||||
|
||||
// Only loaded as single channel and now requested as multichannel?
|
||||
if( multiChannel && this.clips[path].length < ig.Sound.channels ) {
|
||||
for( var i = this.clips[path].length; i < ig.Sound.channels; i++ ) {
|
||||
var a = new Audio( realPath );
|
||||
a.load();
|
||||
this.clips[path].push( a );
|
||||
}
|
||||
}
|
||||
return this.clips[path][0];
|
||||
}
|
||||
|
||||
var clip = new Audio( realPath );
|
||||
if( loadCallback ) {
|
||||
|
||||
// The canplaythrough event is dispatched when the browser determines
|
||||
// that the sound can be played without interuption, provided the
|
||||
// download rate doesn't change.
|
||||
// Mobile browsers stubbornly refuse to preload HTML5, so we simply
|
||||
// ignore the canplaythrough event and immediately "fake" a successful
|
||||
// load callback
|
||||
if( ig.ua.mobile ) {
|
||||
setTimeout(function(){
|
||||
loadCallback( path, true, null );
|
||||
}, 0);
|
||||
}
|
||||
else {
|
||||
clip.addEventListener( 'canplaythrough', function cb(ev){
|
||||
clip.removeEventListener('canplaythrough', cb, false);
|
||||
loadCallback( path, true, ev );
|
||||
}, false );
|
||||
|
||||
clip.addEventListener( 'error', function(ev){
|
||||
loadCallback( path, false, ev );
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
clip.preload = 'auto';
|
||||
clip.load();
|
||||
|
||||
|
||||
this.clips[path] = [clip];
|
||||
if( multiChannel ) {
|
||||
for( var i = 1; i < ig.Sound.channels; i++ ) {
|
||||
var a = new Audio(realPath);
|
||||
a.load();
|
||||
this.clips[path].push( a );
|
||||
}
|
||||
}
|
||||
|
||||
return clip;
|
||||
},
|
||||
|
||||
|
||||
get: function( path ) {
|
||||
// Find and return a channel that is not currently playing
|
||||
var channels = this.clips[path];
|
||||
|
||||
// Is this a WebAudio source? We only ever have one for each Sound
|
||||
if( channels && channels instanceof ig.Sound.WebAudioSource ) {
|
||||
return channels;
|
||||
}
|
||||
|
||||
// Oldschool HTML5 Audio - find a channel that's not currently
|
||||
// playing or, if all are playing, rewind one
|
||||
for( var i = 0, clip; clip = channels[i++]; ) {
|
||||
if( clip.paused || clip.ended ) {
|
||||
if( clip.ended ) {
|
||||
clip.currentTime = 0;
|
||||
}
|
||||
return clip;
|
||||
}
|
||||
}
|
||||
|
||||
// Still here? Pause and rewind the first channel
|
||||
channels[0].pause();
|
||||
channels[0].currentTime = 0;
|
||||
return channels[0];
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
ig.Music = ig.Class.extend({
|
||||
tracks: [],
|
||||
namedTracks: {},
|
||||
currentTrack: null,
|
||||
currentIndex: 0,
|
||||
random: false,
|
||||
|
||||
_volume: 1,
|
||||
_loop: false,
|
||||
_fadeInterval: 0,
|
||||
_fadeTimer: null,
|
||||
_endedCallbackBound: null,
|
||||
|
||||
|
||||
init: function() {
|
||||
this._endedCallbackBound = this._endedCallback.bind(this);
|
||||
|
||||
Object.defineProperty(this,"volume", {
|
||||
get: this.getVolume.bind(this),
|
||||
set: this.setVolume.bind(this)
|
||||
});
|
||||
|
||||
Object.defineProperty(this,"loop", {
|
||||
get: this.getLooping.bind(this),
|
||||
set: this.setLooping.bind(this)
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
add: function( music, name ) {
|
||||
if( !ig.Sound.enabled ) {
|
||||
return;
|
||||
}
|
||||
|
||||
var path = music instanceof ig.Sound ? music.path : music;
|
||||
|
||||
var track = ig.soundManager.load(path, false);
|
||||
|
||||
// Did we get a WebAudio Source? This is suboptimal; Music should be loaded
|
||||
// as HTML5 Audio so it can be streamed
|
||||
if( track instanceof ig.Sound.WebAudioSource ) {
|
||||
// Since this error will likely occour at game start, we stop the game
|
||||
// to not produce any more errors.
|
||||
ig.system.stopRunLoop();
|
||||
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)"
|
||||
);
|
||||
}
|
||||
|
||||
track.loop = this._loop;
|
||||
track.volume = this._volume;
|
||||
track.addEventListener( 'ended', this._endedCallbackBound, false );
|
||||
this.tracks.push( track );
|
||||
|
||||
if( name ) {
|
||||
this.namedTracks[name] = track;
|
||||
}
|
||||
|
||||
if( !this.currentTrack ) {
|
||||
this.currentTrack = track;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
next: function() {
|
||||
if( !this.tracks.length ) { return; }
|
||||
|
||||
this.stop();
|
||||
this.currentIndex = this.random
|
||||
? Math.floor(Math.random() * this.tracks.length)
|
||||
: (this.currentIndex + 1) % this.tracks.length;
|
||||
this.currentTrack = this.tracks[this.currentIndex];
|
||||
this.play();
|
||||
},
|
||||
|
||||
|
||||
pause: function() {
|
||||
if( !this.currentTrack ) { return; }
|
||||
this.currentTrack.pause();
|
||||
},
|
||||
|
||||
|
||||
stop: function() {
|
||||
if( !this.currentTrack ) { return; }
|
||||
this.currentTrack.pause();
|
||||
this.currentTrack.currentTime = 0;
|
||||
},
|
||||
|
||||
|
||||
play: function( name ) {
|
||||
// If a name was provided, stop playing the current track (if any)
|
||||
// and play the named track
|
||||
if( name && this.namedTracks[name] ) {
|
||||
var newTrack = this.namedTracks[name];
|
||||
if( newTrack != this.currentTrack ) {
|
||||
this.stop();
|
||||
this.currentTrack = newTrack;
|
||||
}
|
||||
}
|
||||
else if( !this.currentTrack ) {
|
||||
return;
|
||||
}
|
||||
this.currentTrack.play();
|
||||
},
|
||||
|
||||
|
||||
getLooping: function() {
|
||||
return this._loop;
|
||||
},
|
||||
|
||||
|
||||
setLooping: function( l ) {
|
||||
this._loop = l;
|
||||
for( var i in this.tracks ) {
|
||||
this.tracks[i].loop = l;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
getVolume: function() {
|
||||
return this._volume;
|
||||
},
|
||||
|
||||
|
||||
setVolume: function( v ) {
|
||||
this._volume = v.limit(0,1);
|
||||
for( var i in this.tracks ) {
|
||||
this.tracks[i].volume = this._volume;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
fadeOut: function( time ) {
|
||||
if( !this.currentTrack ) { return; }
|
||||
|
||||
clearInterval( this._fadeInterval );
|
||||
this.fadeTimer = new ig.Timer( time );
|
||||
this._fadeInterval = setInterval( this._fadeStep.bind(this), 50 );
|
||||
},
|
||||
|
||||
|
||||
_fadeStep: function() {
|
||||
var v = this.fadeTimer.delta()
|
||||
.map(-this.fadeTimer.target, 0, 1, 0)
|
||||
.limit( 0, 1 )
|
||||
* this._volume;
|
||||
|
||||
if( v <= 0.01 ) {
|
||||
this.stop();
|
||||
this.currentTrack.volume = this._volume;
|
||||
clearInterval( this._fadeInterval );
|
||||
}
|
||||
else {
|
||||
this.currentTrack.volume = v;
|
||||
}
|
||||
},
|
||||
|
||||
_endedCallback: function() {
|
||||
if( this._loop ) {
|
||||
this.play();
|
||||
}
|
||||
else {
|
||||
this.next();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
ig.Sound = ig.Class.extend({
|
||||
path: '',
|
||||
volume: 1,
|
||||
currentClip: null,
|
||||
multiChannel: true,
|
||||
_loop: false,
|
||||
|
||||
|
||||
init: function( path, multiChannel ) {
|
||||
this.path = path;
|
||||
this.multiChannel = (multiChannel !== false);
|
||||
|
||||
Object.defineProperty(this,"loop", {
|
||||
get: this.getLooping.bind(this),
|
||||
set: this.setLooping.bind(this)
|
||||
});
|
||||
|
||||
this.load();
|
||||
},
|
||||
|
||||
getLooping: function() {
|
||||
return this._loop;
|
||||
},
|
||||
|
||||
setLooping: function( loop ) {
|
||||
this._loop = loop;
|
||||
|
||||
if( this.currentClip ) {
|
||||
this.currentClip.loop = loop;
|
||||
}
|
||||
},
|
||||
|
||||
load: function( loadCallback ) {
|
||||
if( !ig.Sound.enabled ) {
|
||||
if( loadCallback ) {
|
||||
loadCallback( this.path, true );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if( ig.ready ) {
|
||||
ig.soundManager.load( this.path, this.multiChannel, loadCallback );
|
||||
}
|
||||
else {
|
||||
ig.addResource( this );
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
play: function() {
|
||||
if( !ig.Sound.enabled ) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.currentClip = ig.soundManager.get( this.path );
|
||||
this.currentClip.loop = this._loop;
|
||||
this.currentClip.volume = ig.soundManager.volume * this.volume;
|
||||
this.currentClip.play();
|
||||
},
|
||||
|
||||
|
||||
stop: function() {
|
||||
if( this.currentClip ) {
|
||||
this.currentClip.pause();
|
||||
this.currentClip.currentTime = 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
ig.Sound.WebAudioSource = ig.Class.extend({
|
||||
sources: [],
|
||||
gain: null,
|
||||
buffer: null,
|
||||
_loop: false,
|
||||
|
||||
init: function() {
|
||||
this.gain = ig.soundManager.audioContext.createGain();
|
||||
this.gain.connect(ig.soundManager.audioContext.destination);
|
||||
|
||||
Object.defineProperty(this,"loop", {
|
||||
get: this.getLooping.bind(this),
|
||||
set: this.setLooping.bind(this)
|
||||
});
|
||||
|
||||
Object.defineProperty(this,"volume", {
|
||||
get: this.getVolume.bind(this),
|
||||
set: this.setVolume.bind(this)
|
||||
});
|
||||
},
|
||||
|
||||
play: function() {
|
||||
if( !this.buffer ) { return; }
|
||||
var source = ig.soundManager.audioContext.createBufferSource();
|
||||
source.buffer = this.buffer;
|
||||
source.connect(this.gain);
|
||||
source.loop = this._loop;
|
||||
|
||||
// Add this new source to our sources array and remove it again
|
||||
// later when it has finished playing.
|
||||
var that = this;
|
||||
this.sources.push(source);
|
||||
source.onended = function(){ that.sources.erase(source); }
|
||||
|
||||
source.start(0);
|
||||
},
|
||||
|
||||
pause: function() {
|
||||
for( var i = 0; i < this.sources.length; i++ ) {
|
||||
try{
|
||||
this.sources[i].stop();
|
||||
} catch(err){}
|
||||
}
|
||||
},
|
||||
|
||||
getLooping: function() {
|
||||
return this._loop;
|
||||
},
|
||||
|
||||
setLooping: function( loop ) {
|
||||
this._loop = loop;
|
||||
|
||||
for( var i = 0; i < this.sources.length; i++ ) {
|
||||
this.sources[i].loop = loop;
|
||||
}
|
||||
},
|
||||
|
||||
getVolume: function() {
|
||||
return this.gain.gain.value;
|
||||
},
|
||||
|
||||
setVolume: function( volume ) {
|
||||
this.gain.gain.value = volume;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
ig.Sound.FORMAT = {
|
||||
MP3: {ext: 'mp3', mime: 'audio/mpeg'},
|
||||
M4A: {ext: 'm4a', mime: 'audio/mp4; codecs=mp4a'},
|
||||
OGG: {ext: 'ogg', mime: 'audio/ogg; codecs=vorbis'},
|
||||
WEBM: {ext: 'webm', mime: 'audio/webm; codecs=vorbis'},
|
||||
CAF: {ext: 'caf', mime: 'audio/x-caf'}
|
||||
};
|
||||
ig.Sound.use = [ig.Sound.FORMAT.OGG, ig.Sound.FORMAT.MP3];
|
||||
ig.Sound.channels = 4;
|
||||
ig.Sound.enabled = true;
|
||||
|
||||
ig.normalizeVendorAttribute(window, 'AudioContext');
|
||||
ig.Sound.useWebAudio = !!window.AudioContext && !window.nwf;
|
||||
|
||||
});
|
||||
@@ -0,0 +1,145 @@
|
||||
ig.module(
|
||||
'impact.system'
|
||||
)
|
||||
.requires(
|
||||
'impact.timer',
|
||||
'impact.image'
|
||||
)
|
||||
.defines(function(){ "use strict";
|
||||
|
||||
ig.System = ig.Class.extend({
|
||||
fps: 30,
|
||||
width: 320,
|
||||
height: 240,
|
||||
realWidth: 320,
|
||||
realHeight: 240,
|
||||
scale: 1,
|
||||
|
||||
tick: 0,
|
||||
animationId: 0,
|
||||
newGameClass: null,
|
||||
running: false,
|
||||
|
||||
delegate: null,
|
||||
clock: null,
|
||||
canvas: null,
|
||||
context: null,
|
||||
|
||||
init: function( canvasId, fps, width, height, scale ) {
|
||||
this.fps = fps;
|
||||
|
||||
this.clock = new ig.Timer();
|
||||
this.canvas = ig.$(canvasId);
|
||||
this.resize( width, height, scale );
|
||||
this.context = this.canvas.getContext('2d');
|
||||
|
||||
this.getDrawPos = ig.System.drawMode;
|
||||
|
||||
// Automatically switch to crisp scaling when using a scale
|
||||
// other than 1
|
||||
if( this.scale != 1 ) {
|
||||
ig.System.scaleMode = ig.System.SCALE.CRISP;
|
||||
}
|
||||
ig.System.scaleMode( this.canvas, this.context );
|
||||
},
|
||||
|
||||
|
||||
resize: function( width, height, scale ) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.scale = scale || this.scale;
|
||||
|
||||
this.realWidth = this.width * this.scale;
|
||||
this.realHeight = this.height * this.scale;
|
||||
this.canvas.width = this.realWidth;
|
||||
this.canvas.height = this.realHeight;
|
||||
},
|
||||
|
||||
|
||||
setGame: function( gameClass ) {
|
||||
if( this.running ) {
|
||||
this.newGameClass = gameClass;
|
||||
}
|
||||
else {
|
||||
this.setGameNow( gameClass );
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
setGameNow: function( gameClass ) {
|
||||
ig.game = new (gameClass)();
|
||||
ig.system.setDelegate( ig.game );
|
||||
},
|
||||
|
||||
|
||||
setDelegate: function( object ) {
|
||||
if( typeof(object.run) == 'function' ) {
|
||||
this.delegate = object;
|
||||
this.startRunLoop();
|
||||
} else {
|
||||
throw( 'System.setDelegate: No run() function in object' );
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
stopRunLoop: function() {
|
||||
ig.clearAnimation( this.animationId );
|
||||
this.running = false;
|
||||
},
|
||||
|
||||
|
||||
startRunLoop: function() {
|
||||
this.stopRunLoop();
|
||||
this.animationId = ig.setAnimation( this.run.bind(this), this.canvas );
|
||||
this.running = true;
|
||||
},
|
||||
|
||||
|
||||
clear: function( color ) {
|
||||
this.context.fillStyle = color;
|
||||
this.context.fillRect( 0, 0, this.realWidth, this.realHeight );
|
||||
},
|
||||
|
||||
|
||||
run: function() {
|
||||
ig.Timer.step();
|
||||
this.tick = this.clock.tick();
|
||||
|
||||
this.delegate.run();
|
||||
ig.input.clearPressed();
|
||||
|
||||
if( this.newGameClass ) {
|
||||
this.setGameNow( this.newGameClass );
|
||||
this.newGameClass = null;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
getDrawPos: null // Set through constructor
|
||||
});
|
||||
|
||||
ig.System.DRAW = {
|
||||
AUTHENTIC: function( p ) { return Math.round(p) * this.scale; },
|
||||
SMOOTH: function( p ) { return Math.round(p * this.scale); },
|
||||
SUBPIXEL: function( p ) { return p * this.scale; }
|
||||
};
|
||||
ig.System.drawMode = ig.System.DRAW.SMOOTH;
|
||||
|
||||
ig.System.SCALE = {
|
||||
CRISP: function( canvas, context ) {
|
||||
ig.setVendorAttribute( context, 'imageSmoothingEnabled', false );
|
||||
canvas.style.imageRendering = '-moz-crisp-edges';
|
||||
canvas.style.imageRendering = '-o-crisp-edges';
|
||||
canvas.style.imageRendering = '-webkit-optimize-contrast';
|
||||
canvas.style.imageRendering = 'crisp-edges';
|
||||
canvas.style.msInterpolationMode = 'nearest-neighbor'; // No effect on Canvas :/
|
||||
},
|
||||
SMOOTH: function( canvas, context ) {
|
||||
ig.setVendorAttribute( context, 'imageSmoothingEnabled', true );
|
||||
canvas.style.imageRendering = '';
|
||||
canvas.style.msInterpolationMode = '';
|
||||
}
|
||||
};
|
||||
ig.System.scaleMode = ig.System.SCALE.SMOOTH;
|
||||
|
||||
});
|
||||
@@ -0,0 +1,72 @@
|
||||
ig.module(
|
||||
'impact.timer'
|
||||
)
|
||||
.defines(function(){ "use strict";
|
||||
|
||||
ig.Timer = ig.Class.extend({
|
||||
target: 0,
|
||||
base: 0,
|
||||
last: 0,
|
||||
pausedAt: 0,
|
||||
|
||||
init: function( seconds ) {
|
||||
this.base = ig.Timer.time;
|
||||
this.last = ig.Timer.time;
|
||||
|
||||
this.target = seconds || 0;
|
||||
},
|
||||
|
||||
|
||||
set: function( seconds ) {
|
||||
this.target = seconds || 0;
|
||||
this.base = ig.Timer.time;
|
||||
this.pausedAt = 0;
|
||||
},
|
||||
|
||||
|
||||
reset: function() {
|
||||
this.base = ig.Timer.time;
|
||||
this.pausedAt = 0;
|
||||
},
|
||||
|
||||
|
||||
tick: function() {
|
||||
var delta = ig.Timer.time - this.last;
|
||||
this.last = ig.Timer.time;
|
||||
return (this.pausedAt ? 0 : delta);
|
||||
},
|
||||
|
||||
|
||||
delta: function() {
|
||||
return (this.pausedAt || ig.Timer.time) - this.base - this.target;
|
||||
},
|
||||
|
||||
|
||||
pause: function() {
|
||||
if( !this.pausedAt ) {
|
||||
this.pausedAt = ig.Timer.time;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
unpause: function() {
|
||||
if( this.pausedAt ) {
|
||||
this.base += ig.Timer.time - this.pausedAt;
|
||||
this.pausedAt = 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ig.Timer._last = 0;
|
||||
ig.Timer.time = Number.MIN_VALUE;
|
||||
ig.Timer.timeScale = 1;
|
||||
ig.Timer.maxStep = 0.05;
|
||||
|
||||
ig.Timer.step = function() {
|
||||
var current = Date.now();
|
||||
var delta = (current - ig.Timer._last) / 1000;
|
||||
ig.Timer.time += Math.min(delta, ig.Timer.maxStep) * ig.Timer.timeScale;
|
||||
ig.Timer._last = current;
|
||||
};
|
||||
|
||||
});
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
require_once( 'config.php' );
|
||||
|
||||
$dir = WM_Config::$fileRoot . str_replace( '..', '', $_GET['dir'] );
|
||||
if( $dir{strlen($dir)-1} != '/' ) {
|
||||
$dir .= '/';
|
||||
}
|
||||
|
||||
$find = '*.*';
|
||||
switch( $_GET['type'] ) {
|
||||
case 'images':
|
||||
$find = '*.{png,gif,jpg,jpeg}';
|
||||
break;
|
||||
case 'scripts':
|
||||
$find = '*.js';
|
||||
break;
|
||||
}
|
||||
|
||||
$dirs = glob( $dir.'*', GLOB_ONLYDIR );
|
||||
if( $dirs === false ) { $dirs = array(); };
|
||||
|
||||
$files = glob( $dir.$find, GLOB_BRACE );
|
||||
if( $files === false ) { $files = array(); }
|
||||
|
||||
$fileRootLength = strlen( WM_Config::$fileRoot );
|
||||
foreach( $files as $i => $f ) {
|
||||
$files[$i] = substr( $f, $fileRootLength );
|
||||
}
|
||||
foreach( $dirs as $i => $d ) {
|
||||
$dirs[$i] = substr( $d, $fileRootLength );
|
||||
}
|
||||
|
||||
$parent = substr($_GET['dir'], 0, strrpos($_GET['dir'], '/'));
|
||||
echo json_encode( array(
|
||||
'parent' => (empty($_GET['dir']) ? false : $parent),
|
||||
'dirs' => $dirs,
|
||||
'files' => $files
|
||||
));
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
class WM_Config {
|
||||
public static $fileRoot = '../../../';
|
||||
}
|
||||
|
||||
function stripslashes_deep($value)
|
||||
{
|
||||
$value = is_array($value) ?
|
||||
array_map( 'stripslashes_deep', $value ) :
|
||||
stripslashes($value);
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
// revert magic quotes
|
||||
if( function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc() ) {
|
||||
$_GET = array_map( 'stripslashes_deep', $_GET );
|
||||
$_POST = array_map( 'stripslashes_deep', $_POST );
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
require_once( 'config.php' );
|
||||
|
||||
$globs = is_array($_GET['glob']) ? $_GET['glob'] : array($_GET['glob']);
|
||||
$files = array();
|
||||
foreach( $globs as $glob ) {
|
||||
$pattern = WM_Config::$fileRoot . str_replace( '..', '', $glob );
|
||||
$currentFiles = glob( $pattern );
|
||||
if( $currentFiles !== false ) {
|
||||
$files = array_merge( $files, $currentFiles );
|
||||
}
|
||||
}
|
||||
|
||||
$fileRootLength = strlen( WM_Config::$fileRoot );
|
||||
foreach( $files as $i => $f ) {
|
||||
$files[$i] = substr( $f, $fileRootLength );
|
||||
}
|
||||
|
||||
echo json_encode( $files );
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
require_once( 'config.php' );
|
||||
|
||||
$result = array('error' => 0);
|
||||
|
||||
if( !empty($_POST['path']) && !empty($_POST['data']) ) {
|
||||
$path = WM_Config::$fileRoot . str_replace( '..', '', $_POST['path'] );
|
||||
|
||||
if( preg_match('/\.js$/', $path) ) {
|
||||
$success = @file_put_contents( $path, $_POST['data'] );
|
||||
if( $success === false ) {
|
||||
$result = array(
|
||||
'error' => '2',
|
||||
'msg' => "Couldn't write to file: $path"
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$result = array(
|
||||
'error' => '3',
|
||||
'msg' => "File must have a .js suffix"
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$result = array(
|
||||
'error' => '1',
|
||||
'msg' => "No Data or Path specified"
|
||||
);
|
||||
}
|
||||
|
||||
echo json_encode($result);
|
||||
|
||||
?>
|
||||
|
After Width: | Height: | Size: 717 B |
|
After Width: | Height: | Size: 10 KiB |
@@ -0,0 +1,127 @@
|
||||
ig.module(
|
||||
'weltmeister.config'
|
||||
)
|
||||
.defines(function(){ "use strict";
|
||||
|
||||
wm.config = {
|
||||
|
||||
project: {
|
||||
// The prefix path of your game's source code. You only have to change
|
||||
// this if you use the 'ImpactPrefix' in your dev environment.
|
||||
'modulePath': 'lib/',
|
||||
|
||||
// This "glob" tells Weltmeister where to load the entity files
|
||||
// from. If you want to load entities from several directories,
|
||||
// you can specify an array here. E.g.:
|
||||
// 'entityFiles': ['lib/game/powerups/*.js', 'lib/game/entities/*.js']
|
||||
'entityFiles': 'lib/game/entities/*.js',
|
||||
|
||||
// The default path for the level file selection box
|
||||
'levelPath': 'lib/game/levels/',
|
||||
|
||||
// Whether to save levels as plain JSON or wrapped in a module. If
|
||||
// you want to load levels asynchronously via AJAX, saving as plain
|
||||
// JSON can be helpful.
|
||||
'outputFormat': 'module', // 'module' or 'json'
|
||||
|
||||
// Whether to pretty print the JSON data in level files. If you have
|
||||
// any issues with your levels, it's usually a good idea to turn this
|
||||
// on and look at the saved level files with a text editor.
|
||||
'prettyPrint': true
|
||||
},
|
||||
|
||||
|
||||
// Plugins for Weltmeister: an array of module names to load
|
||||
plugins: [],
|
||||
|
||||
|
||||
// Default settings when creating new layers in Weltmeister. Change these
|
||||
// as you like
|
||||
'layerDefaults': {
|
||||
'width': 30,
|
||||
'height': 20,
|
||||
'tilesize': 8
|
||||
},
|
||||
|
||||
// Whether to ask before closing Weltmeister when there are unsaved changes
|
||||
'askBeforeClose': true,
|
||||
|
||||
// Whether to attempt to load the last opened level on startup
|
||||
'loadLastLevel': true,
|
||||
|
||||
// Size of the "snap" grid when moving entities
|
||||
'entityGrid': 4,
|
||||
|
||||
// Number of undo levels. You may want to increase this if you use 'undo'
|
||||
// frequently.
|
||||
'undoLevels': 50,
|
||||
|
||||
// Mouse and Key bindings in Weltmeister. Some function are bound to
|
||||
// several keys. See the documentation of ig.Input for a list of available
|
||||
// key names.
|
||||
'binds': {
|
||||
'MOUSE1': 'draw',
|
||||
'MOUSE2': 'drag',
|
||||
'SHIFT': 'select',
|
||||
'CTRL': 'drag',
|
||||
'SPACE': 'menu',
|
||||
'DELETE': 'delete',
|
||||
'BACKSPACE': 'delete',
|
||||
'G': 'grid',
|
||||
'C': 'clone',
|
||||
'Z': 'undo',
|
||||
'Y': 'redo',
|
||||
'MWHEEL_UP': 'zoomin',
|
||||
'PLUS': 'zoomin',
|
||||
'MWHEEL_DOWN': 'zoomout',
|
||||
'MINUS': 'zoomout'
|
||||
},
|
||||
|
||||
// Whether to enable unidirectional scrolling for touchpads; this
|
||||
// automatically unbinds the MWHEEL_UP and MWHEEL_DOWN actions.
|
||||
'touchScroll': false,
|
||||
|
||||
// View settings. You can change the default Zoom level and whether
|
||||
// to show the grid on startup here.
|
||||
'view': {
|
||||
'zoom': 1,
|
||||
'zoomMax': 4,
|
||||
'zoomMin': 0.125,
|
||||
'grid': false
|
||||
},
|
||||
|
||||
// Font face and size for entity labels and the grid coordinates
|
||||
'labels': {
|
||||
'draw': true,
|
||||
'step': 32,
|
||||
'font': '10px Bitstream Vera Sans Mono, Monaco, sans-serif'
|
||||
},
|
||||
|
||||
// Colors to use for the background, selection boxes, text and the grid
|
||||
'colors': {
|
||||
'clear': '#000000', // Background Color
|
||||
'highlight': '#ceff36', // Currently selected tile or entity
|
||||
'primary': '#ffffff', // Labels and layer bounds
|
||||
'secondary': '#555555', // Grid and tile selection bounds
|
||||
'selection': '#ff9933' // Selection cursor box on tile maps
|
||||
},
|
||||
|
||||
// Settings for the Collision tiles. You shouldn't need to change these.
|
||||
// The tilesize only specifies the size in the image - resizing to final
|
||||
// size for each layer happens in Weltmeister.
|
||||
'collisionTiles': {
|
||||
'path': 'lib/weltmeister/collisiontiles-64.png',
|
||||
'tilesize': 64
|
||||
},
|
||||
|
||||
// API paths for saving levels and browsing directories. If you use a
|
||||
// different backend (i.e. not the official PHP backend), you may have
|
||||
// to change these.
|
||||
'api': {
|
||||
'save': 'lib/weltmeister/api/save.php',
|
||||
'browse': 'lib/weltmeister/api/browse.php',
|
||||
'glob': 'lib/weltmeister/api/glob.php'
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
@@ -0,0 +1,697 @@
|
||||
ig.module(
|
||||
'weltmeister.edit-entities'
|
||||
)
|
||||
.requires(
|
||||
'impact.game',
|
||||
'impact.background-map',
|
||||
'weltmeister.config',
|
||||
'weltmeister.tile-select',
|
||||
'weltmeister.entities'
|
||||
)
|
||||
.defines(function(){ "use strict";
|
||||
|
||||
wm.EditEntities = ig.Class.extend({
|
||||
visible: true,
|
||||
active: true,
|
||||
|
||||
div: null,
|
||||
hotkey: -1,
|
||||
ignoreLastClick: false,
|
||||
name: 'entities',
|
||||
|
||||
entities: [],
|
||||
namedEntities: {},
|
||||
selectedEntity: null,
|
||||
entityClasses: {},
|
||||
menuDiv: null,
|
||||
selector: {size:{x:2, y:2}, pos:{x:0,y:0}, offset:{x:0,y:0}},
|
||||
wasSelectedOnScaleBorder: false,
|
||||
gridSize: wm.config.entityGrid,
|
||||
entityDefinitions: null,
|
||||
|
||||
|
||||
|
||||
init: function( div ) {
|
||||
this.div = div;
|
||||
div.bind( 'mouseup', this.click.bind(this) );
|
||||
this.div.children('.visible').bind( 'mousedown', this.toggleVisibilityClick.bind(this) );
|
||||
|
||||
this.menu = $('#entityMenu');
|
||||
this.importEntityClass( wm.entityModules );
|
||||
this.entityDefinitions = $('#entityDefinitions');
|
||||
|
||||
$('#entityKey').bind( 'keydown', function(ev){
|
||||
if( ev.which == 13 ){
|
||||
$('#entityValue').focus();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
$('#entityValue').bind( 'keydown', this.setEntitySetting.bind(this) );
|
||||
},
|
||||
|
||||
|
||||
clear: function() {
|
||||
this.entities = [];
|
||||
this.selectEntity( null );
|
||||
},
|
||||
|
||||
|
||||
sort: function() {
|
||||
this.entities.sort( ig.Game.SORT.Z_INDEX );
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Loading, Saving
|
||||
|
||||
|
||||
fileNameToClassName: function( name ) {
|
||||
var typeName = '-' + name.replace(/^.*\/|\.js/g,'');
|
||||
typeName = typeName.replace(/-(\w)/g, function( m, a ) {
|
||||
return a.toUpperCase();
|
||||
});
|
||||
return 'Entity' + typeName;
|
||||
},
|
||||
|
||||
|
||||
importEntityClass: function( modules ) {
|
||||
var unloadedClasses = [];
|
||||
for( var m in modules ) {
|
||||
var className = this.fileNameToClassName(modules[m]);
|
||||
var entityName = className.replace(/^Entity/, '');
|
||||
|
||||
// ig.global[className] should be the actual class object
|
||||
if( className && ig.global[className] ) {
|
||||
|
||||
// Ignore entities that have the _wmIgnore flag
|
||||
if( !ig.global[className].prototype._wmIgnore ) {
|
||||
var a = $( '<div/>', {
|
||||
'id': className,
|
||||
'href': '#',
|
||||
'html': entityName,
|
||||
'mouseup': this.newEntityClick.bind(this)
|
||||
});
|
||||
this.menu.append( a );
|
||||
this.entityClasses[className] = m;
|
||||
}
|
||||
}
|
||||
else {
|
||||
unloadedClasses.push( modules[m] + ' (expected name: ' + className + ')' );
|
||||
}
|
||||
}
|
||||
|
||||
if( unloadedClasses.length > 0 ) {
|
||||
var warning = 'The following entity classes were not loaded due to\n'
|
||||
+ 'file and class name mismatches: \n\n'
|
||||
+ unloadedClasses.join( '\n' );
|
||||
alert( warning );
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
getEntityByName: function( name ) {
|
||||
return this.namedEntities[name];
|
||||
},
|
||||
|
||||
|
||||
getSaveData: function() {
|
||||
var ents = [];
|
||||
for( var i = 0; i < this.entities.length; i++ ) {
|
||||
var ent = this.entities[i];
|
||||
var type = ent._wmClassName;
|
||||
var data = {type:type,x:ent.pos.x,y:ent.pos.y};
|
||||
|
||||
var hasSettings = false;
|
||||
for( var p in ent._wmSettings ) {
|
||||
hasSettings = true;
|
||||
}
|
||||
if( hasSettings ) {
|
||||
data.settings = ent._wmSettings;
|
||||
}
|
||||
|
||||
ents.push( data );
|
||||
}
|
||||
return ents;
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Selecting
|
||||
|
||||
|
||||
selectEntityAt: function( x, y ) {
|
||||
this.selector.pos = { x: x, y: y };
|
||||
|
||||
// Find all possible selections
|
||||
var possibleSelections = [];
|
||||
for( var i = 0; i < this.entities.length; i++ ) {
|
||||
if( this.entities[i].touches(this.selector) ) {
|
||||
possibleSelections.push( this.entities[i] );
|
||||
}
|
||||
}
|
||||
|
||||
// Nothing found? Early out.
|
||||
if( !possibleSelections.length ) {
|
||||
this.selectEntity( null );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find the 'next' selection
|
||||
var selectedIndex = possibleSelections.indexOf(this.selectedEntity);
|
||||
var nextSelection = (selectedIndex + 1) % possibleSelections.length;
|
||||
var ent = possibleSelections[nextSelection];
|
||||
|
||||
// Select it!
|
||||
this.selector.offset = {
|
||||
x: (x - ent.pos.x + ent.offset.x),
|
||||
y: (y - ent.pos.y + ent.offset.y)
|
||||
};
|
||||
this.selectEntity( ent );
|
||||
this.wasSelectedOnScaleBorder = this.isOnScaleBorder( ent, this.selector );
|
||||
return ent;
|
||||
},
|
||||
|
||||
|
||||
selectEntity: function( entity ) {
|
||||
if( entity && entity != this.selectedEntity ) {
|
||||
this.selectedEntity = entity;
|
||||
$('#entitySettings').fadeOut(100,(function(){
|
||||
this.loadEntitySettings();
|
||||
$('#entitySettings').fadeIn(100);
|
||||
}).bind(this));
|
||||
}
|
||||
else if( !entity ) {
|
||||
$('#entitySettings').fadeOut(100);
|
||||
$('#entityKey').blur();
|
||||
$('#entityValue').blur();
|
||||
}
|
||||
|
||||
this.selectedEntity = entity;
|
||||
$('#entityKey').val('');
|
||||
$('#entityValue').val('');
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Creating, Deleting, Moving
|
||||
|
||||
|
||||
deleteSelectedEntity: function() {
|
||||
if( !this.selectedEntity ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ig.game.undo.commitEntityDelete( this.selectedEntity );
|
||||
|
||||
this.removeEntity( this.selectedEntity );
|
||||
this.selectEntity( null );
|
||||
return true;
|
||||
},
|
||||
|
||||
|
||||
removeEntity: function( ent ) {
|
||||
if( ent.name ) {
|
||||
delete this.namedEntities[ent.name];
|
||||
}
|
||||
this.entities.erase( ent );
|
||||
},
|
||||
|
||||
|
||||
cloneSelectedEntity: function() {
|
||||
if( !this.selectedEntity ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var className = this.selectedEntity._wmClassName;
|
||||
var settings = ig.copy(this.selectedEntity._wmSettings);
|
||||
if( settings.name ) {
|
||||
settings.name = settings.name + '_clone';
|
||||
}
|
||||
var x = this.selectedEntity.pos.x + this.gridSize;
|
||||
var y = this.selectedEntity.pos.y;
|
||||
var newEntity = this.spawnEntity( className, x, y, settings );
|
||||
newEntity._wmSettings = settings;
|
||||
this.selectEntity( newEntity );
|
||||
|
||||
ig.game.undo.commitEntityCreate( newEntity );
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
|
||||
dragOnSelectedEntity: function( x, y ) {
|
||||
if( !this.selectedEntity ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// scale or move?
|
||||
if( this.selectedEntity._wmScalable && this.wasSelectedOnScaleBorder ) {
|
||||
this.scaleSelectedEntity( x, y );
|
||||
}
|
||||
else {
|
||||
this.moveSelectedEntity( x, y )
|
||||
}
|
||||
|
||||
ig.game.undo.pushEntityEdit( this.selectedEntity );
|
||||
return true;
|
||||
},
|
||||
|
||||
|
||||
moveSelectedEntity: function( x, y ) {
|
||||
x =
|
||||
Math.round( (x - this.selector.offset.x ) / this.gridSize )
|
||||
* this.gridSize + this.selectedEntity.offset.x;
|
||||
y =
|
||||
Math.round( (y - this.selector.offset.y ) / this.gridSize )
|
||||
* this.gridSize + this.selectedEntity.offset.y;
|
||||
|
||||
// new position?
|
||||
if( this.selectedEntity.pos.x != x || this.selectedEntity.pos.y != y ) {
|
||||
$('#entityDefinitionPosX').text( x );
|
||||
$('#entityDefinitionPosY').text( y );
|
||||
|
||||
this.selectedEntity.pos.x = x;
|
||||
this.selectedEntity.pos.y = y;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
scaleSelectedEntity: function( x, y ) {
|
||||
var scale = this.wasSelectedOnScaleBorder;
|
||||
|
||||
var w = Math.round( x / this.gridSize ) * this.gridSize - this.selectedEntity.pos.x;
|
||||
|
||||
if( !this.selectedEntity._wmSettings.size ) {
|
||||
this.selectedEntity._wmSettings.size = {};
|
||||
}
|
||||
|
||||
if( scale == 'n' ) {
|
||||
var h = this.selectedEntity.pos.y - Math.round( y / this.gridSize ) * this.gridSize;
|
||||
if( this.selectedEntity.size.y + h <= this.gridSize ) {
|
||||
h = (this.selectedEntity.size.y - this.gridSize) * -1;
|
||||
}
|
||||
this.selectedEntity.size.y += h;
|
||||
this.selectedEntity.pos.y -= h;
|
||||
}
|
||||
else if( scale == 's' ) {
|
||||
var h = Math.round( y / this.gridSize ) * this.gridSize - this.selectedEntity.pos.y;
|
||||
this.selectedEntity.size.y = Math.max( this.gridSize, h );
|
||||
}
|
||||
else if( scale == 'e' ) {
|
||||
var w = Math.round( x / this.gridSize ) * this.gridSize - this.selectedEntity.pos.x;
|
||||
this.selectedEntity.size.x = Math.max( this.gridSize, w );
|
||||
}
|
||||
else if( scale == 'w' ) {
|
||||
var w = this.selectedEntity.pos.x - Math.round( x / this.gridSize ) * this.gridSize;
|
||||
if( this.selectedEntity.size.x + w <= this.gridSize ) {
|
||||
w = (this.selectedEntity.size.x - this.gridSize) * -1;
|
||||
}
|
||||
this.selectedEntity.size.x += w;
|
||||
this.selectedEntity.pos.x -= w;
|
||||
}
|
||||
this.selectedEntity._wmSettings.size.x = this.selectedEntity.size.x;
|
||||
this.selectedEntity._wmSettings.size.y = this.selectedEntity.size.y;
|
||||
|
||||
this.loadEntitySettings();
|
||||
},
|
||||
|
||||
|
||||
newEntityClick: function( ev ) {
|
||||
this.hideMenu();
|
||||
var newEntity = this.spawnEntity( ev.target.id, 0, 0, {} );
|
||||
this.selectEntity( newEntity );
|
||||
this.moveSelectedEntity( this.selector.pos.x, this.selector.pos.y );
|
||||
ig.editor.setModified();
|
||||
|
||||
ig.game.undo.commitEntityCreate( newEntity );
|
||||
},
|
||||
|
||||
|
||||
spawnEntity: function( className, x, y, settings ) {
|
||||
settings = settings || {};
|
||||
var entityClass = ig.global[ className ];
|
||||
if( entityClass ) {
|
||||
var newEntity = new (entityClass)( x, y, settings );
|
||||
newEntity._wmInEditor = true;
|
||||
newEntity._wmClassName = className;
|
||||
newEntity._wmSettings = {};
|
||||
for( var s in settings ) {
|
||||
newEntity._wmSettings[s] = settings[s];
|
||||
}
|
||||
this.entities.push( newEntity );
|
||||
if( settings.name ) {
|
||||
this.namedEntities[settings.name] = newEntity;
|
||||
}
|
||||
this.sort();
|
||||
return newEntity;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
|
||||
isOnScaleBorder: function( entity, selector ) {
|
||||
var border = 2;
|
||||
var w = selector.pos.x - entity.pos.x;
|
||||
var h = selector.pos.y - entity.pos.y;
|
||||
|
||||
if( w < border ) return 'w';
|
||||
if( w > entity.size.x - border ) return 'e';
|
||||
|
||||
if( h < border ) return 'n';
|
||||
if( h > entity.size.y - border ) return 's';
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Settings
|
||||
|
||||
|
||||
loadEntitySettings: function(ent) {
|
||||
|
||||
if( !this.selectedEntity ) {
|
||||
return;
|
||||
}
|
||||
var html =
|
||||
'<div class="entityDefinition"><span class="key">x</span>:<span class="value" id="entityDefinitionPosX">'+this.selectedEntity.pos.x+'</span></div>'
|
||||
+ '<div class="entityDefinition"><span class="key">y</span>:<span class="value" id="entityDefinitionPosY">'+this.selectedEntity.pos.y+'</span></div>';
|
||||
|
||||
html += this.loadEntitySettingsRecursive( this.selectedEntity._wmSettings );
|
||||
this.entityDefinitions.html( html );
|
||||
|
||||
var className = this.selectedEntity._wmClassName.replace(/^Entity/, '');
|
||||
$('#entityClass').text( className );
|
||||
|
||||
$('.entityDefinition').bind( 'mouseup', this.selectEntitySetting );
|
||||
},
|
||||
|
||||
|
||||
loadEntitySettingsRecursive: function( settings, path ) {
|
||||
path = path || "";
|
||||
var html = "";
|
||||
for( var key in settings ) {
|
||||
var value = settings[key];
|
||||
if( typeof(value) == 'object' ) {
|
||||
html += this.loadEntitySettingsRecursive( value, path + key + "." );
|
||||
}
|
||||
else {
|
||||
html += '<div class="entityDefinition"><span class="key">'+path+key+'</span>:<span class="value">'+value+'</span></div>';
|
||||
}
|
||||
}
|
||||
|
||||
return html;
|
||||
},
|
||||
|
||||
|
||||
setEntitySetting: function( ev ) {
|
||||
if( ev.which != 13 ) {
|
||||
return true;
|
||||
}
|
||||
var key = $('#entityKey').val();
|
||||
var value = $('#entityValue').val();
|
||||
var floatVal = parseFloat(value);
|
||||
if( value == floatVal ) {
|
||||
value = floatVal;
|
||||
}
|
||||
|
||||
if( key == 'name' ) {
|
||||
if( this.selectedEntity.name ) {
|
||||
delete this.namedEntities[this.selectedEntity.name];
|
||||
}
|
||||
this.namedEntities[ value ] = this.selectedEntity;
|
||||
}
|
||||
|
||||
if( key == 'x' ) {
|
||||
this.selectedEntity.pos.x = Math.round(value);
|
||||
}
|
||||
else if( key == 'y' ) {
|
||||
this.selectedEntity.pos.y = Math.round(value);
|
||||
}
|
||||
else {
|
||||
this.writeSettingAtPath( this.selectedEntity._wmSettings, key, value );
|
||||
ig.merge( this.selectedEntity, this.selectedEntity._wmSettings );
|
||||
}
|
||||
|
||||
this.sort();
|
||||
|
||||
ig.game.setModified();
|
||||
ig.game.draw();
|
||||
|
||||
$('#entityKey').val('');
|
||||
$('#entityValue').val('');
|
||||
$('#entityValue').blur();
|
||||
this.loadEntitySettings();
|
||||
|
||||
$('#entityKey').focus();
|
||||
return false;
|
||||
},
|
||||
|
||||
|
||||
writeSettingAtPath: function( root, path, value ) {
|
||||
path = path.split('.');
|
||||
var cur = root;
|
||||
for( var i = 0; i < path.length; i++ ) {
|
||||
var n = path[i];
|
||||
if( i < path.length-1 && typeof(cur[n]) != 'object' ) {
|
||||
cur[n] = {};
|
||||
}
|
||||
|
||||
if( i == path.length-1 ) {
|
||||
cur[n] = value;
|
||||
}
|
||||
cur = cur[n];
|
||||
}
|
||||
|
||||
this.trimObject( root );
|
||||
},
|
||||
|
||||
|
||||
trimObject: function( obj ) {
|
||||
var isEmpty = true;
|
||||
for( var i in obj ) {
|
||||
if(
|
||||
(obj[i] === "") ||
|
||||
(typeof(obj[i]) == 'object' && this.trimObject(obj[i]))
|
||||
) {
|
||||
delete obj[i];
|
||||
}
|
||||
|
||||
if( typeof(obj[i]) != 'undefined' ) {
|
||||
isEmpty = false;
|
||||
}
|
||||
}
|
||||
|
||||
return isEmpty;
|
||||
},
|
||||
|
||||
|
||||
selectEntitySetting: function( ev ) {
|
||||
$('#entityKey').val( $(this).children('.key').text() );
|
||||
$('#entityValue').val( $(this).children('.value').text() );
|
||||
$('#entityValue').select();
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// UI
|
||||
|
||||
setHotkey: function( hotkey ) {
|
||||
this.hotkey = hotkey;
|
||||
this.div.attr('title', 'Select Layer ('+this.hotkey+')' );
|
||||
},
|
||||
|
||||
|
||||
showMenu: function( x, y ) {
|
||||
this.selector.pos = {
|
||||
x: Math.round( (x + ig.editor.screen.x) / this.gridSize ) * this.gridSize,
|
||||
y: Math.round( (y + ig.editor.screen.y) / this.gridSize ) * this.gridSize
|
||||
};
|
||||
this.menu.css({top: (y * ig.system.scale + 2), left: (x * ig.system.scale + 2) });
|
||||
this.menu.show();
|
||||
},
|
||||
|
||||
|
||||
hideMenu: function( x, y ) {
|
||||
ig.editor.mode = ig.editor.MODE.DEFAULT;
|
||||
this.menu.hide();
|
||||
},
|
||||
|
||||
|
||||
setActive: function( active ) {
|
||||
this.active = active;
|
||||
if( active ) {
|
||||
this.div.addClass( 'layerActive' );
|
||||
} else {
|
||||
this.div.removeClass( 'layerActive' );
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
toggleVisibility: function() {
|
||||
this.visible ^= 1;
|
||||
if( this.visible ) {
|
||||
this.div.children('.visible').addClass('checkedVis');
|
||||
} else {
|
||||
this.div.children('.visible').removeClass('checkedVis');
|
||||
}
|
||||
ig.game.draw();
|
||||
},
|
||||
|
||||
|
||||
toggleVisibilityClick: function( ev ) {
|
||||
if( !this.active ) {
|
||||
this.ignoreLastClick = true;
|
||||
}
|
||||
this.toggleVisibility()
|
||||
},
|
||||
|
||||
|
||||
click: function() {
|
||||
if( this.ignoreLastClick ) {
|
||||
this.ignoreLastClick = false;
|
||||
return;
|
||||
}
|
||||
ig.editor.setActiveLayer( 'entities' );
|
||||
},
|
||||
|
||||
|
||||
mousemove: function( x, y ) {
|
||||
this.selector.pos = { x: x, y: y };
|
||||
|
||||
if( this.selectedEntity ) {
|
||||
if( this.selectedEntity._wmScalable && this.selectedEntity.touches(this.selector) ) {
|
||||
var scale = this.isOnScaleBorder( this.selectedEntity, this.selector );
|
||||
if( scale == 'n' || scale == 's' ) {
|
||||
$('body').css('cursor', 'n-resize');
|
||||
return;
|
||||
}
|
||||
else if( scale == 'e' || scale == 'w' ) {
|
||||
$('body').css('cursor', 'e-resize');
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$('body').css('cursor', 'default');
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Drawing
|
||||
|
||||
|
||||
draw: function() {
|
||||
if( this.visible ) {
|
||||
for( var i = 0; i < this.entities.length; i++ ) {
|
||||
this.drawEntity( this.entities[i] );
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
drawEntity: function( ent ) {
|
||||
|
||||
// entity itself
|
||||
ent.draw();
|
||||
|
||||
// box
|
||||
if( ent._wmDrawBox ) {
|
||||
ig.system.context.fillStyle = ent._wmBoxColor || 'rgba(128, 128, 128, 0.9)';
|
||||
ig.system.context.fillRect(
|
||||
ig.system.getDrawPos(ent.pos.x - ig.game.screen.x),
|
||||
ig.system.getDrawPos(ent.pos.y - ig.game.screen.y),
|
||||
ent.size.x * ig.system.scale,
|
||||
ent.size.y * ig.system.scale
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
if( wm.config.labels.draw ) {
|
||||
// description
|
||||
var className = ent._wmClassName.replace(/^Entity/, '');
|
||||
var description = className + (ent.name ? ': ' + ent.name : '' );
|
||||
|
||||
// text-shadow
|
||||
ig.system.context.fillStyle = 'rgba(0,0,0,0.4)';
|
||||
ig.system.context.fillText(
|
||||
description,
|
||||
ig.system.getDrawPos(ent.pos.x - ig.game.screen.x),
|
||||
ig.system.getDrawPos(ent.pos.y - ig.game.screen.y + 0.5)
|
||||
);
|
||||
|
||||
// text
|
||||
ig.system.context.fillStyle = wm.config.colors.primary;
|
||||
ig.system.context.fillText(
|
||||
description,
|
||||
ig.system.getDrawPos(ent.pos.x - ig.game.screen.x),
|
||||
ig.system.getDrawPos(ent.pos.y - ig.game.screen.y)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// line to targets
|
||||
if( typeof(ent.target) == 'object' ) {
|
||||
for( var t in ent.target ) {
|
||||
this.drawLineToTarget( ent, ent.target[t] );
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
drawLineToTarget: function( ent, target ) {
|
||||
target = ig.game.getEntityByName( target );
|
||||
if( !target ) {
|
||||
return;
|
||||
}
|
||||
|
||||
ig.system.context.strokeStyle = '#fff';
|
||||
ig.system.context.lineWidth = 1;
|
||||
|
||||
ig.system.context.beginPath();
|
||||
ig.system.context.moveTo(
|
||||
ig.system.getDrawPos(ent.pos.x + ent.size.x/2 - ig.game.screen.x),
|
||||
ig.system.getDrawPos(ent.pos.y + ent.size.y/2 - ig.game.screen.y)
|
||||
);
|
||||
ig.system.context.lineTo(
|
||||
ig.system.getDrawPos(target.pos.x + target.size.x/2 - ig.game.screen.x),
|
||||
ig.system.getDrawPos(target.pos.y + target.size.y/2 - ig.game.screen.y)
|
||||
);
|
||||
ig.system.context.stroke();
|
||||
ig.system.context.closePath();
|
||||
},
|
||||
|
||||
|
||||
drawCursor: function( x, y ) {
|
||||
if( this.selectedEntity ) {
|
||||
ig.system.context.lineWidth = 1;
|
||||
ig.system.context.strokeStyle = wm.config.colors.highlight;
|
||||
ig.system.context.strokeRect(
|
||||
ig.system.getDrawPos(this.selectedEntity.pos.x - ig.editor.screen.x) - 0.5,
|
||||
ig.system.getDrawPos(this.selectedEntity.pos.y - ig.editor.screen.y) - 0.5,
|
||||
this.selectedEntity.size.x * ig.system.scale + 1,
|
||||
this.selectedEntity.size.y * ig.system.scale + 1
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,388 @@
|
||||
ig.module(
|
||||
'weltmeister.edit-map'
|
||||
)
|
||||
.requires(
|
||||
'impact.background-map',
|
||||
'weltmeister.tile-select'
|
||||
)
|
||||
.defines(function(){ "use strict";
|
||||
|
||||
wm.EditMap = ig.BackgroundMap.extend({
|
||||
name: '',
|
||||
visible: true,
|
||||
active: true,
|
||||
linkWithCollision: false,
|
||||
|
||||
div: null,
|
||||
brush: [[0]],
|
||||
oldData: null,
|
||||
hotkey: -1,
|
||||
ignoreLastClick: false,
|
||||
tileSelect: null,
|
||||
|
||||
isSelecting: false,
|
||||
selectionBegin: null,
|
||||
|
||||
init: function( name, tilesize, tileset, foreground ) {
|
||||
this.name = name;
|
||||
this.parent( tilesize, [[0]], tileset || '' );
|
||||
this.foreground = foreground;
|
||||
|
||||
this.div = $( '<div/>', {
|
||||
'class': 'layer layerActive',
|
||||
'id': ('layer_' + name),
|
||||
'mouseup': this.click.bind(this)
|
||||
});
|
||||
this.setName( name );
|
||||
if( this.foreground ) {
|
||||
$('#layers').prepend( this.div );
|
||||
}
|
||||
else {
|
||||
$('#layerEntities').after( this.div );
|
||||
}
|
||||
|
||||
this.tileSelect = new wm.TileSelect( this );
|
||||
},
|
||||
|
||||
|
||||
getSaveData: function() {
|
||||
return {
|
||||
name: this.name,
|
||||
width: this.width,
|
||||
height: this.height,
|
||||
linkWithCollision: this.linkWithCollision,
|
||||
visible: this.visible,
|
||||
tilesetName: this.tilesetName,
|
||||
repeat: this.repeat,
|
||||
preRender: this.preRender,
|
||||
distance: this.distance,
|
||||
tilesize: this.tilesize,
|
||||
foreground: this.foreground,
|
||||
data: this.data
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
resize: function( newWidth, newHeight ) {
|
||||
var newData = new Array( newHeight );
|
||||
for( var y = 0; y < newHeight; y++ ) {
|
||||
newData[y] = new Array( newWidth );
|
||||
for( var x = 0; x < newWidth; x++ ) {
|
||||
newData[y][x] = (x < this.width && y < this.height) ? this.data[y][x] : 0;
|
||||
}
|
||||
}
|
||||
this.data = newData;
|
||||
this.width = newWidth;
|
||||
this.height = newHeight;
|
||||
|
||||
this.resetDiv();
|
||||
},
|
||||
|
||||
beginEditing: function() {
|
||||
this.oldData = ig.copy(this.data);
|
||||
},
|
||||
|
||||
getOldTile: function( x, y ) {
|
||||
var tx = Math.floor( x / this.tilesize );
|
||||
var ty = Math.floor( y / this.tilesize );
|
||||
if(
|
||||
(tx >= 0 && tx < this.width) &&
|
||||
(ty >= 0 && ty < this.height)
|
||||
) {
|
||||
return this.oldData[ty][tx];
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
|
||||
setTileset: function( tileset ) {
|
||||
if( this.name == 'collision' ) {
|
||||
this.setCollisionTileset();
|
||||
}
|
||||
else {
|
||||
this.parent( tileset );
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
setCollisionTileset: function() {
|
||||
var path = wm.config.collisionTiles.path;
|
||||
var scale = this.tilesize / wm.config.collisionTiles.tilesize;
|
||||
this.tiles = new ig.AutoResizedImage( path, scale );
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// UI
|
||||
|
||||
setHotkey: function( hotkey ) {
|
||||
this.hotkey = hotkey;
|
||||
this.setName( this.name );
|
||||
},
|
||||
|
||||
|
||||
setName: function( name ) {
|
||||
this.name = name.replace(/[^0-9a-zA-Z]/g, '_');
|
||||
this.resetDiv();
|
||||
},
|
||||
|
||||
|
||||
resetDiv: function() {
|
||||
var visClass = this.visible ? ' checkedVis' : '';
|
||||
this.div.html(
|
||||
'<span class="visible'+visClass+'" title="Toggle Visibility (Shift+'+this.hotkey+')"></span>' +
|
||||
'<span class="name">' + this.name + '</span>' +
|
||||
'<span class="size"> (' + this.width + 'x' + this.height + ')</span>'
|
||||
);
|
||||
this.div.attr('title', 'Select Layer ('+this.hotkey+')' );
|
||||
this.div.children('.visible').bind('mousedown', this.toggleVisibilityClick.bind(this) );
|
||||
},
|
||||
|
||||
|
||||
setActive: function( active ) {
|
||||
this.active = active;
|
||||
if( active ) {
|
||||
this.div.addClass( 'layerActive' );
|
||||
} else {
|
||||
this.div.removeClass( 'layerActive' );
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
toggleVisibility: function() {
|
||||
this.visible ^= 1;
|
||||
this.resetDiv();
|
||||
if( this.visible ) {
|
||||
this.div.children('.visible').addClass('checkedVis');
|
||||
} else {
|
||||
this.div.children('.visible').removeClass('checkedVis');
|
||||
}
|
||||
ig.game.draw();
|
||||
},
|
||||
|
||||
|
||||
toggleVisibilityClick: function( event ) {
|
||||
if( !this.active ) {
|
||||
this.ignoreLastClick = true;
|
||||
}
|
||||
this.toggleVisibility()
|
||||
},
|
||||
|
||||
|
||||
click: function() {
|
||||
if( this.ignoreLastClick ) {
|
||||
this.ignoreLastClick = false;
|
||||
return;
|
||||
}
|
||||
ig.editor.setActiveLayer( this.name );
|
||||
},
|
||||
|
||||
|
||||
destroy: function() {
|
||||
this.div.remove();
|
||||
},
|
||||
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Selecting
|
||||
|
||||
beginSelecting: function( x, y ) {
|
||||
this.isSelecting = true;
|
||||
this.selectionBegin = {x:x, y:y};
|
||||
},
|
||||
|
||||
|
||||
endSelecting: function( x, y ) {
|
||||
var r = this.getSelectionRect( x, y);
|
||||
|
||||
var brush = [];
|
||||
for( var ty = r.y; ty < r.y+r.h; ty++ ) {
|
||||
var row = [];
|
||||
for( var tx = r.x; tx < r.x+r.w; tx++ ) {
|
||||
if( tx < 0 || ty < 0 || tx >= this.width || ty >= this.height ) {
|
||||
row.push( 0 );
|
||||
}
|
||||
else {
|
||||
row.push( this.data[ty][tx] );
|
||||
}
|
||||
}
|
||||
brush.push( row );
|
||||
}
|
||||
this.isSelecting = false;
|
||||
this.selectionBegin = null;
|
||||
return brush;
|
||||
},
|
||||
|
||||
|
||||
getSelectionRect: function( x, y ) {
|
||||
var sx = this.selectionBegin ? this.selectionBegin.x : x,
|
||||
sy = this.selectionBegin ? this.selectionBegin.y : y;
|
||||
|
||||
var
|
||||
txb = Math.floor( (sx + this.scroll.x) / this.tilesize ),
|
||||
tyb = Math.floor( (sy + this.scroll.y) / this.tilesize ),
|
||||
txe = Math.floor( (x + this.scroll.x) / this.tilesize ),
|
||||
tye = Math.floor( (y + this.scroll.y) / this.tilesize );
|
||||
|
||||
return {
|
||||
x: Math.min( txb, txe ),
|
||||
y: Math.min( tyb, tye ),
|
||||
w: Math.abs( txb - txe) + 1,
|
||||
h: Math.abs( tyb - tye) + 1
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Drawing
|
||||
|
||||
draw: function() {
|
||||
// For performance reasons, repeated background maps are not drawn
|
||||
// when zoomed out
|
||||
if( this.visible && !(wm.config.view.zoom < 1 && this.repeat) ) {
|
||||
this.drawTiled();
|
||||
}
|
||||
|
||||
// Grid
|
||||
if( this.active && wm.config.view.grid ) {
|
||||
|
||||
var x = -ig.system.getDrawPos(this.scroll.x % this.tilesize) - 0.5;
|
||||
var y = -ig.system.getDrawPos(this.scroll.y % this.tilesize) - 0.5;
|
||||
var step = this.tilesize * ig.system.scale;
|
||||
|
||||
ig.system.context.beginPath();
|
||||
for( x; x < ig.system.realWidth; x += step ) {
|
||||
ig.system.context.moveTo( x, 0 );
|
||||
ig.system.context.lineTo( x, ig.system.realHeight );
|
||||
}
|
||||
for( y; y < ig.system.realHeight; y += step ) {
|
||||
ig.system.context.moveTo( 0, y );
|
||||
ig.system.context.lineTo( ig.system.realWidth, y );
|
||||
}
|
||||
ig.system.context.strokeStyle = wm.config.colors.secondary;
|
||||
ig.system.context.stroke();
|
||||
ig.system.context.closePath();
|
||||
|
||||
// Not calling beginPath() again has some weird performance issues
|
||||
// in Firefox 5. closePath has no effect. So to make it happy:
|
||||
ig.system.context.beginPath();
|
||||
}
|
||||
|
||||
// Bounds
|
||||
if( this.active ) {
|
||||
ig.system.context.lineWidth = 1;
|
||||
ig.system.context.strokeStyle = wm.config.colors.primary;
|
||||
ig.system.context.strokeRect(
|
||||
-ig.system.getDrawPos(this.scroll.x) - 0.5,
|
||||
-ig.system.getDrawPos(this.scroll.y) - 0.5,
|
||||
this.width * this.tilesize * ig.system.scale + 1,
|
||||
this.height * this.tilesize * ig.system.scale + 1
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
getCursorOffset: function() {
|
||||
var w = this.brush[0].length;
|
||||
var h = this.brush.length;
|
||||
|
||||
//return {x:0, y:0};
|
||||
return {
|
||||
x: (w/2-0.5).toInt() * this.tilesize,
|
||||
y: (h/2-0.5).toInt() * this.tilesize
|
||||
}
|
||||
},
|
||||
|
||||
drawCursor: function( x, y ) {
|
||||
if( this.isSelecting ) {
|
||||
var r = this.getSelectionRect( x, y);
|
||||
|
||||
ig.system.context.lineWidth = 1;
|
||||
ig.system.context.strokeStyle = wm.config.colors.selection;
|
||||
ig.system.context.strokeRect(
|
||||
(r.x * this.tilesize - this.scroll.x) * ig.system.scale - 0.5,
|
||||
(r.y * this.tilesize - this.scroll.y) * ig.system.scale - 0.5,
|
||||
r.w * this.tilesize * ig.system.scale + 1,
|
||||
r.h * this.tilesize * ig.system.scale + 1
|
||||
);
|
||||
}
|
||||
else {
|
||||
var w = this.brush[0].length;
|
||||
var h = this.brush.length;
|
||||
|
||||
var co = this.getCursorOffset();
|
||||
|
||||
var cx = Math.floor( (x+this.scroll.x) / this.tilesize ) * this.tilesize - this.scroll.x - co.x;
|
||||
var cy = Math.floor( (y+this.scroll.y) / this.tilesize ) * this.tilesize - this.scroll.y - co.y;
|
||||
|
||||
ig.system.context.lineWidth = 1;
|
||||
ig.system.context.strokeStyle = wm.config.colors.primary;
|
||||
ig.system.context.strokeRect(
|
||||
ig.system.getDrawPos(cx)-0.5,
|
||||
ig.system.getDrawPos(cy)-0.5,
|
||||
w * this.tilesize * ig.system.scale + 1,
|
||||
h * this.tilesize * ig.system.scale + 1
|
||||
);
|
||||
|
||||
ig.system.context.globalAlpha = 0.5;
|
||||
for( var ty = 0; ty < h; ty++ ) {
|
||||
for( var tx = 0; tx < w; tx++ ) {
|
||||
var t = this.brush[ty][tx];
|
||||
if( t ) {
|
||||
var px = cx + tx * this.tilesize;
|
||||
var py = cy + ty * this.tilesize;
|
||||
this.tiles.drawTile( px, py, t-1, this.tilesize );
|
||||
}
|
||||
}
|
||||
}
|
||||
ig.system.context.globalAlpha = 1;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
ig.AutoResizedImage = ig.Image.extend({
|
||||
internalScale: 1,
|
||||
|
||||
staticInstantiate: function() {
|
||||
return null; // Never cache!
|
||||
},
|
||||
|
||||
init: function( path, internalScale ) {
|
||||
this.internalScale = internalScale;
|
||||
this.parent( path );
|
||||
},
|
||||
|
||||
onload: function( event ) {
|
||||
this.width = Math.ceil(this.data.width * this.internalScale);
|
||||
this.height = Math.ceil(this.data.height * this.internalScale);
|
||||
|
||||
if( this.internalScale != 1 ) {
|
||||
var scaled = ig.$new('canvas');
|
||||
scaled.width = this.width;
|
||||
scaled.height = this.height;
|
||||
var scaledCtx = scaled.getContext('2d');
|
||||
|
||||
scaledCtx.drawImage( this.data, 0, 0, this.data.width, this.data.height, 0, 0, this.width , this.height );
|
||||
this.data = scaled;
|
||||
}
|
||||
|
||||
this.loaded = true;
|
||||
if( ig.system.scale != 1 ) {
|
||||
this.resize( ig.system.scale );
|
||||
}
|
||||
|
||||
if( this.loadCallback ) {
|
||||
this.loadCallback( this.path, true );
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
@@ -0,0 +1,58 @@
|
||||
ig.module(
|
||||
'weltmeister.entityLoader'
|
||||
)
|
||||
.requires(
|
||||
'weltmeister.config'
|
||||
)
|
||||
.defines(function(){ "use strict";
|
||||
|
||||
// Load the list of entity files via AJAX PHP glob
|
||||
var path = wm.config.api.glob + '?',
|
||||
globs = typeof wm.config.project.entityFiles == 'string' ?
|
||||
[wm.config.project.entityFiles] :
|
||||
wm.config.project.entityFiles;
|
||||
|
||||
for (var i = 0; i < globs.length; i++) {
|
||||
path += 'glob[]=' + encodeURIComponent(globs[i]) + '&';
|
||||
}
|
||||
|
||||
path += 'nocache=' + Math.random();
|
||||
|
||||
var req = $.ajax({
|
||||
url: path,
|
||||
method: 'get',
|
||||
dataType: 'json',
|
||||
|
||||
// MUST load synchronous, as the engine would otherwise determine that it
|
||||
// can't resolve dependencies to weltmeister.entities when there are
|
||||
// no more files to load and weltmeister.entities is still not defined
|
||||
// because the ajax request hasn't finished yet.
|
||||
// FIXME FFS!
|
||||
async: false,
|
||||
success: function(files) {
|
||||
|
||||
// File names to Module names
|
||||
var moduleNames = [];
|
||||
var modules = {};
|
||||
for( var i = 0; i < files.length; i++ ) {
|
||||
var name = files[i]
|
||||
.replace(new RegExp("^"+ig.lib+"|\\.js$", "g"), '')
|
||||
.replace(/\//g, '.');
|
||||
moduleNames.push( name );
|
||||
modules[name] = files[i];
|
||||
}
|
||||
|
||||
// Define a Module that requires all entity Modules
|
||||
ig.module('weltmeister.entities')
|
||||
.requires.apply(ig, moduleNames)
|
||||
.defines(function(){ wm.entityModules = modules; });
|
||||
},
|
||||
error: function( xhr, status, error ){
|
||||
throw(
|
||||
"Failed to load entity list via glob.php: " + error + "\n" +
|
||||
xhr.responseText
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,79 @@
|
||||
ig.module(
|
||||
'weltmeister.evented-input'
|
||||
)
|
||||
.requires(
|
||||
'impact.input'
|
||||
)
|
||||
.defines(function(){ "use strict";
|
||||
|
||||
wm.EventedInput = ig.Input.extend({
|
||||
mousemoveCallback: null,
|
||||
keyupCallback: null,
|
||||
keydownCallback: null,
|
||||
|
||||
delayedKeyup: {push:function(){},length: 0},
|
||||
|
||||
|
||||
keydown: function( event ) {
|
||||
var tag = event.target.tagName;
|
||||
if( tag == 'INPUT' || tag == 'TEXTAREA' ) { return; }
|
||||
|
||||
var code = event.type == 'keydown'
|
||||
? event.keyCode
|
||||
: (event.button == 2 ? ig.KEY.MOUSE2 : ig.KEY.MOUSE1);
|
||||
var action = this.bindings[code];
|
||||
if( action ) {
|
||||
if( !this.actions[action] ) {
|
||||
this.actions[action] = true;
|
||||
if( this.keydownCallback ) {
|
||||
this.keydownCallback( action );
|
||||
}
|
||||
}
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
keyup: function( event ) {
|
||||
var tag = event.target.tagName;
|
||||
if( tag == 'INPUT' || tag == 'TEXTAREA' ) { return; }
|
||||
|
||||
var code = event.type == 'keyup'
|
||||
? event.keyCode
|
||||
: (event.button == 2 ? ig.KEY.MOUSE2 : ig.KEY.MOUSE1);
|
||||
var action = this.bindings[code];
|
||||
if( action ) {
|
||||
this.actions[action] = false;
|
||||
if( this.keyupCallback ) {
|
||||
this.keyupCallback( action );
|
||||
}
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
mousewheel: function( event ) {
|
||||
var delta = event.wheelDelta ? event.wheelDelta : (event.detail * -1);
|
||||
var code = delta > 0 ? ig.KEY.MWHEEL_UP : ig.KEY.MWHEEL_DOWN;
|
||||
var action = this.bindings[code];
|
||||
if( action ) {
|
||||
if( this.keyupCallback ) {
|
||||
this.keyupCallback( action );
|
||||
}
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
mousemove: function( event ) {
|
||||
this.parent( event );
|
||||
if( this.mousemoveCallback ) {
|
||||
this.mousemoveCallback();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,107 @@
|
||||
/*!
|
||||
* jQuery UI 1.8.1
|
||||
*
|
||||
* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
||||
* and GPL (GPL-LICENSE.txt) licenses.
|
||||
*
|
||||
* http://docs.jquery.com/UI
|
||||
*/
|
||||
jQuery.ui||function(c){c.ui={version:"1.8.1",plugin:{add:function(a,b,d){a=c.ui[a].prototype;for(var e in d){a.plugins[e]=a.plugins[e]||[];a.plugins[e].push([b,d[e]])}},call:function(a,b,d){if((b=a.plugins[b])&&a.element[0].parentNode)for(var e=0;e<b.length;e++)a.options[b[e][0]]&&b[e][1].apply(a.element,d)}},contains:function(a,b){return document.compareDocumentPosition?a.compareDocumentPosition(b)&16:a!==b&&a.contains(b)},hasScroll:function(a,b){if(c(a).css("overflow")=="hidden")return false;
|
||||
b=b&&b=="left"?"scrollLeft":"scrollTop";var d=false;if(a[b]>0)return true;a[b]=1;d=a[b]>0;a[b]=0;return d},isOverAxis:function(a,b,d){return a>b&&a<b+d},isOver:function(a,b,d,e,f,g){return c.ui.isOverAxis(a,d,f)&&c.ui.isOverAxis(b,e,g)},keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,
|
||||
PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38}};c.fn.extend({_focus:c.fn.focus,focus:function(a,b){return typeof a==="number"?this.each(function(){var d=this;setTimeout(function(){c(d).focus();b&&b.call(d)},a)}):this._focus.apply(this,arguments)},enableSelection:function(){return this.attr("unselectable","off").css("MozUserSelect","")},disableSelection:function(){return this.attr("unselectable","on").css("MozUserSelect","none")},scrollParent:function(){var a;a=c.browser.msie&&/(static|relative)/.test(this.css("position"))||
|
||||
/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(c.curCSS(this,"position",1))&&/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0);return/fixed/.test(this.css("position"))||!a.length?c(document):a},zIndex:function(a){if(a!==
|
||||
undefined)return this.css("zIndex",a);if(this.length){a=c(this[0]);for(var b;a.length&&a[0]!==document;){b=a.css("position");if(b=="absolute"||b=="relative"||b=="fixed"){b=parseInt(a.css("zIndex"));if(!isNaN(b)&&b!=0)return b}a=a.parent()}}return 0}});c.extend(c.expr[":"],{data:function(a,b,d){return!!c.data(a,d[3])},focusable:function(a){var b=a.nodeName.toLowerCase(),d=c.attr(a,"tabindex");return(/input|select|textarea|button|object/.test(b)?!a.disabled:"a"==b||"area"==b?a.href||!isNaN(d):!isNaN(d))&&
|
||||
!c(a)["area"==b?"parents":"closest"](":hidden").length},tabbable:function(a){var b=c.attr(a,"tabindex");return(isNaN(b)||b>=0)&&c(a).is(":focusable")}})}(jQuery);
|
||||
;/*!
|
||||
* jQuery UI Widget 1.8.1
|
||||
*
|
||||
* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
||||
* and GPL (GPL-LICENSE.txt) licenses.
|
||||
*
|
||||
* http://docs.jquery.com/UI/Widget
|
||||
*/
|
||||
(function(b){var j=b.fn.remove;b.fn.remove=function(a,c){return this.each(function(){if(!c)if(!a||b.filter(a,[this]).length)b("*",this).add(this).each(function(){b(this).triggerHandler("remove")});return j.call(b(this),a,c)})};b.widget=function(a,c,d){var e=a.split(".")[0],f;a=a.split(".")[1];f=e+"-"+a;if(!d){d=c;c=b.Widget}b.expr[":"][f]=function(h){return!!b.data(h,a)};b[e]=b[e]||{};b[e][a]=function(h,g){arguments.length&&this._createWidget(h,g)};c=new c;c.options=b.extend({},c.options);b[e][a].prototype=
|
||||
b.extend(true,c,{namespace:e,widgetName:a,widgetEventPrefix:b[e][a].prototype.widgetEventPrefix||a,widgetBaseClass:f},d);b.widget.bridge(a,b[e][a])};b.widget.bridge=function(a,c){b.fn[a]=function(d){var e=typeof d==="string",f=Array.prototype.slice.call(arguments,1),h=this;d=!e&&f.length?b.extend.apply(null,[true,d].concat(f)):d;if(e&&d.substring(0,1)==="_")return h;e?this.each(function(){var g=b.data(this,a),i=g&&b.isFunction(g[d])?g[d].apply(g,f):g;if(i!==g&&i!==undefined){h=i;return false}}):this.each(function(){var g=
|
||||
b.data(this,a);if(g){d&&g.option(d);g._init()}else b.data(this,a,new c(d,this))});return h}};b.Widget=function(a,c){arguments.length&&this._createWidget(a,c)};b.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:false},_createWidget:function(a,c){this.element=b(c).data(this.widgetName,this);this.options=b.extend(true,{},this.options,b.metadata&&b.metadata.get(c)[this.widgetName],a);var d=this;this.element.bind("remove."+this.widgetName,function(){d.destroy()});this._create();
|
||||
this._init()},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName);this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled ui-state-disabled")},widget:function(){return this.element},option:function(a,c){var d=a,e=this;if(arguments.length===0)return b.extend({},e.options);if(typeof a==="string"){if(c===undefined)return this.options[a];d={};d[a]=c}b.each(d,function(f,
|
||||
h){e._setOption(f,h)});return e},_setOption:function(a,c){this.options[a]=c;if(a==="disabled")this.widget()[c?"addClass":"removeClass"](this.widgetBaseClass+"-disabled ui-state-disabled").attr("aria-disabled",c);return this},enable:function(){return this._setOption("disabled",false)},disable:function(){return this._setOption("disabled",true)},_trigger:function(a,c,d){var e=this.options[a];c=b.Event(c);c.type=(a===this.widgetEventPrefix?a:this.widgetEventPrefix+a).toLowerCase();d=d||{};if(c.originalEvent){a=
|
||||
b.event.props.length;for(var f;a;){f=b.event.props[--a];c[f]=c.originalEvent[f]}}this.element.trigger(c,d);return!(b.isFunction(e)&&e.call(this.element[0],c,d)===false||c.isDefaultPrevented())}}})(jQuery);
|
||||
;/*!
|
||||
* jQuery UI Mouse 1.8.1
|
||||
*
|
||||
* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
||||
* and GPL (GPL-LICENSE.txt) licenses.
|
||||
*
|
||||
* http://docs.jquery.com/UI/Mouse
|
||||
*
|
||||
* Depends:
|
||||
* jquery.ui.widget.js
|
||||
*/
|
||||
(function(c){c.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var a=this;this.element.bind("mousedown."+this.widgetName,function(b){return a._mouseDown(b)}).bind("click."+this.widgetName,function(b){if(a._preventClickEvent){a._preventClickEvent=false;b.stopImmediatePropagation();return false}});this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName)},_mouseDown:function(a){a.originalEvent=a.originalEvent||{};if(!a.originalEvent.mouseHandled){this._mouseStarted&&
|
||||
this._mouseUp(a);this._mouseDownEvent=a;var b=this,e=a.which==1,f=typeof this.options.cancel=="string"?c(a.target).parents().add(a.target).filter(this.options.cancel).length:false;if(!e||f||!this._mouseCapture(a))return true;this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet)this._mouseDelayTimer=setTimeout(function(){b.mouseDelayMet=true},this.options.delay);if(this._mouseDistanceMet(a)&&this._mouseDelayMet(a)){this._mouseStarted=this._mouseStart(a)!==false;if(!this._mouseStarted){a.preventDefault();
|
||||
return true}}this._mouseMoveDelegate=function(d){return b._mouseMove(d)};this._mouseUpDelegate=function(d){return b._mouseUp(d)};c(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);c.browser.safari||a.preventDefault();return a.originalEvent.mouseHandled=true}},_mouseMove:function(a){if(c.browser.msie&&!a.button)return this._mouseUp(a);if(this._mouseStarted){this._mouseDrag(a);return a.preventDefault()}if(this._mouseDistanceMet(a)&&
|
||||
this._mouseDelayMet(a))(this._mouseStarted=this._mouseStart(this._mouseDownEvent,a)!==false)?this._mouseDrag(a):this._mouseUp(a);return!this._mouseStarted},_mouseUp:function(a){c(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;this._preventClickEvent=a.target==this._mouseDownEvent.target;this._mouseStop(a)}return false},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX-
|
||||
a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return true}})})(jQuery);
|
||||
;/*
|
||||
* jQuery UI Sortable 1.8.1
|
||||
*
|
||||
* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
||||
* and GPL (GPL-LICENSE.txt) licenses.
|
||||
*
|
||||
* http://docs.jquery.com/UI/Sortables
|
||||
*
|
||||
* Depends:
|
||||
* jquery.ui.core.js
|
||||
* jquery.ui.mouse.js
|
||||
* jquery.ui.widget.js
|
||||
*/
|
||||
(function(d){d.widget("ui.sortable",d.ui.mouse,{widgetEventPrefix:"sort",options:{appendTo:"parent",axis:false,connectWith:false,containment:false,cursor:"auto",cursorAt:false,dropOnEmpty:true,forcePlaceholderSize:false,forceHelperSize:false,grid:false,handle:false,helper:"original",items:"> *",opacity:false,placeholder:false,revert:false,scroll:true,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1E3},_create:function(){this.containerCache={};this.element.addClass("ui-sortable");
|
||||
this.refresh();this.floating=this.items.length?/left|right/.test(this.items[0].item.css("float")):false;this.offset=this.element.offset();this._mouseInit()},destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").removeData("sortable").unbind(".sortable");this._mouseDestroy();for(var a=this.items.length-1;a>=0;a--)this.items[a].item.removeData("sortable-item");return this},_setOption:function(a,b){if(a==="disabled"){this.options[a]=b;this.widget()[b?"addClass":"removeClass"]("ui-sortable-disabled")}else d.Widget.prototype._setOption.apply(self,
|
||||
arguments)},_mouseCapture:function(a,b){if(this.reverting)return false;if(this.options.disabled||this.options.type=="static")return false;this._refreshItems(a);var c=null,e=this;d(a.target).parents().each(function(){if(d.data(this,"sortable-item")==e){c=d(this);return false}});if(d.data(a.target,"sortable-item")==e)c=d(a.target);if(!c)return false;if(this.options.handle&&!b){var f=false;d(this.options.handle,c).find("*").andSelf().each(function(){if(this==a.target)f=true});if(!f)return false}this.currentItem=
|
||||
c;this._removeCurrentsFromItems();return true},_mouseStart:function(a,b,c){b=this.options;var e=this;this.currentContainer=this;this.refreshPositions();this.helper=this._createHelper(a);this._cacheHelperProportions();this._cacheMargins();this.scrollParent=this.helper.scrollParent();this.offset=this.currentItem.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};this.helper.css("position","absolute");this.cssPosition=this.helper.css("position");d.extend(this.offset,
|
||||
{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]};this.helper[0]!=this.currentItem[0]&&this.currentItem.hide();this._createPlaceholder();b.containment&&this._setContainment();
|
||||
if(b.cursor){if(d("body").css("cursor"))this._storedCursor=d("body").css("cursor");d("body").css("cursor",b.cursor)}if(b.opacity){if(this.helper.css("opacity"))this._storedOpacity=this.helper.css("opacity");this.helper.css("opacity",b.opacity)}if(b.zIndex){if(this.helper.css("zIndex"))this._storedZIndex=this.helper.css("zIndex");this.helper.css("zIndex",b.zIndex)}if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML")this.overflowOffset=this.scrollParent.offset();this._trigger("start",
|
||||
a,this._uiHash());this._preserveHelperProportions||this._cacheHelperProportions();if(!c)for(c=this.containers.length-1;c>=0;c--)this.containers[c]._trigger("activate",a,e._uiHash(this));if(d.ui.ddmanager)d.ui.ddmanager.current=this;d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.dragging=true;this.helper.addClass("ui-sortable-helper");this._mouseDrag(a);return true},_mouseDrag:function(a){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute");
|
||||
if(!this.lastPositionAbs)this.lastPositionAbs=this.positionAbs;if(this.options.scroll){var b=this.options,c=false;if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){if(this.overflowOffset.top+this.scrollParent[0].offsetHeight-a.pageY<b.scrollSensitivity)this.scrollParent[0].scrollTop=c=this.scrollParent[0].scrollTop+b.scrollSpeed;else if(a.pageY-this.overflowOffset.top<b.scrollSensitivity)this.scrollParent[0].scrollTop=c=this.scrollParent[0].scrollTop-b.scrollSpeed;if(this.overflowOffset.left+
|
||||
this.scrollParent[0].offsetWidth-a.pageX<b.scrollSensitivity)this.scrollParent[0].scrollLeft=c=this.scrollParent[0].scrollLeft+b.scrollSpeed;else if(a.pageX-this.overflowOffset.left<b.scrollSensitivity)this.scrollParent[0].scrollLeft=c=this.scrollParent[0].scrollLeft-b.scrollSpeed}else{if(a.pageY-d(document).scrollTop()<b.scrollSensitivity)c=d(document).scrollTop(d(document).scrollTop()-b.scrollSpeed);else if(d(window).height()-(a.pageY-d(document).scrollTop())<b.scrollSensitivity)c=d(document).scrollTop(d(document).scrollTop()+
|
||||
b.scrollSpeed);if(a.pageX-d(document).scrollLeft()<b.scrollSensitivity)c=d(document).scrollLeft(d(document).scrollLeft()-b.scrollSpeed);else if(d(window).width()-(a.pageX-d(document).scrollLeft())<b.scrollSensitivity)c=d(document).scrollLeft(d(document).scrollLeft()+b.scrollSpeed)}c!==false&&d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a)}this.positionAbs=this._convertPositionTo("absolute");if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+
|
||||
"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";for(b=this.items.length-1;b>=0;b--){c=this.items[b];var e=c.item[0],f=this._intersectsWithPointer(c);if(f)if(e!=this.currentItem[0]&&this.placeholder[f==1?"next":"prev"]()[0]!=e&&!d.ui.contains(this.placeholder[0],e)&&(this.options.type=="semi-dynamic"?!d.ui.contains(this.element[0],e):true)){this.direction=f==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(c))this._rearrange(a,
|
||||
c);else break;this._trigger("change",a,this._uiHash());break}}this._contactContainers(a);d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);this._trigger("sort",a,this._uiHash());this.lastPositionAbs=this.positionAbs;return false},_mouseStop:function(a,b){if(a){d.ui.ddmanager&&!this.options.dropBehaviour&&d.ui.ddmanager.drop(this,a);if(this.options.revert){var c=this;b=c.placeholder.offset();c.reverting=true;d(this.helper).animate({left:b.left-this.offset.parent.left-c.margins.left+(this.offsetParent[0]==
|
||||
document.body?0:this.offsetParent[0].scrollLeft),top:b.top-this.offset.parent.top-c.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){c._clear(a)})}else this._clear(a,b);return false}},cancel:function(){var a=this;if(this.dragging){this._mouseUp();this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var b=this.containers.length-1;b>=0;b--){this.containers[b]._trigger("deactivate",
|
||||
null,a._uiHash(this));if(this.containers[b].containerCache.over){this.containers[b]._trigger("out",null,a._uiHash(this));this.containers[b].containerCache.over=0}}}this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]);this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove();d.extend(this,{helper:null,dragging:false,reverting:false,_noFinalSort:null});this.domPosition.prev?d(this.domPosition.prev).after(this.currentItem):
|
||||
d(this.domPosition.parent).prepend(this.currentItem);return this},serialize:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};d(b).each(function(){var e=(d(a.item||this).attr(a.attribute||"id")||"").match(a.expression||/(.+)[-=_](.+)/);if(e)c.push((a.key||e[1]+"[]")+"="+(a.key&&a.expression?e[1]:e[2]))});return c.join("&")},toArray:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};b.each(function(){c.push(d(a.item||this).attr(a.attribute||"id")||"")});return c},
|
||||
_intersectsWith:function(a){var b=this.positionAbs.left,c=b+this.helperProportions.width,e=this.positionAbs.top,f=e+this.helperProportions.height,g=a.left,h=g+a.width,i=a.top,k=i+a.height,j=this.offset.click.top,l=this.offset.click.left;j=e+j>i&&e+j<k&&b+l>g&&b+l<h;return this.options.tolerance=="pointer"||this.options.forcePointerForContainers||this.options.tolerance!="pointer"&&this.helperProportions[this.floating?"width":"height"]>a[this.floating?"width":"height"]?j:g<b+this.helperProportions.width/
|
||||
2&&c-this.helperProportions.width/2<h&&i<e+this.helperProportions.height/2&&f-this.helperProportions.height/2<k},_intersectsWithPointer:function(a){var b=d.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,a.top,a.height);a=d.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,a.left,a.width);b=b&&a;a=this._getDragVerticalDirection();var c=this._getDragHorizontalDirection();if(!b)return false;return this.floating?c&&c=="right"||a=="down"?2:1:a&&(a=="down"?2:1)},_intersectsWithSides:function(a){var b=
|
||||
d.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,a.top+a.height/2,a.height);a=d.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,a.left+a.width/2,a.width);var c=this._getDragVerticalDirection(),e=this._getDragHorizontalDirection();return this.floating&&e?e=="right"&&a||e=="left"&&!a:c&&(c=="down"&&b||c=="up"&&!b)},_getDragVerticalDirection:function(){var a=this.positionAbs.top-this.lastPositionAbs.top;return a!=0&&(a>0?"down":"up")},_getDragHorizontalDirection:function(){var a=
|
||||
this.positionAbs.left-this.lastPositionAbs.left;return a!=0&&(a>0?"right":"left")},refresh:function(a){this._refreshItems(a);this.refreshPositions();return this},_connectWith:function(){var a=this.options;return a.connectWith.constructor==String?[a.connectWith]:a.connectWith},_getItemsAsjQuery:function(a){var b=[],c=[],e=this._connectWith();if(e&&a)for(a=e.length-1;a>=0;a--)for(var f=d(e[a]),g=f.length-1;g>=0;g--){var h=d.data(f[g],"sortable");if(h&&h!=this&&!h.options.disabled)c.push([d.isFunction(h.options.items)?
|
||||
h.options.items.call(h.element):d(h.options.items,h.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),h])}c.push([d.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):d(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);for(a=c.length-1;a>=0;a--)c[a][0].each(function(){b.push(this)});return d(b)},_removeCurrentsFromItems:function(){for(var a=this.currentItem.find(":data(sortable-item)"),
|
||||
b=0;b<this.items.length;b++)for(var c=0;c<a.length;c++)a[c]==this.items[b].item[0]&&this.items.splice(b,1)},_refreshItems:function(a){this.items=[];this.containers=[this];var b=this.items,c=[[d.isFunction(this.options.items)?this.options.items.call(this.element[0],a,{item:this.currentItem}):d(this.options.items,this.element),this]],e=this._connectWith();if(e)for(var f=e.length-1;f>=0;f--)for(var g=d(e[f]),h=g.length-1;h>=0;h--){var i=d.data(g[h],"sortable");if(i&&i!=this&&!i.options.disabled){c.push([d.isFunction(i.options.items)?
|
||||
i.options.items.call(i.element[0],a,{item:this.currentItem}):d(i.options.items,i.element),i]);this.containers.push(i)}}for(f=c.length-1;f>=0;f--){a=c[f][1];e=c[f][0];h=0;for(g=e.length;h<g;h++){i=d(e[h]);i.data("sortable-item",a);b.push({item:i,instance:a,width:0,height:0,left:0,top:0})}}},refreshPositions:function(a){if(this.offsetParent&&this.helper)this.offset.parent=this._getParentOffset();for(var b=this.items.length-1;b>=0;b--){var c=this.items[b],e=this.options.toleranceElement?d(this.options.toleranceElement,
|
||||
c.item):c.item;if(!a){c.width=e.outerWidth();c.height=e.outerHeight()}e=e.offset();c.left=e.left;c.top=e.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(b=this.containers.length-1;b>=0;b--){e=this.containers[b].element.offset();this.containers[b].containerCache.left=e.left;this.containers[b].containerCache.top=e.top;this.containers[b].containerCache.width=this.containers[b].element.outerWidth();this.containers[b].containerCache.height=
|
||||
this.containers[b].element.outerHeight()}return this},_createPlaceholder:function(a){var b=a||this,c=b.options;if(!c.placeholder||c.placeholder.constructor==String){var e=c.placeholder;c.placeholder={element:function(){var f=d(document.createElement(b.currentItem[0].nodeName)).addClass(e||b.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];if(!e)f.style.visibility="hidden";return f},update:function(f,g){if(!(e&&!c.forcePlaceholderSize)){g.height()||g.height(b.currentItem.innerHeight()-
|
||||
parseInt(b.currentItem.css("paddingTop")||0,10)-parseInt(b.currentItem.css("paddingBottom")||0,10));g.width()||g.width(b.currentItem.innerWidth()-parseInt(b.currentItem.css("paddingLeft")||0,10)-parseInt(b.currentItem.css("paddingRight")||0,10))}}}}b.placeholder=d(c.placeholder.element.call(b.element,b.currentItem));b.currentItem.after(b.placeholder);c.placeholder.update(b,b.placeholder)},_contactContainers:function(a){for(var b=null,c=null,e=this.containers.length-1;e>=0;e--)if(!d.ui.contains(this.currentItem[0],
|
||||
this.containers[e].element[0]))if(this._intersectsWith(this.containers[e].containerCache)){if(!(b&&d.ui.contains(this.containers[e].element[0],b.element[0]))){b=this.containers[e];c=e}}else if(this.containers[e].containerCache.over){this.containers[e]._trigger("out",a,this._uiHash(this));this.containers[e].containerCache.over=0}if(b)if(this.containers.length===1){this.containers[c]._trigger("over",a,this._uiHash(this));this.containers[c].containerCache.over=1}else if(this.currentContainer!=this.containers[c]){b=
|
||||
1E4;e=null;for(var f=this.positionAbs[this.containers[c].floating?"left":"top"],g=this.items.length-1;g>=0;g--)if(d.ui.contains(this.containers[c].element[0],this.items[g].item[0])){var h=this.items[g][this.containers[c].floating?"left":"top"];if(Math.abs(h-f)<b){b=Math.abs(h-f);e=this.items[g]}}if(e||this.options.dropOnEmpty){this.currentContainer=this.containers[c];e?this._rearrange(a,e,null,true):this._rearrange(a,null,this.containers[c].element,true);this._trigger("change",a,this._uiHash());this.containers[c]._trigger("change",
|
||||
a,this._uiHash(this));this.options.placeholder.update(this.currentContainer,this.placeholder);this.containers[c]._trigger("over",a,this._uiHash(this));this.containers[c].containerCache.over=1}}},_createHelper:function(a){var b=this.options;a=d.isFunction(b.helper)?d(b.helper.apply(this.element[0],[a,this.currentItem])):b.helper=="clone"?this.currentItem.clone():this.currentItem;a.parents("body").length||d(b.appendTo!="parent"?b.appendTo:this.currentItem[0].parentNode)[0].appendChild(a[0]);if(a[0]==
|
||||
this.currentItem[0])this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")};if(a[0].style.width==""||b.forceHelperSize)a.width(this.currentItem.width());if(a[0].style.height==""||b.forceHelperSize)a.height(this.currentItem.height());return a},_adjustOffsetFromHelper:function(a){if(typeof a=="string")a=a.split(" ");if(d.isArray(a))a={left:+a[0],top:+a[1]||
|
||||
0};if("left"in a)this.offset.click.left=a.left+this.margins.left;if("right"in a)this.offset.click.left=this.helperProportions.width-a.right+this.margins.left;if("top"in a)this.offset.click.top=a.top+this.margins.top;if("bottom"in a)this.offset.click.top=this.helperProportions.height-a.bottom+this.margins.top},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var a=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],
|
||||
this.offsetParent[0])){a.left+=this.scrollParent.scrollLeft();a.top+=this.scrollParent.scrollTop()}if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&d.browser.msie)a={top:0,left:0};return{top:a.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:a.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.currentItem.position();return{top:a.top-
|
||||
(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var a=this.options;
|
||||
if(a.containment=="parent")a.containment=this.helper[0].parentNode;if(a.containment=="document"||a.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,d(a.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(d(a.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(a.containment)){var b=
|
||||
d(a.containment)[0];a=d(a.containment).offset();var c=d(b).css("overflow")!="hidden";this.containment=[a.left+(parseInt(d(b).css("borderLeftWidth"),10)||0)+(parseInt(d(b).css("paddingLeft"),10)||0)-this.margins.left,a.top+(parseInt(d(b).css("borderTopWidth"),10)||0)+(parseInt(d(b).css("paddingTop"),10)||0)-this.margins.top,a.left+(c?Math.max(b.scrollWidth,b.offsetWidth):b.offsetWidth)-(parseInt(d(b).css("borderLeftWidth"),10)||0)-(parseInt(d(b).css("paddingRight"),10)||0)-this.helperProportions.width-
|
||||
this.margins.left,a.top+(c?Math.max(b.scrollHeight,b.offsetHeight):b.offsetHeight)-(parseInt(d(b).css("borderTopWidth"),10)||0)-(parseInt(d(b).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}},_convertPositionTo:function(a,b){if(!b)b=this.position;a=a=="absolute"?1:-1;var c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,e=/(html|body)/i.test(c[0].tagName);return{top:b.top+
|
||||
this.offset.relative.top*a+this.offset.parent.top*a-(d.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():e?0:c.scrollTop())*a),left:b.left+this.offset.relative.left*a+this.offset.parent.left*a-(d.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():e?0:c.scrollLeft())*a)}},_generatePosition:function(a){var b=this.options,c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],
|
||||
this.offsetParent[0]))?this.offsetParent:this.scrollParent,e=/(html|body)/i.test(c[0].tagName);if(this.cssPosition=="relative"&&!(this.scrollParent[0]!=document&&this.scrollParent[0]!=this.offsetParent[0]))this.offset.relative=this._getRelativeOffset();var f=a.pageX,g=a.pageY;if(this.originalPosition){if(this.containment){if(a.pageX-this.offset.click.left<this.containment[0])f=this.containment[0]+this.offset.click.left;if(a.pageY-this.offset.click.top<this.containment[1])g=this.containment[1]+this.offset.click.top;
|
||||
if(a.pageX-this.offset.click.left>this.containment[2])f=this.containment[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>this.containment[3])g=this.containment[3]+this.offset.click.top}if(b.grid){g=this.originalPageY+Math.round((g-this.originalPageY)/b.grid[1])*b.grid[1];g=this.containment?!(g-this.offset.click.top<this.containment[1]||g-this.offset.click.top>this.containment[3])?g:!(g-this.offset.click.top<this.containment[1])?g-b.grid[1]:g+b.grid[1]:g;f=this.originalPageX+Math.round((f-
|
||||
this.originalPageX)/b.grid[0])*b.grid[0];f=this.containment?!(f-this.offset.click.left<this.containment[0]||f-this.offset.click.left>this.containment[2])?f:!(f-this.offset.click.left<this.containment[0])?f-b.grid[0]:f+b.grid[0]:f}}return{top:g-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(d.browser.safari&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():e?0:c.scrollTop()),left:f-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+
|
||||
(d.browser.safari&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():e?0:c.scrollLeft())}},_rearrange:function(a,b,c,e){c?c[0].appendChild(this.placeholder[0]):b.item[0].parentNode.insertBefore(this.placeholder[0],this.direction=="down"?b.item[0]:b.item[0].nextSibling);this.counter=this.counter?++this.counter:1;var f=this,g=this.counter;window.setTimeout(function(){g==f.counter&&f.refreshPositions(!e)},0)},_clear:function(a,b){this.reverting=false;var c=[];!this._noFinalSort&&
|
||||
this.currentItem[0].parentNode&&this.placeholder.before(this.currentItem);this._noFinalSort=null;if(this.helper[0]==this.currentItem[0]){for(var e in this._storedCSS)if(this._storedCSS[e]=="auto"||this._storedCSS[e]=="static")this._storedCSS[e]="";this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();this.fromOutside&&!b&&c.push(function(f){this._trigger("receive",f,this._uiHash(this.fromOutside))});if((this.fromOutside||this.domPosition.prev!=this.currentItem.prev().not(".ui-sortable-helper")[0]||
|
||||
this.domPosition.parent!=this.currentItem.parent()[0])&&!b)c.push(function(f){this._trigger("update",f,this._uiHash())});if(!d.ui.contains(this.element[0],this.currentItem[0])){b||c.push(function(f){this._trigger("remove",f,this._uiHash())});for(e=this.containers.length-1;e>=0;e--)if(d.ui.contains(this.containers[e].element[0],this.currentItem[0])&&!b){c.push(function(f){return function(g){f._trigger("receive",g,this._uiHash(this))}}.call(this,this.containers[e]));c.push(function(f){return function(g){f._trigger("update",
|
||||
g,this._uiHash(this))}}.call(this,this.containers[e]))}}for(e=this.containers.length-1;e>=0;e--){b||c.push(function(f){return function(g){f._trigger("deactivate",g,this._uiHash(this))}}.call(this,this.containers[e]));if(this.containers[e].containerCache.over){c.push(function(f){return function(g){f._trigger("out",g,this._uiHash(this))}}.call(this,this.containers[e]));this.containers[e].containerCache.over=0}}this._storedCursor&&d("body").css("cursor",this._storedCursor);this._storedOpacity&&this.helper.css("opacity",
|
||||
this._storedOpacity);if(this._storedZIndex)this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex);this.dragging=false;if(this.cancelHelperRemoval){if(!b){this._trigger("beforeStop",a,this._uiHash());for(e=0;e<c.length;e++)c[e].call(this,a);this._trigger("stop",a,this._uiHash())}return false}b||this._trigger("beforeStop",a,this._uiHash());this.placeholder[0].parentNode.removeChild(this.placeholder[0]);this.helper[0]!=this.currentItem[0]&&this.helper.remove();this.helper=null;if(!b){for(e=
|
||||
0;e<c.length;e++)c[e].call(this,a);this._trigger("stop",a,this._uiHash())}this.fromOutside=false;return true},_trigger:function(){d.Widget.prototype._trigger.apply(this,arguments)===false&&this.cancel()},_uiHash:function(a){var b=a||this;return{helper:b.helper,placeholder:b.placeholder||d([]),position:b.position,originalPosition:b.originalPosition,offset:b.positionAbs,item:b.currentItem,sender:a?a.element:null}}});d.extend(d.ui.sortable,{version:"1.8.1"})})(jQuery);
|
||||
;
|
||||
@@ -0,0 +1,108 @@
|
||||
ig.module(
|
||||
'weltmeister.modal-dialogs'
|
||||
)
|
||||
.requires(
|
||||
'weltmeister.select-file-dropdown'
|
||||
)
|
||||
.defines(function(){ "use strict";
|
||||
|
||||
wm.ModalDialog = ig.Class.extend({
|
||||
onOk: null,
|
||||
onCancel: null,
|
||||
|
||||
text: '',
|
||||
okText: '',
|
||||
cancelText: '',
|
||||
|
||||
background: null,
|
||||
dialogBox: null,
|
||||
buttonDiv: null,
|
||||
|
||||
init: function( text, okText, cancelText ) {
|
||||
this.text = text;
|
||||
this.okText = okText || 'OK';
|
||||
this.cancelText = cancelText || 'Cancel';
|
||||
|
||||
this.background = $('<div/>', {'class':'modalDialogBackground'});
|
||||
this.dialogBox = $('<div/>', {'class':'modalDialogBox'});
|
||||
this.background.append( this.dialogBox );
|
||||
$('body').append( this.background );
|
||||
|
||||
this.initDialog( text );
|
||||
},
|
||||
|
||||
|
||||
initDialog: function() {
|
||||
this.buttonDiv = $('<div/>', {'class': 'modalDialogButtons'} );
|
||||
var okButton = $('<input/>', {'type': 'button', 'class':'button', 'value': this.okText});
|
||||
var cancelButton = $('<input/>', {'type': 'button', 'class':'button', 'value': this.cancelText});
|
||||
|
||||
okButton.bind( 'click', this.clickOk.bind(this) );
|
||||
cancelButton.bind( 'click', this.clickCancel.bind(this) );
|
||||
|
||||
this.buttonDiv.append( okButton ).append( cancelButton );
|
||||
|
||||
this.dialogBox.html('<div class="modalDialogText">' + this.text + '</div>' );
|
||||
this.dialogBox.append( this.buttonDiv );
|
||||
},
|
||||
|
||||
|
||||
clickOk: function() {
|
||||
if( this.onOk ) { this.onOk(this); }
|
||||
this.close();
|
||||
},
|
||||
|
||||
|
||||
clickCancel: function() {
|
||||
if( this.onCancel ) { this.onCancel(this); }
|
||||
this.close();
|
||||
},
|
||||
|
||||
|
||||
open: function() {
|
||||
this.background.fadeIn(100);
|
||||
},
|
||||
|
||||
|
||||
close: function() {
|
||||
this.background.fadeOut(100);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
wm.ModalDialogPathSelect = wm.ModalDialog.extend({
|
||||
pathDropdown: null,
|
||||
pathInput: null,
|
||||
fileType: '',
|
||||
|
||||
init: function( text, okText, type ) {
|
||||
this.fileType = type || '';
|
||||
this.parent( text, (okText || 'Select') );
|
||||
},
|
||||
|
||||
|
||||
setPath: function( path ) {
|
||||
var dir = path.replace(/\/[^\/]*$/, '');
|
||||
this.pathInput.val( path );
|
||||
this.pathDropdown.loadDir( dir );
|
||||
},
|
||||
|
||||
|
||||
initDialog: function() {
|
||||
this.parent();
|
||||
this.pathInput = $('<input/>', {'type': 'text', 'class': 'modalDialogPath'} );
|
||||
this.buttonDiv.before( this.pathInput );
|
||||
this.pathDropdown = new wm.SelectFileDropdown( this.pathInput, wm.config.api.browse, this.fileType );
|
||||
},
|
||||
|
||||
|
||||
clickOk: function() {
|
||||
if( this.onOk ) {
|
||||
this.onOk(this, this.pathInput.val());
|
||||
}
|
||||
this.close();
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,99 @@
|
||||
ig.module(
|
||||
'weltmeister.select-file-dropdown'
|
||||
)
|
||||
.defines(function(){ "use strict";
|
||||
|
||||
wm.SelectFileDropdown = ig.Class.extend({
|
||||
input: null,
|
||||
boundShow: null,
|
||||
div: null,
|
||||
filelistPHP: '',
|
||||
filetype: '',
|
||||
|
||||
init: function( elementId, filelistPHP, filetype ) {
|
||||
this.filetype = filetype || '';
|
||||
this.filelistPHP = filelistPHP;
|
||||
this.input = $(elementId);
|
||||
this.boundHide = this.hide.bind(this);
|
||||
this.input.bind('focus', this.show.bind(this) );
|
||||
|
||||
this.div = $('<div/>', {'class':'selectFileDialog'});
|
||||
this.input.after( this.div );
|
||||
this.div.bind('mousedown', this.noHide.bind(this) );
|
||||
|
||||
this.loadDir( '' );
|
||||
},
|
||||
|
||||
|
||||
loadDir: function( dir ) {
|
||||
var path = this.filelistPHP + '?dir=' + encodeURIComponent( dir || '' ) + '&type=' + this.filetype;
|
||||
var req = $.ajax({
|
||||
url:path,
|
||||
dataType: 'json',
|
||||
async: false,
|
||||
success:this.showFiles.bind(this)
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
selectDir: function( event ) {
|
||||
this.loadDir( $(event.target).attr('href') );
|
||||
return false;
|
||||
},
|
||||
|
||||
|
||||
selectFile: function( event ) {
|
||||
this.input.val( $(event.target).attr('href') );
|
||||
this.input.blur();
|
||||
this.hide();
|
||||
return false;
|
||||
},
|
||||
|
||||
|
||||
showFiles: function( data ) {
|
||||
this.div.empty();
|
||||
if( data.parent !== false ) {
|
||||
var parentDir = $('<a/>', {'class':'dir', href:data.parent, html: '…parent directory'});
|
||||
parentDir.bind( 'click', this.selectDir.bind(this) );
|
||||
this.div.append( parentDir );
|
||||
}
|
||||
for( var i = 0; i < data.dirs.length; i++ ) {
|
||||
var name = data.dirs[i].match(/[^\/]*$/)[0] + '/';
|
||||
var dir = $('<a/>', {'class':'dir', href:data.dirs[i], html: name, title: name});
|
||||
dir.bind( 'click', this.selectDir.bind(this) );
|
||||
this.div.append( dir );
|
||||
}
|
||||
for( var i = 0; i < data.files.length; i++ ) {
|
||||
var name = data.files[i].match(/[^\/]*$/)[0];
|
||||
var file = $('<a/>', {'class':'file', href:data.files[i], html: name, title: name});
|
||||
file.bind( 'click', this.selectFile.bind(this) );
|
||||
this.div.append( file );
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
noHide: function(event) {
|
||||
event.stopPropagation();
|
||||
},
|
||||
|
||||
|
||||
show: function( event ) {
|
||||
var inputPos = this.input.position();//this.input.getPosition(this.input.getOffsetParent());
|
||||
var inputHeight = parseInt(this.input.innerHeight()) + parseInt(this.input.css('margin-top'));
|
||||
var inputWidth = this.input.innerWidth();
|
||||
$(document).bind( 'mousedown', this.boundHide );
|
||||
this.div.css({
|
||||
'top': inputPos.top + inputHeight + 1,
|
||||
'left': inputPos.left,
|
||||
'width': inputWidth
|
||||
}).slideDown(100);
|
||||
},
|
||||
|
||||
|
||||
hide: function() {
|
||||
$(document).unbind( 'mousedown', this.boundHide );
|
||||
this.div.slideUp(100);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,155 @@
|
||||
ig.module(
|
||||
'weltmeister.tile-select'
|
||||
)
|
||||
.defines(function(){ "use strict";
|
||||
|
||||
wm.TileSelect = ig.Class.extend({
|
||||
|
||||
pos: {x:0, y:0},
|
||||
|
||||
layer: null,
|
||||
selectionBegin: null,
|
||||
|
||||
init: function( layer ) {
|
||||
this.layer = layer;
|
||||
},
|
||||
|
||||
|
||||
getCurrentTile: function() {
|
||||
var b = this.layer.brush;
|
||||
if( b.length == 1 && b[0].length == 1 ) {
|
||||
return b[0][0] - 1;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
setPosition: function( x, y ) {
|
||||
this.selectionBegin = null;
|
||||
var tile = this.getCurrentTile();
|
||||
this.pos.x =
|
||||
Math.floor( x / this.layer.tilesize ) * this.layer.tilesize
|
||||
- Math.floor( tile * this.layer.tilesize ) % this.layer.tiles.width;
|
||||
|
||||
this.pos.y =
|
||||
Math.floor( y / this.layer.tilesize ) * this.layer.tilesize
|
||||
- Math.floor( tile * this.layer.tilesize / this.layer.tiles.width ) * this.layer.tilesize
|
||||
- (tile == -1 ? this.layer.tilesize : 0);
|
||||
|
||||
this.pos.x = this.pos.x.limit( 0, ig.system.width - this.layer.tiles.width - (ig.system.width % this.layer.tilesize) );
|
||||
this.pos.y = this.pos.y.limit( 0, ig.system.height - this.layer.tiles.height - (ig.system.height % this.layer.tilesize) );
|
||||
},
|
||||
|
||||
|
||||
beginSelecting: function( x, y ) {
|
||||
this.selectionBegin = {x:x, y:y};
|
||||
},
|
||||
|
||||
|
||||
endSelecting: function( x, y ) {
|
||||
var r = this.getSelectionRect( x, y);
|
||||
|
||||
var mw = Math.floor( this.layer.tiles.width / this.layer.tilesize );
|
||||
var mh = Math.floor( this.layer.tiles.height / this.layer.tilesize );
|
||||
|
||||
var brush = [];
|
||||
for( var ty = r.y; ty < r.y+r.h; ty++ ) {
|
||||
var row = [];
|
||||
for( var tx = r.x; tx < r.x+r.w; tx++ ) {
|
||||
if( tx < 0 || ty < 0 || tx >= mw || ty >= mh) {
|
||||
row.push( 0 );
|
||||
}
|
||||
else {
|
||||
row.push( ty * Math.floor(this.layer.tiles.width / this.layer.tilesize) + tx + 1 );
|
||||
}
|
||||
}
|
||||
brush.push( row );
|
||||
}
|
||||
this.selectionBegin = null;
|
||||
return brush;
|
||||
},
|
||||
|
||||
|
||||
getSelectionRect: function( x, y ) {
|
||||
var sx = this.selectionBegin ? this.selectionBegin.x : x,
|
||||
sy = this.selectionBegin ? this.selectionBegin.y : y;
|
||||
|
||||
var
|
||||
txb = Math.floor( (sx - this.pos.x) / this.layer.tilesize ),
|
||||
tyb = Math.floor( (sy - this.pos.y) / this.layer.tilesize ),
|
||||
txe = Math.floor( (x - this.pos.x) / this.layer.tilesize ),
|
||||
tye = Math.floor( (y - this.pos.y) / this.layer.tilesize );
|
||||
|
||||
return {
|
||||
x: Math.min( txb, txe ),
|
||||
y: Math.min( tyb, tye ),
|
||||
w: Math.abs( txb - txe) + 1,
|
||||
h: Math.abs( tyb - tye) + 1
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
draw: function() {
|
||||
ig.system.clear( "rgba(0,0,0,0.8)" );
|
||||
if( !this.layer.tiles.loaded ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Tileset
|
||||
ig.system.context.lineWidth = 1;
|
||||
ig.system.context.strokeStyle = wm.config.colors.secondary;
|
||||
ig.system.context.fillStyle = wm.config.colors.clear;
|
||||
ig.system.context.fillRect(
|
||||
this.pos.x * ig.system.scale,
|
||||
this.pos.y * ig.system.scale,
|
||||
this.layer.tiles.width * ig.system.scale,
|
||||
this.layer.tiles.height * ig.system.scale
|
||||
);
|
||||
ig.system.context.strokeRect(
|
||||
this.pos.x * ig.system.scale - 0.5,
|
||||
this.pos.y * ig.system.scale - 0.5,
|
||||
this.layer.tiles.width * ig.system.scale + 1,
|
||||
this.layer.tiles.height * ig.system.scale + 1
|
||||
);
|
||||
|
||||
this.layer.tiles.draw( this.pos.x, this.pos.y );
|
||||
|
||||
// Selected Tile
|
||||
var tile = this.getCurrentTile();
|
||||
var tx = Math.floor( tile * this.layer.tilesize ) % this.layer.tiles.width + this.pos.x;
|
||||
var ty =
|
||||
Math.floor( tile * this.layer.tilesize / this.layer.tiles.width )
|
||||
* this.layer.tilesize + this.pos.y
|
||||
+ (tile == -1 ? this.layer.tilesize : 0);
|
||||
|
||||
ig.system.context.lineWidth = 1;
|
||||
ig.system.context.strokeStyle = wm.config.colors.highlight;
|
||||
ig.system.context.strokeRect(
|
||||
tx * ig.system.scale - 0.5,
|
||||
ty * ig.system.scale - 0.5,
|
||||
this.layer.tilesize * ig.system.scale + 1,
|
||||
this.layer.tilesize * ig.system.scale + 1
|
||||
);
|
||||
},
|
||||
|
||||
|
||||
drawCursor: function( x, y ) {
|
||||
var cx = Math.floor( x / this.layer.tilesize ) * this.layer.tilesize;
|
||||
var cy = Math.floor( y / this.layer.tilesize ) * this.layer.tilesize;
|
||||
|
||||
var r = this.getSelectionRect( x, y);
|
||||
|
||||
ig.system.context.lineWidth = 1;
|
||||
ig.system.context.strokeStyle = wm.config.colors.selection;
|
||||
ig.system.context.strokeRect(
|
||||
(r.x * this.layer.tilesize + this.pos.x) * ig.system.scale - 0.5,
|
||||
(r.y * this.layer.tilesize + this.pos.y) * ig.system.scale - 0.5,
|
||||
r.w * this.layer.tilesize * ig.system.scale + 1,
|
||||
r.h * this.layer.tilesize * ig.system.scale + 1
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,234 @@
|
||||
ig.module(
|
||||
'weltmeister.undo'
|
||||
)
|
||||
.requires(
|
||||
'weltmeister.config'
|
||||
)
|
||||
.defines(function(){ "use strict";
|
||||
|
||||
|
||||
wm.Undo = ig.Class.extend({
|
||||
levels: 10,
|
||||
chain: [],
|
||||
rpos: 0,
|
||||
currentAction: null,
|
||||
|
||||
init: function( levels ) {
|
||||
this.levels = levels || 10;
|
||||
},
|
||||
|
||||
|
||||
clear: function() {
|
||||
this.chain = [];
|
||||
this.currentAction = null;
|
||||
},
|
||||
|
||||
|
||||
commit: function( action ) {
|
||||
if( this.rpos ) {
|
||||
this.chain.splice( this.chain.length - this.rpos, this.rpos );
|
||||
this.rpos = 0;
|
||||
}
|
||||
action.activeLayer = ig.game.activeLayer ? ig.game.activeLayer.name : '';
|
||||
this.chain.push( action );
|
||||
if( this.chain.length > this.levels ) {
|
||||
this.chain.shift();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
undo: function() {
|
||||
var action = this.chain[ this.chain.length - this.rpos - 1 ];
|
||||
if( !action ) {
|
||||
return;
|
||||
}
|
||||
this.rpos++;
|
||||
|
||||
|
||||
ig.game.setActiveLayer( action.activeLayer );
|
||||
|
||||
if( action.type == wm.Undo.MAP_DRAW ) {
|
||||
for( var i = 0; i < action.changes.length; i++ ) {
|
||||
var change = action.changes[i];
|
||||
change.layer.setTile( change.x, change.y, change.old );
|
||||
}
|
||||
}
|
||||
else if( action.type == wm.Undo.ENTITY_EDIT ) {
|
||||
action.entity.pos.x = action.old.x;
|
||||
action.entity.pos.y = action.old.y;
|
||||
action.entity.size.x = action.old.w;
|
||||
action.entity.size.y = action.old.h;
|
||||
ig.game.entities.selectEntity( action.entity );
|
||||
ig.game.entities.loadEntitySettings();
|
||||
}
|
||||
else if( action.type == wm.Undo.ENTITY_CREATE ) {
|
||||
ig.game.entities.removeEntity( action.entity );
|
||||
ig.game.entities.selectEntity( null );
|
||||
}
|
||||
else if( action.type == wm.Undo.ENTITY_DELETE ) {
|
||||
ig.game.entities.entities.push( action.entity );
|
||||
if( action.entity.name ) {
|
||||
this.namedEntities[action.entity.name] = action.entity;
|
||||
}
|
||||
ig.game.entities.selectEntity( action.entity );
|
||||
}
|
||||
|
||||
ig.game.setModified();
|
||||
},
|
||||
|
||||
|
||||
redo: function() {
|
||||
if( !this.rpos ) {
|
||||
return;
|
||||
}
|
||||
|
||||
var action = this.chain[ this.chain.length - this.rpos ];
|
||||
if( !action ) {
|
||||
return;
|
||||
}
|
||||
this.rpos--;
|
||||
|
||||
|
||||
ig.game.setActiveLayer( action.activeLayer );
|
||||
|
||||
if( action.type == wm.Undo.MAP_DRAW ) {
|
||||
for( var i = 0; i < action.changes.length; i++ ) {
|
||||
var change = action.changes[i];
|
||||
change.layer.setTile( change.x, change.y, change.current );
|
||||
}
|
||||
}
|
||||
else if( action.type == wm.Undo.ENTITY_EDIT ) {
|
||||
action.entity.pos.x = action.current.x;
|
||||
action.entity.pos.y = action.current.y;
|
||||
action.entity.size.x = action.current.w;
|
||||
action.entity.size.y = action.current.h;
|
||||
ig.game.entities.selectEntity( action.entity );
|
||||
ig.game.entities.loadEntitySettings();
|
||||
}
|
||||
else if( action.type == wm.Undo.ENTITY_CREATE ) {
|
||||
ig.game.entities.entities.push( action.entity );
|
||||
if( action.entity.name ) {
|
||||
this.namedEntities[action.entity.name] = action.entity;
|
||||
}
|
||||
ig.game.entities.selectEntity( action.entity );
|
||||
}
|
||||
else if( action.type == wm.Undo.ENTITY_DELETE ) {
|
||||
ig.game.entities.removeEntity( action.entity );
|
||||
ig.game.entities.selectEntity( null );
|
||||
}
|
||||
|
||||
ig.game.setModified();
|
||||
},
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Map changes
|
||||
|
||||
beginMapDraw: function( layer ) {
|
||||
this.currentAction = {
|
||||
type: wm.Undo.MAP_DRAW,
|
||||
time: Date.now(),
|
||||
changes: []
|
||||
};
|
||||
},
|
||||
|
||||
pushMapDraw: function( layer, x, y, oldTile, currentTile ) {
|
||||
if( !this.currentAction ) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.currentAction.changes.push({
|
||||
layer: layer,
|
||||
x: x,
|
||||
y: y,
|
||||
old: oldTile,
|
||||
current: currentTile
|
||||
});
|
||||
},
|
||||
|
||||
endMapDraw: function() {
|
||||
if( !this.currentAction || !this.currentAction.changes.length ) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.commit( this.currentAction );
|
||||
this.currentAction = null;
|
||||
},
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Entity changes
|
||||
|
||||
beginEntityEdit: function( entity ) {
|
||||
this.currentAction = {
|
||||
type: wm.Undo.ENTITY_EDIT,
|
||||
time: Date.now(),
|
||||
entity: entity,
|
||||
old: {
|
||||
x: entity.pos.x,
|
||||
y: entity.pos.y,
|
||||
w: entity.size.x,
|
||||
h: entity.size.y
|
||||
},
|
||||
current: {
|
||||
x: entity.pos.x,
|
||||
y: entity.pos.y,
|
||||
w: entity.size.x,
|
||||
h: entity.size.y
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
pushEntityEdit: function( entity ) {
|
||||
if( !this.currentAction ) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.currentAction.current = {
|
||||
x: entity.pos.x,
|
||||
y: entity.pos.y,
|
||||
w: entity.size.x,
|
||||
h: entity.size.y
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
endEntityEdit: function() {
|
||||
var a = this.currentAction;
|
||||
|
||||
if( !a || (
|
||||
a.old.x == a.current.x && a.old.y == a.current.y &&
|
||||
a.old.w == a.current.w && a.old.h == a.current.h
|
||||
)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.commit( this.currentAction );
|
||||
this.currentAction = null;
|
||||
},
|
||||
|
||||
|
||||
commitEntityCreate: function( entity ) {
|
||||
this.commit({
|
||||
type: wm.Undo.ENTITY_CREATE,
|
||||
time: Date.now(),
|
||||
entity: entity
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
commitEntityDelete: function( entity ) {
|
||||
this.commit({
|
||||
type: wm.Undo.ENTITY_DELETE,
|
||||
time: Date.now(),
|
||||
entity: entity
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
wm.Undo.MAP_DRAW = 1;
|
||||
wm.Undo.ENTITY_EDIT = 2;
|
||||
wm.Undo.ENTITY_CREATE = 3;
|
||||
wm.Undo.ENTITY_DELETE = 4;
|
||||
|
||||
});
|
||||
@@ -0,0 +1,486 @@
|
||||
body {
|
||||
background-color: #000;
|
||||
color: #fff;
|
||||
font-family: sans-serif;
|
||||
font-size: 10pt;
|
||||
margin: 0px;
|
||||
overflow: hidden;
|
||||
text-shadow: 0px 1px 1px rgba(0,0,0,0.5);
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin: 0 0 4px 0;
|
||||
padding: 4px 0 4px 6px;
|
||||
background-color: #000;
|
||||
font-size: 100%;
|
||||
color: #555;
|
||||
xtext-transform: uppercase;
|
||||
xborder-bottom: 1px solid #555;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-size: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
dt {
|
||||
margin: 0;
|
||||
padding: 4px 0 0 6px;
|
||||
display:inline;
|
||||
float:left;
|
||||
margin-right:5px;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin: 0;
|
||||
padding: 2px 0 8px 6px;
|
||||
}
|
||||
|
||||
dl {
|
||||
margin:0;
|
||||
}
|
||||
|
||||
div.clear {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
label {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* --- Input ------------------------------------------------------------------ */
|
||||
|
||||
input {
|
||||
background-color: rgba(0,0,0,0.5);
|
||||
border: 1px solid rgb(50,50,50);
|
||||
color: #fff;
|
||||
margin: 0;
|
||||
font-family: sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
font-size: 10pt;
|
||||
outline: none;
|
||||
text-shadow: 0px 1px 1px rgba(0,0,0,0.5);
|
||||
|
||||
}
|
||||
|
||||
input:focus{
|
||||
border: 1px solid rgb(200,200,200);
|
||||
}
|
||||
|
||||
input.text {
|
||||
padding: 1px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
input.number {
|
||||
width: 30px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
input.button {
|
||||
font-size: 90%;
|
||||
padding-left: 13px;
|
||||
padding-right: 13px;
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
background-color: rgba(255,255,255,0.1);
|
||||
border:none;
|
||||
border-top: 1px solid rgba(255,255,255,0.1);
|
||||
border-bottom: 1px solid rgba(0,0,0,0.1);
|
||||
cursor: pointer;
|
||||
-webkit-transition: 0.1s linear;
|
||||
}
|
||||
|
||||
input.button:hover {
|
||||
background-color: rgba(255,255,255,0.2);
|
||||
}
|
||||
|
||||
input.button:active {
|
||||
background-color: rgba(255,255,255,0.3);
|
||||
}
|
||||
|
||||
input.text#layerName {
|
||||
width:140px;
|
||||
}
|
||||
|
||||
input.text#layerTileset {
|
||||
width:138px;
|
||||
}
|
||||
|
||||
input#levelSaveAs { margin-right: 10px; }
|
||||
input#levelLoad { margin-right: 10px; }
|
||||
input#reloadImages {margin-right: 10px;}
|
||||
|
||||
input:disabled {
|
||||
background-color: #555;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
/* --- Layout ------------------------------------------------------------------ */
|
||||
|
||||
#editor {
|
||||
margin: 0px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#canvas {
|
||||
image-rendering: optimizeSpeed;
|
||||
-webkit-interpolation-mode: nearest-neighbor;
|
||||
}
|
||||
|
||||
#menu {
|
||||
width: 200px;
|
||||
float: right;
|
||||
position:absolute;
|
||||
top:0px;
|
||||
right:0px;
|
||||
}
|
||||
|
||||
/* --- Layers ------------------------------------------------------------------ */
|
||||
|
||||
#layerContainer {
|
||||
background-color: rgba(0,0,0,0.95);
|
||||
padding-right:2px;
|
||||
}
|
||||
|
||||
#layers {
|
||||
max-height: 200px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
#layerButtons div.button#buttonAddLayer {
|
||||
position:absolute;
|
||||
right: 0px;
|
||||
top:-5px;
|
||||
cursor: pointer;
|
||||
padding: 10px;
|
||||
color:rgba(255,255,255,0.5);
|
||||
font-weight: bold;
|
||||
font-size:110%;
|
||||
margin-left:1px;
|
||||
-webkit-transition: 0.1s linear;
|
||||
-webkit-font-smoothing: none;
|
||||
z-index:10;
|
||||
}
|
||||
#layerButtons div.button#buttonAddLayer:hover { color:rgba(255,255,255,1);}
|
||||
#layerButtons div.button#buttonAddLayer:active { color:rgba(255,255,255,1); text-shadow:none;}
|
||||
|
||||
.layer {
|
||||
padding: 6px 4px;
|
||||
cursor: pointer;
|
||||
-webkit-transition: background-color 0.1s linear;
|
||||
border-top: 1px solid rgba(255,255,255,0);
|
||||
border-bottom: 1px solid rgba(255,255,255,0);
|
||||
}
|
||||
|
||||
.layer:hover {
|
||||
background-color: rgba(255,255,255,0.1);
|
||||
border-top: 1px solid rgba(255,255,255,0.1);
|
||||
border-bottom: 1px solid rgba(255,255,255,0.1);
|
||||
}
|
||||
|
||||
.layer:active {
|
||||
background-color: rgba(255,255,255,0.2);
|
||||
border-top: 1px solid rgba(255,255,255,0.2);
|
||||
border-bottom: 1px solid rgba(255,255,255,0.2);
|
||||
}
|
||||
|
||||
.layerActive {
|
||||
background-color: rgba(255,255,255,0.1);
|
||||
border-top: 1px solid rgba(255,255,255,0.2);
|
||||
border-bottom: 1px solid rgba(255,255,255,0.2) !important;
|
||||
}
|
||||
|
||||
|
||||
#layerEntities { border-bottom: 1px solid #000; }
|
||||
|
||||
.layer .visible {
|
||||
background-color: rgba(255,255,255,0.2);
|
||||
text-indent: -99999px;
|
||||
display: inline-block;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
margin-right: 7px;
|
||||
margin-left: 4px;
|
||||
-webkit-transition: 0.1s linear;
|
||||
}
|
||||
|
||||
.layer .visible.specialVis{
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.layer .checkedVis{ background-color: rgba(255,255,255,1); }
|
||||
.layer span.size { font-size: 75%; color: rgba(255,255,255,0.7); }
|
||||
|
||||
#layerSettings {
|
||||
background-color: rgba(0,0,0,0.95);
|
||||
padding-top: 5px;
|
||||
margin-top: 1px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* --- Entities ------------------------------------------------------------------ */
|
||||
h3#entityClass {
|
||||
border-bottom: 1px solid rgba(255,255,255,0.2);
|
||||
padding: 5px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
#entitySettings {
|
||||
background-color: rgba(0,0,0,0.95);
|
||||
margin-top: 1px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#entityDefinitions {
|
||||
max-height: 220px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
div.entityDefinition {
|
||||
color: #aaa;
|
||||
padding: 2px 0;
|
||||
border-bottom: 1px solid rgba(255,255,255,0.2);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div.entityDefinition:hover {
|
||||
background-color: rgba(255,255,255,0.1);
|
||||
}
|
||||
|
||||
div.entityDefinition .key {
|
||||
width: 50%;
|
||||
display: block;
|
||||
float: left;
|
||||
margin: 0 0px 0 0;
|
||||
padding: 0;
|
||||
text-align: right;
|
||||
color: #fff;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
div.entityDefinition .value {
|
||||
padding: 0 0 0 2px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
dl#entityDefinitionInput {
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
dl#entityDefinitionInput dt {
|
||||
width: 40px;
|
||||
display: block;
|
||||
float: left;
|
||||
margin: 0 4px 0 0;
|
||||
padding: 4px 0 0 0;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
dl#entityDefinitionInput dd {
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: 2px 0;
|
||||
}
|
||||
|
||||
#entityKey, #entityValue {
|
||||
}
|
||||
|
||||
#entityMenu {
|
||||
background-color: rgba(0,0,0,0.9);
|
||||
display: none;
|
||||
position: absolute;
|
||||
min-width: 100px;
|
||||
max-height:300px;
|
||||
overflow-y: scroll;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
#entityMenu div {
|
||||
padding: 3px;
|
||||
padding-left: 8px;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
border-top: 1px solid rgba(255,255,255,0);
|
||||
border-bottom: 1px solid rgba(255,255,255,0);
|
||||
-webkit-transition: 0.1s linear;
|
||||
}
|
||||
|
||||
#entityMenu div:hover {
|
||||
background-color: rgba(255,255,255,0.2);
|
||||
border-top: 1px solid rgba(255,255,255,0.2);
|
||||
border-bottom: 1px solid rgba(255,255,255,0.2);
|
||||
}
|
||||
|
||||
/* --- Dialogs ------------------------------------------------------------------ */
|
||||
|
||||
.selectFileDialog {
|
||||
background-color: rgba(0,0,0,0.9);
|
||||
border: 1px solid white;
|
||||
border-top: 1px solid rgba(255,255,255,0.4);
|
||||
display: none;
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
-webkit-box-shadow: 0px 0px 10px rgba(0,0,0,1);
|
||||
|
||||
max-height: 300px;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.selectFileDialog a {
|
||||
padding: 4px;
|
||||
color: #fff;
|
||||
display: block;
|
||||
text-decoration: none;
|
||||
border-top: 1px solid rgba(255,255,255,0);
|
||||
border-bottom: 1px solid rgba(255,255,255,0);
|
||||
}
|
||||
|
||||
.selectFileDialog a:hover {
|
||||
background-color: rgba(255,255,255,0.2);
|
||||
border-top: 1px solid rgba(255,255,255,0.2);
|
||||
border-bottom: 1px solid rgba(255,255,255,0.2);
|
||||
}
|
||||
|
||||
div.modalDialogBackground {
|
||||
background-color: rgba(0,0,0,0.7);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: none;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
div.modalDialogBox {
|
||||
width: 300px;
|
||||
margin-left: -170px;
|
||||
background-color: rgba(0,0,0,0.9);
|
||||
border: 1px solid rgb(100,100,100);
|
||||
-webkit-box-shadow: 0px 0px 10px rgba(0,0,0,1);
|
||||
position: absolute;
|
||||
top: 20%;
|
||||
left: 50%;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
div.modalDialogText {
|
||||
font-size: 180%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.modalDialogButtons {
|
||||
margin-top: 20px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
div.modalDialogButtons input.button {
|
||||
min-width: 100px;
|
||||
text-align: center;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
input.modalDialogPath {
|
||||
margin-top: 20px;
|
||||
width: 100%;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
input.modalDialogPath:focus {
|
||||
outline: none;
|
||||
border: 1px solid rgb(100,100,100);
|
||||
}
|
||||
|
||||
#headerMenu {
|
||||
position:relative;
|
||||
z-index:10;
|
||||
height:47px;
|
||||
width:100%;
|
||||
background: #131314;
|
||||
background: -webkit-gradient(linear, left bottom, left top, color-stop(0,#000000), color-stop(1,#2e3033));
|
||||
background: -moz-linear-gradient(center bottom, #000000 0%, #2e3033 100%);
|
||||
background: -o-linear-gradient(#2e3033, #000000);
|
||||
}
|
||||
|
||||
#headerMenu span.headerTitle {
|
||||
display:inline-block;
|
||||
font-weight:bold;
|
||||
font-size:200%;
|
||||
padding-left:20px;
|
||||
padding-top:7px;
|
||||
color:rgba(0,0,0,0.1);
|
||||
text-shadow:0px -1px 0px rgba(255,255,255,0.4);
|
||||
}
|
||||
|
||||
#headerMenu span.unsavedTitle {
|
||||
display:inline-block;
|
||||
font-weight:bold;
|
||||
font-size:240%;
|
||||
padding-left:0px;
|
||||
color:#cc0000;
|
||||
text-shadow:0px 1px 1px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
#headerMenu span.headerFloat {
|
||||
float: right;
|
||||
}
|
||||
|
||||
div#zoomIndicator {
|
||||
font-weight: bold;
|
||||
font-size: 300%;
|
||||
position: absolute;
|
||||
left: 50px;
|
||||
top: 30px;
|
||||
color: #fff;
|
||||
display: none;
|
||||
}
|
||||
|
||||
input#toggleSidebar {
|
||||
width: 200px;
|
||||
height: 47px;
|
||||
text-indent: -99999px;
|
||||
background: url(arrow.png) 50% -37px no-repeat;
|
||||
-webkit-transition: 0s linear;
|
||||
opacity: 0.25;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
input#toggleSidebar.active{
|
||||
background-position: 50% 10px;
|
||||
}
|
||||
|
||||
input[type="checkbox"] {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
display: inline-block;
|
||||
-webkit-appearance: none;
|
||||
-webkit-transition: 0.1s linear;
|
||||
}
|
||||
input[type="checkbox"] {
|
||||
background-color:rgba(255,255,255,0.2);
|
||||
}
|
||||
input[type="checkbox"]:checked {
|
||||
background-color: rgba(255,255,255,1);
|
||||
}
|
||||
input[type="checkbox"]:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
input[type="checkbox"]:disabled {
|
||||
background-color: rgba(255,255,255,0.1);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar { width: 2px; }
|
||||
::-webkit-scrollbar-button:start:decrement,
|
||||
::-webkit-scrollbar-button:end:increment { display: block; height: 2px; }
|
||||
::-webkit-scrollbar-button:vertical:increment { background-color: transparent; }
|
||||
::-webkit-scrollbar-track-piece { background-color: rgba(0,0,0,0); }
|
||||
::-webkit-scrollbar-thumb:vertical { background-color: rgba(255,255,255,1); }
|
||||
|
After Width: | Height: | Size: 484 B |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 246 B |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 272 B |
|
After Width: | Height: | Size: 514 B |
|
After Width: | Height: | Size: 9.8 KiB |
|
After Width: | Height: | Size: 6.9 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 36 KiB |
@@ -0,0 +1,235 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import BaseHTTPServer
|
||||
import cgi
|
||||
import glob
|
||||
import json
|
||||
import mimetypes
|
||||
import os
|
||||
import os.path
|
||||
import urlparse
|
||||
|
||||
# Various config settings for the python server
|
||||
SETTINGS = {
|
||||
'port': 8080,
|
||||
'logging': False,
|
||||
|
||||
'api-save': '/lib/weltmeister/api/save.php',
|
||||
'api-browse': '/lib/weltmeister/api/browse.php',
|
||||
'api-glob': '/lib/weltmeister/api/glob.php',
|
||||
|
||||
'image-types': ['.png', '.jpg', '.gif', '.jpeg'],
|
||||
|
||||
'mimetypes': {
|
||||
'ogg': 'audio/ogg'
|
||||
}
|
||||
}
|
||||
|
||||
# Override port if we are on a Heroku server
|
||||
if os.environ.get('PORT'):
|
||||
SETTINGS['port'] = int(os.environ.get('PORT'))
|
||||
|
||||
# Get the current directory
|
||||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
if BASE_DIR[-1] != '/':
|
||||
BASE_DIR += '/'
|
||||
|
||||
# Blank favicon - prevents silly 404s from occuring if no favicon is supplied
|
||||
FAVICON_GIF = 'GIF89a\x01\x00\x01\x00\xf0\x00\x00\xff\xff\xff\x00\x00\x00!\xff\x0bXMP DataXMP\x02?x\x00!\xf9\x04\x05\x00\x00\x00\x00,\x00\x00\x00\x00\x01\x00\x01\x00@\x02\x02D\x01\x00;'
|
||||
|
||||
class HTTPHandler(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||
|
||||
def send_json(self, obj, code=200, headers=None):
|
||||
'Send response as JSON'
|
||||
if not headers:
|
||||
headers = {}
|
||||
headers['Content-Type'] = 'application/json'
|
||||
self.send_response(json.dumps(obj), code, headers)
|
||||
|
||||
def send_response(self, mesg, code=200, headers=None):
|
||||
'Wraps sending a response down'
|
||||
if not headers:
|
||||
headers = {}
|
||||
if 'Content-Type' not in headers:
|
||||
headers['Content-Type'] = 'text/html'
|
||||
BaseHTTPServer.BaseHTTPRequestHandler.send_response(self, code)
|
||||
self.send_header('Content-Length', len(mesg))
|
||||
if headers:
|
||||
for k, v in headers.iteritems():
|
||||
self.send_header(k, v)
|
||||
self.end_headers()
|
||||
self.wfile.write(mesg)
|
||||
|
||||
def log_request(self, *args, **kwargs):
|
||||
'If logging is disabled '
|
||||
if SETTINGS['logging']:
|
||||
BaseHTTPServer.BaseHTTPRequestHandler.log_request(self, *args, **kwargs)
|
||||
|
||||
def init_request(self):
|
||||
parts = self.path.split('?', 1)
|
||||
self.post_params = {}
|
||||
if len(parts) == 1:
|
||||
self.file_path = parts[0]
|
||||
self.query_params = {}
|
||||
else:
|
||||
self.file_path = parts[0]
|
||||
self.query_params = urlparse.parse_qs(parts[1])
|
||||
|
||||
def do_GET(self):
|
||||
self.init_request()
|
||||
self.route_request('GET')
|
||||
|
||||
def do_HEAD(self):
|
||||
self.init_request()
|
||||
self.send_response('')
|
||||
|
||||
def do_POST(self):
|
||||
self.init_request()
|
||||
|
||||
# From http://stackoverflow.com/questions/4233218/python-basehttprequesthandler-post-variables
|
||||
ctype, pdict = cgi.parse_header(self.headers.getheader('content-type'))
|
||||
if ctype == 'multipart/form-data':
|
||||
self.post_params = cgi.parse_multipart(self.rfile, pdict)
|
||||
elif ctype == 'application/x-www-form-urlencoded':
|
||||
length = int(self.headers.getheader('content-length'))
|
||||
self.post_params = cgi.parse_qs(self.rfile.read(length), keep_blank_values=1)
|
||||
|
||||
self.route_request('POST')
|
||||
|
||||
def route_request(self, method='GET'):
|
||||
if self.file_path == SETTINGS['api-save']:
|
||||
self.save()
|
||||
elif self.file_path == SETTINGS['api-browse']:
|
||||
self.browse()
|
||||
elif self.file_path == SETTINGS['api-glob']:
|
||||
self.glob()
|
||||
elif method == 'GET':
|
||||
self.serve_file()
|
||||
else:
|
||||
self.barf()
|
||||
|
||||
def save(self):
|
||||
resp = {'error': 0}
|
||||
if 'path' in self.post_params and 'data' in self.post_params:
|
||||
path = self.post_params['path'][0]
|
||||
path = os.path.join(BASE_DIR, path.replace('..', ''))
|
||||
data = self.post_params['data'][0]
|
||||
|
||||
if path.endswith('.js'):
|
||||
try:
|
||||
open(path, 'w').write(data)
|
||||
except:
|
||||
resp['error'] = 2
|
||||
resp['msg'] = 'Couldn\'t write to file %d' % path
|
||||
|
||||
else:
|
||||
resp['error'] = 3
|
||||
resp['msg'] = 'File must have a .js suffix'
|
||||
|
||||
else:
|
||||
resp['error'] = 1
|
||||
resp['msg'] = 'No Data or Path specified'
|
||||
|
||||
return self.send_json(resp)
|
||||
|
||||
def browse(self):
|
||||
# Get the directory to scan
|
||||
dir = ''
|
||||
if 'dir' in self.query_params:
|
||||
dir = self.query_params['dir'][0].replace('..', '')
|
||||
if dir[-1] != '/':
|
||||
dir += '/'
|
||||
|
||||
# Get the dir and files
|
||||
dirs = [os.path.join(dir, d) for d in os.listdir(os.path.join(BASE_DIR, dir))
|
||||
if os.path.isdir(os.path.join(dir, d))]
|
||||
|
||||
files = glob.glob(dir + '*.*')
|
||||
|
||||
# Filter on file types
|
||||
if 'type' in self.query_params:
|
||||
types = self.query_params['type']
|
||||
if 'images' in types:
|
||||
files = [f for f in files if os.path.splitext(f)[1] in SETTINGS['image-types']]
|
||||
elif 'scripts' in types:
|
||||
files = [f for f in files if os.path.splitext(f)[1] == '.js']
|
||||
|
||||
if os.name == 'nt':
|
||||
files = [f.replace('\\', '/') for f in files]
|
||||
dirs = [d.replace('\\', '/') for d in dirs]
|
||||
|
||||
response = {
|
||||
'files': files,
|
||||
'dirs': dirs,
|
||||
'parent': False if dir == './' else os.path.dirname(os.path.dirname(dir))
|
||||
}
|
||||
return self.send_json(response)
|
||||
|
||||
def glob(self):
|
||||
globs = self.query_params['glob[]']
|
||||
files = []
|
||||
|
||||
for g in globs:
|
||||
g = g.replace('..', '')
|
||||
more = glob.glob(g)
|
||||
files.extend(more)
|
||||
|
||||
if os.name == 'nt':
|
||||
files = [f.replace('\\', '/') for f in files]
|
||||
|
||||
return self.send_json(files)
|
||||
|
||||
def guess_type(self, path):
|
||||
type, _ = mimetypes.guess_type(path)
|
||||
|
||||
if not type:
|
||||
ext = path.split('.')[-1]
|
||||
if ext in SETTINGS['mimetypes'].keys():
|
||||
type = SETTINGS['mimetypes'][ext]
|
||||
|
||||
# Winblows hack
|
||||
if os.name == "nt" and type.startswith("image"):
|
||||
type = type.replace("x-", "")
|
||||
|
||||
return type
|
||||
|
||||
def serve_file(self):
|
||||
path = self.file_path
|
||||
if path == '/':
|
||||
path = 'index.html'
|
||||
elif path == '/editor':
|
||||
path = 'weltmeister.html'
|
||||
|
||||
# Remove the leading forward slash
|
||||
if path[0] == '/':
|
||||
path = path[1:]
|
||||
|
||||
# Security, remove the ..
|
||||
path = path.replace('..', '')
|
||||
|
||||
# Determine the fullpath
|
||||
path = os.path.join(BASE_DIR, path)
|
||||
|
||||
try:
|
||||
data = open(path, 'rb').read()
|
||||
type = self.guess_type(path)
|
||||
self.send_response(data, 200, headers={'Content-Type': type})
|
||||
except:
|
||||
if '/favicon.ico' in path:
|
||||
self.send_response(FAVICON_GIF, 200, headers={'Content-Type': 'image/gif'})
|
||||
else:
|
||||
self.send_response('', 404)
|
||||
|
||||
def barf(self):
|
||||
self.send_response('barf', 405)
|
||||
|
||||
|
||||
def main():
|
||||
addr = ('', SETTINGS['port'])
|
||||
server = BaseHTTPServer.HTTPServer(addr, HTTPHandler)
|
||||
print 'Running ImpactJS Server\nGame: http://localhost:%d\nEditor: http://localhost:%d/editor' % (addr[1], addr[1])
|
||||
server.serve_forever()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
@echo off
|
||||
|
||||
:: Path to impact.js and your game's main .js
|
||||
SET IMPACT_LIBRARY=lib/impact/impact.js
|
||||
SET GAME=lib/game/main.js
|
||||
|
||||
:: Output file
|
||||
SET OUTPUT_FILE=game.min.js
|
||||
|
||||
|
||||
:: Change CWD to Impact's base dir
|
||||
cd ../
|
||||
|
||||
|
||||
:: Bake!
|
||||
php tools/bake.php %IMPACT_LIBRARY% %GAME% %OUTPUT_FILE%
|
||||
|
||||
:: If you dont have the php.exe in your PATH uncomment the
|
||||
:: following line and point it to your php.exe
|
||||
|
||||
::c:/php/php.exe tools/bake.php %IMPACT_LIBRARY% %GAME% %OUTPUT_FILE%
|
||||
|
||||
pause
|
||||
@@ -0,0 +1,157 @@
|
||||
<?php
|
||||
if( count($argv) < 3 ) {
|
||||
echo "Usage: bake.php <in...> <out>\n";
|
||||
echo "e.g. bake.php lib/impact/impact.js lib/game/game.js mygame-baked.js\n";
|
||||
die;
|
||||
}
|
||||
|
||||
$inFiles = array_slice( $argv, 1, -1 );
|
||||
$outFile = $argv[ count($argv)-1 ];
|
||||
|
||||
$baker = new Baker( Baker::MINIFIED );
|
||||
$baker->bake( $inFiles, $outFile );
|
||||
|
||||
|
||||
class Baker {
|
||||
const PLAIN = 0;
|
||||
const MINIFIED = 1;
|
||||
const GZIPPED = 2;
|
||||
|
||||
protected $base = 'lib/';
|
||||
protected $format = 0;
|
||||
protected $loaded = array();
|
||||
protected $currentInput = 'Command Line';
|
||||
protected $fileCount = 0, $bytesIn = 0, $bytesOut = 0;
|
||||
|
||||
public function __construct( $format = 0 ) {
|
||||
$this->format = $format;
|
||||
if( $this->format & self::MINIFIED ) {
|
||||
require_once( 'jsmin.php' );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function bake( $inFiles, $outFile ) {
|
||||
$this->fileCount = 0;
|
||||
$this->bytesIn = 0;
|
||||
$out = "/*! Built with IMPACT - impactjs.com */\n\n";
|
||||
|
||||
foreach( $inFiles as $f ) {
|
||||
$out .= $this->load( $f );
|
||||
}
|
||||
|
||||
$bytesOut = strlen($out);
|
||||
$bytesOutZipped = 0;
|
||||
|
||||
echo "writing $outFile\n";
|
||||
@file_put_contents( $outFile, $out ) or
|
||||
die("ERROR: Couldn't write to $outFile\n");
|
||||
|
||||
if( $this->format & self::GZIPPED ) {
|
||||
$gzFile = "$outFile.gz";
|
||||
echo "writing $gzFile\n";
|
||||
$fh = gzopen( $gzFile, 'w9' ) or
|
||||
die("ERROR: Couldn't write to $gzFile\n");
|
||||
|
||||
gzwrite( $fh, $out );
|
||||
gzclose( $fh );
|
||||
$bytesOutZipped = filesize( $gzFile );
|
||||
}
|
||||
|
||||
|
||||
echo
|
||||
"\nbaked {$this->fileCount} files: ".
|
||||
round($this->bytesIn/1024,1)."kb -> ".round($bytesOut/1024,1)."kb" .
|
||||
( $this->format & self::GZIPPED
|
||||
? " (".round($bytesOutZipped/1024,1)."kb gzipped)\n"
|
||||
: "\n"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
protected function load( $path ) {
|
||||
if( isset($this->loaded[$path]) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if( !file_exists($path) ) {
|
||||
die("ERROR: Couldn't load $path required from {$this->currentInput}\n");
|
||||
}
|
||||
|
||||
echo "loading $path \n";
|
||||
$this->loaded[$path] = true;
|
||||
$this->currentInput = $path;
|
||||
|
||||
$code = file_get_contents( $path );
|
||||
$this->bytesIn += strlen($code);
|
||||
$this->fileCount++;
|
||||
if( $this->format & self::MINIFIED ) {
|
||||
$code = trim(JSMin::minify($code));
|
||||
}
|
||||
|
||||
|
||||
// Naively probe the file for 'ig.module().requires().defines()' code;
|
||||
// the 'requries()' part will be handled by the regexp callback
|
||||
$this->definesModule = false;
|
||||
$code = preg_replace_callback(
|
||||
'/ig\s*
|
||||
\.\s*module\s*\((.*?)\)\s*
|
||||
(\.\s*requires\s*\((.*?)\)\s*)?
|
||||
\.\s*defines\s*\(
|
||||
/smx',
|
||||
array($this,'loadCallback'),
|
||||
$code
|
||||
);
|
||||
|
||||
// All files should define a module; maybe we just missed it? Print a
|
||||
// friendly reminder :)
|
||||
if( !$this->definesModule ) {
|
||||
echo "WARNING: file $path seems to define no module!\n";
|
||||
}
|
||||
|
||||
return $code;
|
||||
}
|
||||
|
||||
|
||||
protected function loadCallback( $matches ) {
|
||||
$currentInput = $this->currentInput;
|
||||
$this->definesModule = true;
|
||||
|
||||
$moduleName = $matches[1];
|
||||
$requiredFiles = isset($matches[3]) ? $matches[3] : '';
|
||||
$requiredCode = '';
|
||||
|
||||
if( $requiredFiles ) {
|
||||
// Explode the module names and map them to file names. Ignore the
|
||||
// dom.ready module if present
|
||||
$moduleFiles = array_diff(
|
||||
explode(
|
||||
',',
|
||||
preg_replace(
|
||||
'/[\s\'"]|\/\/.*|\/\*.*\*\//', // strip quotes and spaces
|
||||
'',
|
||||
str_replace('.', '/', $requiredFiles ) // . to /
|
||||
)
|
||||
),
|
||||
array('dom/ready')
|
||||
);
|
||||
|
||||
foreach( $moduleFiles as $f ) {
|
||||
$requiredCode .= $this->load( $this->base . $f.'.js' );
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
$requiredCode .
|
||||
"\n\n// $currentInput\n" .
|
||||
'ig.baked=true;' .
|
||||
'ig.module('.$moduleName.')' .
|
||||
( $requiredFiles
|
||||
? '.requires('.$requiredFiles.')'
|
||||
: ''
|
||||
) .
|
||||
'.defines(';
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Path to impact.js and your game's main .js
|
||||
IMPACT_LIBRARY=lib/impact/impact.js
|
||||
GAME=lib/game/main.js
|
||||
|
||||
# Output file
|
||||
OUTPUT_FILE=game.min.js
|
||||
|
||||
|
||||
# Change CWD to Impact's base dir and bake!
|
||||
cd ..
|
||||
php tools/bake.php $IMPACT_LIBRARY $GAME $OUTPUT_FILE
|
||||
@@ -0,0 +1,291 @@
|
||||
<?php
|
||||
/**
|
||||
* jsmin.php - PHP implementation of Douglas Crockford's JSMin.
|
||||
*
|
||||
* This is pretty much a direct port of jsmin.c to PHP with just a few
|
||||
* PHP-specific performance tweaks. Also, whereas jsmin.c reads from stdin and
|
||||
* outputs to stdout, this library accepts a string as input and returns another
|
||||
* string as output.
|
||||
*
|
||||
* PHP 5 or higher is required.
|
||||
*
|
||||
* Permission is hereby granted to use this version of the library under the
|
||||
* same terms as jsmin.c, which has the following license:
|
||||
*
|
||||
* --
|
||||
* Copyright (c) 2002 Douglas Crockford (www.crockford.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished to do
|
||||
* so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* The Software shall be used for Good, not Evil.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
* --
|
||||
*
|
||||
* @package JSMin
|
||||
* @author Ryan Grove <ryan@wonko.com>
|
||||
* @copyright 2002 Douglas Crockford <douglas@crockford.com> (jsmin.c)
|
||||
* @copyright 2008 Ryan Grove <ryan@wonko.com> (PHP port)
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @version 1.1.1 (2008-03-02)
|
||||
* @link http://code.google.com/p/jsmin-php/
|
||||
*/
|
||||
|
||||
class JSMin {
|
||||
const ORD_LF = 10;
|
||||
const ORD_SPACE = 32;
|
||||
|
||||
protected $a = '';
|
||||
protected $b = '';
|
||||
protected $input = '';
|
||||
protected $inputIndex = 0;
|
||||
protected $inputLength = 0;
|
||||
protected $lookAhead = null;
|
||||
protected $output = '';
|
||||
|
||||
// -- Public Static Methods --------------------------------------------------
|
||||
|
||||
public static function minify($js) {
|
||||
$jsmin = new JSMin($js);
|
||||
return $jsmin->min();
|
||||
}
|
||||
|
||||
// -- Public Instance Methods ------------------------------------------------
|
||||
|
||||
public function __construct($input) {
|
||||
$this->input = str_replace("\r\n", "\n", $input);
|
||||
$this->inputLength = strlen($this->input);
|
||||
}
|
||||
|
||||
// -- Protected Instance Methods ---------------------------------------------
|
||||
|
||||
protected function action($d) {
|
||||
switch($d) {
|
||||
case 1:
|
||||
$this->output .= $this->a;
|
||||
|
||||
case 2:
|
||||
$this->a = $this->b;
|
||||
|
||||
if ($this->a === "'" || $this->a === '"') {
|
||||
for (;;) {
|
||||
$this->output .= $this->a;
|
||||
$this->a = $this->get();
|
||||
|
||||
if ($this->a === $this->b) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (ord($this->a) <= self::ORD_LF) {
|
||||
throw new JSMinException('Unterminated string literal.');
|
||||
}
|
||||
|
||||
if ($this->a === '\\') {
|
||||
$this->output .= $this->a;
|
||||
$this->a = $this->get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case 3:
|
||||
$this->b = $this->next();
|
||||
|
||||
if ($this->b === '/' && (
|
||||
$this->a === '(' || $this->a === ',' || $this->a === '=' ||
|
||||
$this->a === ':' || $this->a === '[' || $this->a === '!' ||
|
||||
$this->a === '&' || $this->a === '|' || $this->a === '?')) {
|
||||
|
||||
$this->output .= $this->a . $this->b;
|
||||
|
||||
for (;;) {
|
||||
$this->a = $this->get();
|
||||
|
||||
if ($this->a === '/') {
|
||||
break;
|
||||
} elseif ($this->a === '\\') {
|
||||
$this->output .= $this->a;
|
||||
$this->a = $this->get();
|
||||
} elseif (ord($this->a) <= self::ORD_LF) {
|
||||
throw new JSMinException('Unterminated regular expression '.
|
||||
'literal.');
|
||||
}
|
||||
|
||||
$this->output .= $this->a;
|
||||
}
|
||||
|
||||
$this->b = $this->next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function get() {
|
||||
$c = $this->lookAhead;
|
||||
$this->lookAhead = null;
|
||||
|
||||
if ($c === null) {
|
||||
if ($this->inputIndex < $this->inputLength) {
|
||||
$c = $this->input[$this->inputIndex];
|
||||
$this->inputIndex += 1;
|
||||
} else {
|
||||
$c = null;
|
||||
}
|
||||
}
|
||||
|
||||
if ($c === "\r") {
|
||||
return "\n";
|
||||
}
|
||||
|
||||
if ($c === null || $c === "\n" || ord($c) >= self::ORD_SPACE) {
|
||||
return $c;
|
||||
}
|
||||
|
||||
return ' ';
|
||||
}
|
||||
|
||||
protected function isAlphaNum($c) {
|
||||
return ord($c) > 126 || $c === '\\' || preg_match('/^[\w\$]$/', $c) === 1;
|
||||
}
|
||||
|
||||
protected function min() {
|
||||
$this->a = "\n";
|
||||
$this->action(3);
|
||||
|
||||
while ($this->a !== null) {
|
||||
switch ($this->a) {
|
||||
case ' ':
|
||||
if ($this->isAlphaNum($this->b)) {
|
||||
$this->action(1);
|
||||
} else {
|
||||
$this->action(2);
|
||||
}
|
||||
break;
|
||||
|
||||
case "\n":
|
||||
switch ($this->b) {
|
||||
case '{':
|
||||
case '[':
|
||||
case '(':
|
||||
case '+':
|
||||
case '-':
|
||||
$this->action(1);
|
||||
break;
|
||||
|
||||
case ' ':
|
||||
$this->action(3);
|
||||
break;
|
||||
|
||||
default:
|
||||
if ($this->isAlphaNum($this->b)) {
|
||||
$this->action(1);
|
||||
}
|
||||
else {
|
||||
$this->action(2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
switch ($this->b) {
|
||||
case ' ':
|
||||
if ($this->isAlphaNum($this->a)) {
|
||||
$this->action(1);
|
||||
break;
|
||||
}
|
||||
|
||||
$this->action(3);
|
||||
break;
|
||||
|
||||
case "\n":
|
||||
switch ($this->a) {
|
||||
case '}':
|
||||
case ']':
|
||||
case ')':
|
||||
case '+':
|
||||
case '-':
|
||||
case '"':
|
||||
case "'":
|
||||
$this->action(1);
|
||||
break;
|
||||
|
||||
default:
|
||||
if ($this->isAlphaNum($this->a)) {
|
||||
$this->action(1);
|
||||
}
|
||||
else {
|
||||
$this->action(3);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
$this->action(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->output;
|
||||
}
|
||||
|
||||
protected function next() {
|
||||
$c = $this->get();
|
||||
|
||||
if ($c === '/') {
|
||||
switch($this->peek()) {
|
||||
case '/':
|
||||
for (;;) {
|
||||
$c = $this->get();
|
||||
|
||||
if (ord($c) <= self::ORD_LF) {
|
||||
return $c;
|
||||
}
|
||||
}
|
||||
|
||||
case '*':
|
||||
$this->get();
|
||||
|
||||
for (;;) {
|
||||
switch($this->get()) {
|
||||
case '*':
|
||||
if ($this->peek() === '/') {
|
||||
$this->get();
|
||||
return ' ';
|
||||
}
|
||||
break;
|
||||
|
||||
case null:
|
||||
throw new JSMinException('Unterminated comment.');
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
return $c;
|
||||
}
|
||||
}
|
||||
|
||||
return $c;
|
||||
}
|
||||
|
||||
protected function peek() {
|
||||
$this->lookAhead = $this->get();
|
||||
return $this->lookAhead;
|
||||
}
|
||||
}
|
||||
|
||||
// -- Exceptions ---------------------------------------------------------------
|
||||
class JSMinException extends Exception {}
|
||||
?>
|
||||
@@ -0,0 +1,98 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<title>Weltmeister</title>
|
||||
<link rel="stylesheet" type="text/css" href="lib/weltmeister/weltmeister.css"/>
|
||||
<script src="lib/weltmeister/jquery-1.7.1.min.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="lib/weltmeister/jquery-ui-1.8.1.custom.min.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="lib/impact/impact.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="lib/weltmeister/weltmeister.js" type="text/javascript" charset="utf-8"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="headerMenu">
|
||||
<span class="headerTitle"></span>
|
||||
<span class="unsavedTitle"></span>
|
||||
<span class="headerFloat">
|
||||
<input type="button" id="levelSave" value="Save" class="button"/>
|
||||
<input type="button" id="levelSaveAs" value="Save As" class="button"/>
|
||||
<input type="button" id="levelNew" value="New" class="button"/>
|
||||
<input type="button" id="levelLoad" value="Load" class="button"/>
|
||||
<input type="button" id="reloadImages" value="Reload Images" title="Reload Images" class="button"/>
|
||||
<input type="button" id="toggleSidebar" value="Toggle Sidebar" title="Toggle Sidebar" class="button"/>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div id="editor">
|
||||
<div id="entityMenu"></div>
|
||||
|
||||
<canvas id="canvas"></canvas>
|
||||
|
||||
<div id="menu">
|
||||
<div id="layerContainer">
|
||||
<h2>Layers</h2>
|
||||
<div id="layerButtons">
|
||||
<div class="button" id="buttonAddLayer" title="Add Layer">+</div>
|
||||
</div>
|
||||
<div id="layers">
|
||||
<div id="layerEntities" class="layer">
|
||||
<span class="visible specialVis checkedVis" title="Toggle Visibility (Shift+0)"></span>
|
||||
<span class="name">entities</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="layerSettings">
|
||||
<h2>Layer Settings</h2>
|
||||
<dl>
|
||||
<dt>Name:</dt><dd><input type="text" class="text" id="layerName"/></dd>
|
||||
<dt>Tileset:</dt><dd><input type="text" class="text" id="layerTileset"/></dd>
|
||||
<dt>Tilesize:</dt><dd><input type="text" class="number" id="layerTilesize"/></dd>
|
||||
<dt>Dimensions:</dt>
|
||||
<dd>
|
||||
<input type="text" class="number" id="layerWidth"/> × <input type="text" class="number" id="layerHeight"/>
|
||||
</dd>
|
||||
<dt>Distance:</dt><dd><input type="text" class="number" id="layerDistance"/></dd>
|
||||
<dd>
|
||||
<input type="checkbox" id="layerIsCollision"/>
|
||||
<label for="layerIsCollision">Is Collision Layer</label>
|
||||
</dd>
|
||||
<dd>
|
||||
<input type="checkbox" id="layerPreRender"/>
|
||||
<label for="layerPreRender">Pre-Render in Game</label>
|
||||
</dd>
|
||||
<dd>
|
||||
<input type="checkbox" id="layerRepeat"/>
|
||||
<label for="layerRepeat">Repeat</label>
|
||||
</dd>
|
||||
<dd>
|
||||
<input type="checkbox" id="layerLinkWithCollision"/>
|
||||
<label for="layerLinkWithCollision">Link with Collision</label>
|
||||
</dd>
|
||||
<dd>
|
||||
<input type="button" id="buttonSaveLayerSettings" value="Apply Changes" class="button"/>
|
||||
<input type="button" id="buttonRemoveLayer" value="Delete" class="button"/>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
<div id="entitySettings">
|
||||
<h2>Entity Settings</h2>
|
||||
<h3 id="entityClass">EntityClassName</h3>
|
||||
<div id="entityDefinitions">
|
||||
<div class="entityDefinition"><span class="key">x</span>:<span class="value">188</span></div>
|
||||
<div class="entityDefinition"><span class="key">y</span>:<span class="value">269</span></div>
|
||||
</div>
|
||||
<dl id="entityDefinitionInput">
|
||||
<dt>Key:</dt><dd><input type="text" class="text" id="entityKey"/></dd>
|
||||
<dt>Value:</dt><dd><input type="text" class="text" id="entityValue"/></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="zoomIndicator">1x</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||