Merge branch 'master' into rendering-cleanup

This commit is contained in:
Felipe Alfonso 2018-01-23 13:39:33 -03:00
commit 336cc4e3fe
14 changed files with 302 additions and 44 deletions

View file

@ -229,6 +229,17 @@ var Tile = new Class({
return this; return this;
}, },
/**
* The collision group for this Tile, defined within the Tileset. This returns a reference to
* the collision group stored within the Tileset, so any modification of the returned object
* will impact all tiles that have the same index as this tile.
* @returns {object|null} tileset
*/
getCollisionGroup: function ()
{
return this.tileset ? this.tileset.getTileCollisionGroup(this.index) : null;
},
/** /**
* Clean up memory. * Clean up memory.
*/ */
@ -510,8 +521,35 @@ var Tile = new Class({
{ {
return this.pixelY + this.height / 2; return this.pixelY + this.height / 2;
} }
} },
/**
* The tileset that contains this Tile. This will only return null if accessed from a LayerData
* instance before the tile is placed within a StaticTilemapLayer or DynamicTilemapLayer.
* @property {Tileset|null} tileset
* @readonly
*/
tileset: {
get: function ()
{
var tilemapLayer = this.tilemapLayer;
return tilemapLayer ? tilemapLayer.tileset : null;
}
},
/**
* The tilemap layer that contains this Tile. This will only return null if accessed from a
* LayerData instance before the tile is placed within a StaticTilemapLayer or
* DynamicTilemapLayer.
* @property {StaticTilemapLayer|DynamicTilemapLayer|null} tilemapLayer
* @readonly
*/
tilemapLayer: {
get: function ()
{
return this.layer.tilemapLayer;
}
}
}); });
module.exports = Tile; module.exports = Tile;

View file

@ -1001,6 +1001,19 @@ var Tilemap = new Class({
return this; return this;
}, },
/**
* See component documentation. If no layer specified, the map's current layer is used.
*
* @return {this|null} Returns this, or null if the layer given was invalid.
*/
setCollisionByProperty: function (properties, collides, recalculateFaces, layer)
{
layer = this.getLayer(layer);
if (layer === null) { return this; }
TilemapComponents.SetCollisionByProperty(properties, collides, recalculateFaces, layer);
return this;
},
/** /**
* See component documentation. If no layer specified, the map's current layer is used. * See component documentation. If no layer specified, the map's current layer is used.
* *
@ -1014,6 +1027,19 @@ var Tilemap = new Class({
return this; return this;
}, },
/**
* See component documentation. If no layer specified, the map's current layer is used.
*
* @return {this|null} Returns this, or null if the layer given was invalid.
*/
setCollisionFromCollisionGroup: function (collides, recalculateFaces, layer)
{
layer = this.getLayer(layer);
if (layer === null) { return this; }
TilemapComponents.SetCollisionFromCollisionGroup(collides, recalculateFaces, layer);
return this;
},
/** /**
* See component documentation. If no layer specified, the map's current layer is used. * See component documentation. If no layer specified, the map's current layer is used.
* *

View file

@ -72,14 +72,15 @@ var Tileset = new Class({
this.tileSpacing = tileSpacing; this.tileSpacing = tileSpacing;
/** /**
* Tileset-specific properties per tile that are typically defined in the Tiled editor. * Tileset-specific properties per tile that are typically defined in the Tiled editor in the
* Tileset editor.
* @property {object} tileProperties * @property {object} tileProperties
*/ */
this.tileProperties = tileProperties; this.tileProperties = tileProperties;
/** /**
* Tileset-specific data per tile that are typically defined in the Tiled editor. This is * Tileset-specific data per tile that are typically defined in the Tiled editor, e.g. within
* where collision objects and terrain are stored. * the Tileset collision editor. This is where collision objects and terrain are stored.
* @property {object} tileData * @property {object} tileData
*/ */
this.tileData = tileData; this.tileData = tileData;
@ -123,20 +124,21 @@ var Tileset = new Class({
/** /**
* Get a tile's properties that are stored in the Tileset. Returns null if tile index is not * Get a tile's properties that are stored in the Tileset. Returns null if tile index is not
* contained in this Tileset. * contained in this Tileset. This is typically defined in Tiled under the Tileset editor.
* *
* @param {integer} tileIndex - The unique id of the tile across all tilesets in the map. * @param {integer} tileIndex - The unique id of the tile across all tilesets in the map.
* @returns {object|undefined|null} * @returns {object|undefined|null}
*/ */
getTileProperty: function (tileIndex) getTileProperties: function (tileIndex)
{ {
if (!this.containsTileIndex(tileIndex)) { return null; } if (!this.containsTileIndex(tileIndex)) { return null; }
return this.tileProperties[tileIndex - this.firstgid]; return this.tileProperties[tileIndex - this.firstgid];
}, },
/** /**
* Get a tile's data that is stored in the Tileset. Returns null if tile index is not * Get a tile's data that is stored in the Tileset. Returns null if tile index is not contained
* contained in this Tileset. * in this Tileset. This is typically defined in Tiled and will contain both Tileset collision
* info and terrain mapping.
* *
* @param {integer} tileIndex - The unique id of the tile across all tilesets in the map. * @param {integer} tileIndex - The unique id of the tile across all tilesets in the map.
* @returns {object|undefined|null} * @returns {object|undefined|null}
@ -148,8 +150,8 @@ var Tileset = new Class({
}, },
/** /**
* Get a tile's data that is stored in the Tileset. Returns null if tile index is not * Get a tile's collision group that is stored in the Tileset. Returns null if tile index is not
* contained in this Tileset. * contained in this Tileset. This is typically defined within Tiled's tileset collision editor.
* *
* @param {integer} tileIndex - The unique id of the tile across all tilesets in the map. * @param {integer} tileIndex - The unique id of the tile across all tilesets in the map.
* @returns {object|null} * @returns {object|null}

View file

@ -0,0 +1,59 @@
var SetTileCollision = require('./SetTileCollision');
var CalculateFacesWithin = require('./CalculateFacesWithin');
var HasValue = require('../../../utils/object/HasValue');
/**
* Sets collision on the tiles within a layer by checking tile properties. If a tile has a property
* that matches the given properties object, its collision flag will be set. The `collides`
* parameter controls if collision will be enabled (true) or disabled (false). Passing in
* `{ collides: true }` would update the collision flag on any tiles with a "collides" property that
* has a value of true. Any tile that doesn't have "collides" set to true will be ignored. You can
* also use an array of values, e.g. `{ types: ["stone", "lava", "sand" ] }`. If a tile has a
* "types" property that matches any of those values, its collision flag will be updated.
*
* @param {object} properties - An object with tile properties and corresponding values that should
* be checked.
* @param {boolean} [collides=true] - If true it will enable collision. If false it will clear
* collision.
* @param {boolean} [recalculateFaces=true] - Whether or not to recalculate the tile faces after the
* update.
* @param {LayerData} layer - [description]
*/
var SetCollisionByProperty = function (properties, collides, recalculateFaces, layer)
{
if (collides === undefined) { collides = true; }
if (recalculateFaces === undefined) { recalculateFaces = true; }
for (var ty = 0; ty < layer.height; ty++)
{
for (var tx = 0; tx < layer.width; tx++)
{
var tile = layer.data[ty][tx];
if (!tile) { continue; }
for (var property in properties)
{
if (!HasValue(tile.properties, property)) { continue; }
var values = properties[property];
if (!Array.isArray(values))
{
values = [ values ];
}
for (var i = 0; i < values.length; i++)
{
if (tile.properties[property] === values[i])
{
SetTileCollision(tile, collides);
}
}
}
}
}
if (recalculateFaces) { CalculateFacesWithin(0, 0, layer.width, layer.height, layer); }
};
module.exports = SetCollisionByProperty;

View file

@ -0,0 +1,43 @@
var SetTileCollision = require('./SetTileCollision');
var CalculateFacesWithin = require('./CalculateFacesWithin');
/**
* Sets collision on the tiles within a layer by checking each tile's collision group data
* (typically defined in Tiled within the tileset collision editor). If any objects are found within
* a tile's collision group, the tile's colliding information will be set. The `collides` parameter
* controls if collision will be enabled (true) or disabled (false).
*
* @param {boolean} [collides=true] - If true it will enable collision. If false it will clear
* collision.
* @param {boolean} [recalculateFaces=true] - Whether or not to recalculate the tile faces after the
* update.
* @param {LayerData} layer - [description]
*/
var SetCollisionFromCollisionGroup = function (collides, recalculateFaces, layer)
{
if (collides === undefined) { collides = true; }
if (recalculateFaces === undefined) { recalculateFaces = true; }
for (var ty = 0; ty < layer.height; ty++)
{
for (var tx = 0; tx < layer.width; tx++)
{
var tile = layer.data[ty][tx];
if (!tile) { continue; }
var collisionGroup = tile.getCollisionGroup();
// It's possible in Tiled to have a collision group without any shapes, e.g. create a
// shape and then delete the shape.
if (collisionGroup && collisionGroup.objects && collisionGroup.objects.length > 0)
{
SetTileCollision(tile, collides);
}
}
}
if (recalculateFaces) { CalculateFacesWithin(0, 0, layer.width, layer.height, layer); }
};
module.exports = SetCollisionFromCollisionGroup;

View file

@ -27,7 +27,9 @@ module.exports = {
RenderDebug: require('./RenderDebug'), RenderDebug: require('./RenderDebug'),
SetCollision: require('./SetCollision'), SetCollision: require('./SetCollision'),
SetCollisionBetween: require('./SetCollisionBetween'), SetCollisionBetween: require('./SetCollisionBetween'),
SetCollisionByProperty: require('./SetCollisionByProperty'),
SetCollisionByExclusion: require('./SetCollisionByExclusion'), SetCollisionByExclusion: require('./SetCollisionByExclusion'),
SetCollisionFromCollisionGroup: require('./SetCollisionFromCollisionGroup'),
SetTileIndexCallback: require('./SetTileIndexCallback'), SetTileIndexCallback: require('./SetTileIndexCallback'),
SetTileLocationCallback: require('./SetTileLocationCallback'), SetTileLocationCallback: require('./SetTileLocationCallback'),
Shuffle: require('./Shuffle'), Shuffle: require('./Shuffle'),

View file

@ -382,6 +382,17 @@ var DynamicTilemapLayer = new Class({
return this; return this;
}, },
/**
* See component documentation.
*
* @return {this}
*/
setCollisionByProperty: function (properties, collides, recalculateFaces)
{
TilemapComponents.SetCollisionByProperty(properties, collides, recalculateFaces, this.layer);
return this;
},
/** /**
* See component documentation. * See component documentation.
* *
@ -393,6 +404,17 @@ var DynamicTilemapLayer = new Class({
return this; return this;
}, },
/**
* See component documentation.
*
* @return {this}
*/
setCollisionFromCollisionGroup: function (collides, recalculateFaces)
{
TilemapComponents.SetCollisionFromCollisionGroup(collides, recalculateFaces, this.layer);
return this;
},
/** /**
* See component documentation. * See component documentation.
* *

View file

@ -447,6 +447,17 @@ var StaticTilemapLayer = new Class({
return this; return this;
}, },
/**
* See component documentation.
*
* @return {this}
*/
setCollisionByProperty: function (properties, collides, recalculateFaces)
{
TilemapComponents.SetCollisionByProperty(properties, collides, recalculateFaces, this.layer);
return this;
},
/** /**
* See component documentation. * See component documentation.
* *
@ -469,6 +480,17 @@ var StaticTilemapLayer = new Class({
return this; return this;
}, },
/**
* See component documentation.
*
* @return {this}
*/
setCollisionFromCollisionGroup: function (collides, recalculateFaces)
{
TilemapComponents.SetCollisionFromCollisionGroup(collides, recalculateFaces, this.layer);
return this;
},
/** /**
* See component documentation. * See component documentation.
* *

View file

@ -3,6 +3,7 @@ var EventEmitter = require('eventemitter3');
var Key = require('./keys/Key'); var Key = require('./keys/Key');
var KeyCodes = require('./keys/KeyCodes'); var KeyCodes = require('./keys/KeyCodes');
var KeyCombo = require('./combo/KeyCombo'); var KeyCombo = require('./combo/KeyCombo');
var KeyMap = require('./keys/KeyMap');
var ProcessKeyCombo = require('./combo/ProcessKeyCombo'); var ProcessKeyCombo = require('./combo/ProcessKeyCombo');
var ProcessKeyDown = require('./keys/ProcessKeyDown'); var ProcessKeyDown = require('./keys/ProcessKeyDown');
var ProcessKeyUp = require('./keys/ProcessKeyUp'); var ProcessKeyUp = require('./keys/ProcessKeyUp');
@ -215,26 +216,30 @@ var KeyboardManager = new Class({
for (var i = 0; i < len; i++) for (var i = 0; i < len; i++)
{ {
var event = queue[i]; var event = queue[i];
var code = event.keyCode;
// Will emit a keyboard or keyup event // Will emit a keyboard or keyup event
this.emit(event.type, event); this.emit(event.type, event);
if (event.type === 'keydown') if (event.type === 'keydown')
{ {
this.emit('down_' + event.keyCode, event); if (KeyMap[code])
if (keys[event.keyCode])
{ {
ProcessKeyDown(keys[event.keyCode], event); this.emit('keydown_' + KeyMap[code], event);
}
if (keys[code])
{
ProcessKeyDown(keys[code], event);
} }
} }
else else
{ {
this.emit('up_' + event.keyCode, event); this.emit('keyup_' + KeyMap[code], event);
if (keys[event.keyCode]) if (keys[code])
{ {
ProcessKeyUp(keys[event.keyCode], event); ProcessKeyUp(keys[code], event);
} }
} }
} }

View file

@ -0,0 +1,10 @@
var KeyCodes = require('./KeyCodes');
var KeyMap = {};
for (var key in KeyCodes)
{
KeyMap[KeyCodes[key]] = key;
}
module.exports = KeyMap;

View file

@ -90,25 +90,21 @@ var SceneManager = new Class({
this.start(entry); this.start(entry);
} }
// Clear the pending lists
this._start.length = 0;
this._pending.length = 0;
return;
} }
for (i = 0; i < queueLength; i++) for (i = 0; i < queueLength; i++)
{ {
entry = this._queue[i]; entry = this._queue[i];
if (entry.op === 'swapPosition') this[entry.op](entry.keyA, entry.keyB);
{
this.swapPosition(entry.keyA, entry.keyB);
}
else
{
this[entry.op](entry.key);
}
} }
// Clear the pending lists
this._start.length = 0;
this._pending.length = 0;
this._queue.length = 0; this._queue.length = 0;
}, },
@ -342,6 +338,8 @@ var SceneManager = new Class({
{ {
if (scene.create) if (scene.create)
{ {
scene.sys.settings.status = CONST.CREATING;
scene.create.call(scene, scene.sys.settings.data); scene.create.call(scene, scene.sys.settings.data);
} }
@ -902,7 +900,7 @@ var SceneManager = new Class({
{ {
if (this._processing) if (this._processing)
{ {
this._queue.push( { op: 'bringToTop', key: key }); this._queue.push( { op: 'bringToTop', keyA: key, keyB: null });
} }
else else
{ {
@ -934,7 +932,7 @@ var SceneManager = new Class({
{ {
if (this._processing) if (this._processing)
{ {
this._queue.push( { op: 'sendToBack', key: key }); this._queue.push( { op: 'sendToBack', keyA: key, keyB: null });
} }
else else
{ {
@ -966,7 +964,7 @@ var SceneManager = new Class({
{ {
if (this._processing) if (this._processing)
{ {
this._queue.push( { op: 'moveDown', key: key }); this._queue.push( { op: 'moveDown', keyA: key, keyB: null });
} }
else else
{ {
@ -1000,7 +998,7 @@ var SceneManager = new Class({
{ {
if (this._processing) if (this._processing)
{ {
this._queue.push( { op: 'moveUp', key: key }); this._queue.push( { op: 'moveUp', keyA: key, keyB: null });
} }
else else
{ {
@ -1020,6 +1018,13 @@ var SceneManager = new Class({
return this; return this;
}, },
queueOp: function (op, keyA, keyB)
{
this._queue.push( { op: op, keyA: keyA, keyB: keyB });
return this;
},
/** /**
* [description] * [description]
* *

View file

@ -1,4 +1,5 @@
var Class = require('../utils/Class'); var Class = require('../utils/Class');
var CONST = require('./const');
var PluginManager = require('../plugins/PluginManager'); var PluginManager = require('../plugins/PluginManager');
// A proxy class to the Global Scene Manager // A proxy class to the Global Scene Manager
@ -44,8 +45,16 @@ var ScenePlugin = new Class({
if (key !== this.key) if (key !== this.key)
{ {
this.manager.stop(this.key); if (this.settings.status !== CONST.RUNNING)
this.manager.start(key); {
this.manager.queueOp('stop', this.key);
this.manager.queueOp('start', key);
}
else
{
this.manager.stop(this.key);
this.manager.start(key);
}
} }
return this; return this;
@ -64,7 +73,14 @@ var ScenePlugin = new Class({
{ {
if (key && key !== this.key) if (key && key !== this.key)
{ {
this.manager.start(key); if (this.settings.status !== CONST.RUNNING)
{
this.manager.queueOp('start', key);
}
else
{
this.manager.start(key);
}
} }
return this; return this;
@ -115,7 +131,14 @@ var ScenePlugin = new Class({
{ {
if (key !== this.key) if (key !== this.key)
{ {
this.manager.switch(this.key, key); if (this.settings.status !== CONST.RUNNING)
{
this.manager.queueOp('switch', this.key, key);
}
else
{
this.manager.switch(this.key, key);
}
} }
return this; return this;

View file

@ -5,10 +5,11 @@ module.exports = {
INIT: 1, INIT: 1,
START: 2, START: 2,
LOADING: 3, LOADING: 3,
RUNNING: 4, CREATING: 4,
PAUSED: 5, RUNNING: 5,
SLEEPING: 6, PAUSED: 6,
SHUTDOWN: 7, SLEEPING: 7,
DESTROYED: 8 SHUTDOWN: 8,
DESTROYED: 9
}; };

View file

@ -120,7 +120,7 @@ var Clock = new Class({
return; return;
} }
delta * this.timeScale; delta *= this.timeScale;
for (var i = 0; i < this._active.length; i++) for (var i = 0; i < this._active.length; i++)
{ {