Merge remote-tracking branch 'origin/master'

This commit is contained in:
Pavle Goloskokovic 2018-01-20 21:23:53 +01:00
commit 0198a71cd1
34 changed files with 1225 additions and 839 deletions

View file

@ -1,6 +1,2 @@
**/.*
dist/
docs/
merge/
examples/
v3/
wip/

View file

@ -11,8 +11,8 @@ var CoreScenePlugins = [
'GameObjectCreator',
'GameObjectFactory',
'ScenePlugin',
'DisplayList',
'UpdateList'
'DisplayListPlugin',
'UpdateListPlugin'
];

View file

@ -182,6 +182,18 @@ var Config = new Class({
this.physics = GetValue(config, 'physics', {});
this.defaultPhysicsSystem = GetValue(this.physics, 'default', false);
// Loader Defaults
this.loaderBaseURL = GetValue(config, 'loader.baseURL', '');
this.loaderPath = GetValue(config, 'loader.path', '');
this.loaderEnableParallel = GetValue(config, 'loader.enableParallel', true);
this.loaderMaxParallelDownloads = GetValue(config, 'loader.maxParallelDownloads', 4);
this.loaderCrossOrigin = GetValue(config, 'loader.crossOrigin', undefined);
this.loaderResponseType = GetValue(config, 'loader.responseType', '');
this.loaderAsync = GetValue(config, 'loader.async', true);
this.loaderUser = GetValue(config, 'loader.user', '');
this.loaderPassword = GetValue(config, 'loader.password', '');
this.loaderTimeout = GetValue(config, 'loader.timeout', 0);
// Scene Plugins
this.defaultPlugins = GetValue(config, 'plugins', DefaultScenePlugins);

View file

@ -105,7 +105,7 @@ var DebugHeader = function (game)
}
// Keep this during dev build only
console.log(CHECKSUM.build);
// console.log(CHECKSUM.build);
};
module.exports = DebugHeader;

View file

@ -226,9 +226,6 @@ var Game = new Class({
*/
step: function (time, delta)
{
var active = this.scene.active;
var renderer = this.renderer;
// Global Managers
this.input.update(time, delta);
@ -239,28 +236,21 @@ var Game = new Class({
this.onStepCallback();
for (var i = 0; i < active.length; i++)
{
active[i].scene.sys.step(time, delta);
}
this.scene.update(time, delta);
// Render
// var interpolation = this.frameDelta / this.timestep;
var renderer = this.renderer;
renderer.preRender();
this.events.emit('prerender');
this.events.emit('prerender', renderer);
// This uses active.length, in case scene.update removed the scene from the active list
for (i = 0; i < active.length; i++)
{
active[i].scene.sys.render(0, renderer);
}
this.scene.render(renderer);
renderer.postRender();
this.events.emit('postrender');
this.events.emit('postrender', renderer);
},
/**

View file

@ -1,23 +1,12 @@
var Class = require('../utils/Class');
var StableSort = require('../utils/array/StableSort');
var PluginManager = require('../plugins/PluginManager');
var DisplayList = new Class({
initialize:
function DisplayList (scene)
function DisplayList ()
{
// The Scene that owns this plugin
this.scene = scene;
this.systems = scene.sys;
if (!scene.sys.settings.isBooted)
{
scene.sys.events.once('boot', this.boot, this);
}
// The objects that belong to this collection.
// The equivalent of the old `Sprite.children` array.
this.list = [];
@ -27,14 +16,6 @@ var DisplayList = new Class({
this.position = 0;
},
boot: function ()
{
var eventEmitter = this.systems.events;
eventEmitter.on('shutdown', this.shutdown, this);
eventEmitter.on('destroy', this.destroy, this);
},
process: function ()
{
if (this.sortChildrenFlag)
@ -725,6 +706,4 @@ var DisplayList = new Class({
});
PluginManager.register('DisplayList', DisplayList, 'displayList');
module.exports = DisplayList;

View file

@ -0,0 +1,48 @@
var Class = require('../utils/Class');
var DisplayList = require('./DisplayList');
var PluginManager = require('../plugins/PluginManager');
var DisplayListPlugin = new Class({
Extends: DisplayList,
initialize:
function DisplayListPlugin (scene)
{
// The Scene that owns this plugin
this.scene = scene;
this.systems = scene.sys;
if (!scene.sys.settings.isBooted)
{
scene.sys.events.once('boot', this.boot, this);
}
DisplayList.call(this);
},
boot: function ()
{
var eventEmitter = this.systems.events;
eventEmitter.on('shutdown', this.shutdown, this);
eventEmitter.on('destroy', this.destroy, this);
},
shutdown: function ()
{
this.removeAll();
},
destroy: function ()
{
this.shutdown();
}
});
PluginManager.register('DisplayListPlugin', DisplayListPlugin, 'displayList');
module.exports = DisplayListPlugin;

View file

@ -1,36 +1,16 @@
var Class = require('../utils/Class');
var PluginManager = require('../plugins/PluginManager');
var UpdateList = new Class({
initialize:
function UpdateList (scene)
function UpdateList ()
{
this.scene = scene;
this.systems = scene.sys;
if (!scene.sys.settings.isBooted)
{
scene.sys.events.once('boot', this.boot, this);
}
this._list = [];
this._pendingInsertion = [];
this._pendingRemoval = [];
},
boot: function ()
{
var eventEmitter = this.systems.events;
eventEmitter.on('preupdate', this.preUpdate, this);
eventEmitter.on('update', this.update, this);
eventEmitter.on('shutdown', this.shutdown, this);
eventEmitter.on('destroy', this.destroy, this);
},
add: function (child)
{
// Is child already in this list?
@ -130,12 +110,8 @@ var UpdateList = new Class({
destroy: function ()
{
this.shutdown();
this.scene = undefined;
}
});
PluginManager.register('UpdateList', UpdateList, 'updateList');
module.exports = UpdateList;

View file

@ -0,0 +1,46 @@
var Class = require('../utils/Class');
var PluginManager = require('../plugins/PluginManager');
var UpdateList = require('./UpdateList');
var UpdateListPlugin = new Class({
Extends: UpdateList,
initialize:
function UpdateListPlugin (scene)
{
this.scene = scene;
this.systems = scene.sys;
if (!scene.sys.settings.isBooted)
{
scene.sys.events.once('boot', this.boot, this);
}
UpdateList.call(this);
},
boot: function ()
{
var eventEmitter = this.systems.events;
eventEmitter.on('preupdate', this.preUpdate, this);
eventEmitter.on('update', this.update, this);
eventEmitter.on('shutdown', this.shutdown, this);
eventEmitter.on('destroy', this.destroy, this);
},
destroy: function ()
{
this.shutdown();
this.scene = undefined;
}
});
PluginManager.register('UpdateListPlugin', UpdateListPlugin, 'updateList');
module.exports = UpdateListPlugin;

View file

@ -3,6 +3,7 @@ var Bob = require('./Bob');
var Class = require('../../utils/Class');
var Components = require('../components');
var DisplayList = require('../DisplayList');
var Frame = require('../../textures/Frame');
var GameObject = require('../GameObject');
/**
@ -41,7 +42,7 @@ var Blitter = new Class({
this.setTexture(texture, frame);
this.setPosition(x, y);
this.children = new DisplayList(this);
this.children = new DisplayList();
this.renderList = [];
@ -49,6 +50,7 @@ var Blitter = new Class({
},
// frame MUST be part of the Blitter texture
// and can be either a Frame object or a string
create: function (x, y, frame, visible, index)
{
if (visible === undefined) { visible = true; }
@ -58,7 +60,7 @@ var Blitter = new Class({
{
frame = this.frame;
}
else
else if (!(frame instanceof Frame))
{
frame = this.texture.get(frame);
}
@ -90,7 +92,7 @@ var Blitter = new Class({
// frame MUST be part of the Blitter texture
createMultiple: function (quantity, frame, visible)
{
if (frame === undefined) { frame = this.frame; }
if (frame === undefined) { frame = this.frame.name; }
if (visible === undefined) { visible = true; }
if (!Array.isArray(frame))

View file

@ -23,7 +23,10 @@ var BlitterCanvasRenderer = function (renderer, src, interpolationPercentage, ca
ca = renderer.setAlpha(bob.alpha);
}
renderer.blitImage(bob.x, bob.y, bob.frame, camera);
// var x = src.x + bob.x + frame.x - cameraScrollX + ((frame.width) * (bob.flipX ? 1 : 0));
// var y = src.y + bob.y + frame.y - cameraScrollY + ((frame.height) * (bob.flipY ? 1 : 0));
renderer.blitImage(src.x + bob.x, src.y + bob.y, bob.frame, camera);
}
};

View file

@ -33,8 +33,8 @@ var BlitterWebGLRenderer = function (renderer, src, interpolationPercentage, cam
var uvs = frame.uvs;
var width = frame.width * (bob.flipX ? -1 : 1);
var height = frame.height * (bob.flipY ? -1 : 1);
var x = bob.x + frame.x - cameraScrollX + ((frame.width) * (bob.flipX ? 1 : 0.0));
var y = bob.y + frame.y - cameraScrollY + ((frame.height) * (bob.flipY ? 1 : 0.0));
var x = src.x + bob.x + frame.x - cameraScrollX + ((frame.width) * (bob.flipX ? 1 : 0));
var y = src.y + bob.y + frame.y - cameraScrollY + ((frame.height) * (bob.flipY ? 1 : 0));
var xw = x + width;
var yh = y + height;
var tx = x * a + y * c + e;

View file

@ -20,6 +20,20 @@ var Bob = new Class({
this.flipY = false;
},
setFrame: function (frame)
{
if (frame === undefined)
{
frame = this.parent.frame;
}
else
{
frame = this.parent.texture.get(frame);
}
return this;
},
resetFlip: function ()
{
this.flipX = false;
@ -33,6 +47,42 @@ var Bob = new Class({
this.frame = frame;
},
setFlipX: function (value)
{
this.flipX = value;
return this;
},
setFlipY: function (value)
{
this.flipY = value;
return this;
},
setFlip: function (x, y)
{
this.flipX = x;
this.flipY = y;
return this;
},
setVisible: function (value)
{
this.visible = value;
return this;
},
setAlpha: function (value)
{
this.alpha = value;
return this;
},
destroy: function ()
{
this.parent.dirty = true;

View file

@ -3,7 +3,9 @@
var GameObjects = {
DisplayList: require('./DisplayList'),
DisplayListPlugin: require('./DisplayListPlugin'),
UpdateList: require('./UpdateList'),
UpdateListPlugin: require('./UpdateListPlugin'),
GameObjectCreator: require('./GameObjectCreator'),
GameObjectFactory: require('./GameObjectFactory'),

View file

@ -38,9 +38,16 @@ var InputManager = new Class({
this.scale = { x: 1, y: 1 };
// If the top-most Scene in the Scene List receives an input it will stop input from
// propagating any lower down the scene list, i.e. if you have a UI Scene at the top
// and click something on it, that click will not then be passed down to any other
// Scene below. Disable this to have input events passed through all Scenes, all the time.
this.globalTopOnly = true;
this.ignoreEvents = false;
this.bounds;
// this._tempMatrix = new TransformMatrix();
this._tempPoint = { x: 0, y: 0 };
this._tempHitTest = [];
@ -85,6 +92,8 @@ var InputManager = new Class({
this.keyboard.update();
this.gamepad.update();
this.ignoreEvents = false;
var len = this.queue.length;
// Currently just 1 pointer supported

View file

@ -210,6 +210,8 @@ var InputPlugin = new Class({
// Contains ALL Game Objects currently over in the array
this.emit('pointerdown', pointer, currentlyOver);
var total = 0;
// Go through all objects the pointer was over and fire their events / callbacks
for (var i = 0; i < currentlyOver.length; i++)
{
@ -220,10 +222,14 @@ var InputPlugin = new Class({
continue;
}
total++;
gameObject.emit('pointerdown', pointer, gameObject.input.localX, gameObject.input.localY, pointer.camera);
this.emit('gameobjectdown', pointer, gameObject);
}
return total;
},
processDragEvents: function (pointer, time)
@ -231,7 +237,7 @@ var InputPlugin = new Class({
if (this._draggable.length === 0)
{
// There are no draggable items, so let's not even bother going further
return;
return 0;
}
var i;
@ -481,6 +487,8 @@ var InputPlugin = new Class({
pointer.dragState = 0;
}
return (pointer.dragState > 0);
},
processMoveEvents: function (pointer)
@ -489,6 +497,8 @@ var InputPlugin = new Class({
this.emit('pointermove', pointer, currentlyOver);
var total = 0;
// Go through all objects the pointer was over and fire their events / callbacks
for (var i = 0; i < currentlyOver.length; i++)
{
@ -499,6 +509,8 @@ var InputPlugin = new Class({
continue;
}
total++;
gameObject.emit('pointermove', pointer, gameObject.input.localX, gameObject.input.localY);
this.emit('gameobjectmove', pointer, gameObject);
@ -508,6 +520,8 @@ var InputPlugin = new Class({
break;
}
}
return total;
},
processOverOutEvents: function (pointer)
@ -611,6 +625,8 @@ var InputPlugin = new Class({
// Then sort it into display list order
this._over[pointer.id] = this.sortGameObjects(previouslyOver);
return previouslyOver.length;
},
processUpEvents: function (pointer)
@ -808,6 +824,13 @@ var InputPlugin = new Class({
return this;
},
setGlobalTopOnly: function (value)
{
this.manager.globalTopOnly = value;
return this;
},
setTopOnly: function (value)
{
this.topOnly = value;
@ -887,9 +910,27 @@ var InputPlugin = new Class({
return interactiveObjects.sort(this.sortHandlerIO.bind(this));
},
stopPropagation: function ()
{
if (this.manager.globalTopOnly)
{
this.manager.ignoreEvents = true;
}
return this;
},
update: function (time, delta)
{
var pointer = this.manager.activePointer;
var manager = this.manager;
// Another Scene above this one has already consumed the input events
if (manager.globalTopOnly && manager.ignoreEvents)
{
return;
}
var pointer = manager.activePointer;
var runUpdate = (pointer.dirty || this.pollRate === 0);
@ -921,16 +962,16 @@ var InputPlugin = new Class({
this._temp.splice(1);
}
this.processDragEvents(pointer, time);
var total = this.processDragEvents(pointer, time);
if (!pointer.wasTouch)
{
this.processOverOutEvents(pointer);
total += this.processOverOutEvents(pointer);
}
if (pointer.justDown)
{
this.processDownEvents(pointer);
total += this.processDownEvents(pointer);
}
if (pointer.justUp)
@ -940,7 +981,13 @@ var InputPlugin = new Class({
if (pointer.justMoved)
{
this.processMoveEvents(pointer);
total += this.processMoveEvents(pointer);
}
if (total > 0 && manager.globalTopOnly)
{
// We interacted with an event in this Scene, so block any Scenes below us from doing the same this frame
manager.ignoreEvents = true;
}
},

View file

@ -0,0 +1,34 @@
// XBox 360 controller
module.exports = {
UP: 12,
DOWN: 13,
LEFT: 14,
RIGHT: 15,
MENU: 16,
A: 0,
B: 1,
X: 2,
Y: 3,
LB: 4,
RB: 5,
LT: 6,
RT: 7,
BACK: 8,
START: 9,
LS: 10,
RS: 11,
LEFT_STICK_H: 0,
LEFT_STICK_V: 1,
RIGHT_STICK_H: 2,
RIGHT_STICK_V: 3
};

View file

@ -3,6 +3,7 @@
module.exports = {
DUALSHOCK_4: require('./Sony_PlayStation_DualShock_4'),
SNES_USB: require('./SNES_USB_Controller')
SNES_USB: require('./SNES_USB_Controller'),
XBOX_360: require('./XBox360_Controller')
};

View file

@ -1,4 +1,5 @@
module.exports = {
BACKSPACE: 8,
TAB: 9,
ENTER: 13,
@ -84,5 +85,9 @@ module.exports = {
PERIOD: 190,
FORWAD_SLASH: 191,
BACK_SLASH: 220,
QUOTES: 222
QUOTES: 222,
BACKTICK: 192,
OPEN_BRACKET: 219,
CLOSED_BRACKET: 221
};

View file

@ -48,6 +48,9 @@ var File = new Class({
this.xhrSettings = MergeXHRSettings(this.xhrSettings, GetFastValue(fileConfig, 'xhrSettings', {}));
}
// The LoaderPlugin instance that is loading this file
this.loader = null;
this.xhrLoader = null;
this.state = CONST.FILE_PENDING;
@ -70,8 +73,6 @@ var File = new Class({
// Multipart file? (i.e. an atlas and its json together)
this.linkFile = undefined;
this.linkType = '';
this.callback = null;
},
resetXHR: function ()
@ -81,20 +82,54 @@ var File = new Class({
this.xhrLoader.onprogress = undefined;
},
// Called when the Image loads
// ProgressEvent
// Called by the Loader, starts the actual file downloading.
// During the load the methods onLoad, onProgress, etc are called based on the XHR events.
load: function (loader)
{
this.loader = loader;
if (this.state === CONST.FILE_POPULATED)
{
this.onComplete();
loader.nextFile(this);
}
else
{
this.src = GetURL(this, loader.baseURL);
if (this.src.indexOf('data:') === 0)
{
console.log('Local data URI');
}
else
{
this.xhrLoader = XHRLoader(this, loader.xhr);
}
}
},
// Called when the file loads, is sent a DOM ProgressEvent
onLoad: function (event)
{
this.resetXHR();
this.callback(this, true);
if (event.target && event.target.status !== 200)
{
this.loader.nextFile(this, false);
}
else
{
this.loader.nextFile(this, true);
}
},
// Called when the file errors, is sent a DOM ProgressEvent
onError: function (event)
{
this.resetXHR();
this.callback(this, false);
this.loader.nextFile(this, false);
},
onProgress: function (event)
@ -105,11 +140,14 @@ var File = new Class({
this.bytesTotal = event.total;
this.percentComplete = Math.min((this.bytesLoaded / this.bytesTotal), 1);
}
// console.log(this.percentComplete + '% (' + this.bytesLoaded + ' bytes)');
// console.log(this.percentComplete + '% (' + this.bytesLoaded + ' bytes)');
this.loader.emit('fileprogress', this, this.percentComplete);
}
},
// Usually overriden by the FileTypes and is called by Loader.finishedLoading.
// The callback is Loader.processUpdate
onProcess: function (callback)
{
this.state = CONST.FILE_PROCESSING;
@ -139,25 +177,6 @@ var File = new Class({
{
this.state = CONST.FILE_COMPLETE;
}
},
// Called by the Loader, starts the actual file downloading
load: function (callback, baseURL, globalXHR)
{
if (baseURL === undefined) { baseURL = ''; }
this.callback = callback;
this.src = GetURL(this, baseURL);
if (this.src.indexOf('data:') === 0)
{
console.log('Local data URI');
}
else
{
this.xhrLoader = XHRLoader(this, globalXHR);
}
}
});

View file

@ -3,6 +3,7 @@ var CONST = require('./const');
var CustomSet = require('../structs/Set');
var EventEmitter = require('eventemitter3');
var FileTypesManager = require('./FileTypesManager');
var GetFastValue = require('../utils/object/GetFastValue');
var ParseXMLBitmapFont = require('../gameobjects/bitmaptext/ParseXMLBitmapFont');
var PluginManager = require('../plugins/PluginManager');
var XHRSettings = require('./XHRSettings');
@ -33,18 +34,31 @@ var LoaderPlugin = new Class({
// Inject the available filetypes into the Loader
FileTypesManager.install(this);
// Move to a 'setURL' method?
this.baseURL = '';
this.path = '';
var gameConfig = this.systems.game.config;
var sceneConfig = this.systems.settings.loader;
// Read from Game / Scene Config
this.enableParallel = true;
this.maxParallelDownloads = 4;
this.path = '';
this.baseURL = '';
this.setBaseURL(GetFastValue(sceneConfig, 'baseURL', gameConfig.loaderBaseURL));
this.setPath(GetFastValue(sceneConfig, 'path', gameConfig.loaderPath));
this.enableParallel = GetFastValue(sceneConfig, 'enableParallel', gameConfig.loaderEnableParallel);
this.maxParallelDownloads = GetFastValue(sceneConfig, 'maxParallelDownloads', gameConfig.loaderMaxParallelDownloads);
// xhr specific global settings (can be overridden on a per-file basis)
this.xhr = XHRSettings();
this.xhr = XHRSettings(
GetFastValue(sceneConfig, 'responseType', gameConfig.loaderResponseType),
GetFastValue(sceneConfig, 'async', gameConfig.loaderAsync),
GetFastValue(sceneConfig, 'user', gameConfig.loaderUser),
GetFastValue(sceneConfig, 'password', gameConfig.loaderPassword),
GetFastValue(sceneConfig, 'timeout', gameConfig.loaderTimeout)
);
this.crossOrigin = undefined;
this.crossOrigin = GetFastValue(sceneConfig, 'crossOrigin', gameConfig.loaderCrossOrigin);
this.totalToLoad = 0;
this.progress = 0;
this.list = new CustomSet();
this.inflight = new CustomSet();
@ -63,9 +77,21 @@ var LoaderPlugin = new Class({
eventEmitter.on('destroy', this.destroy, this);
},
setBaseURL: function (url)
{
if (url !== '' && url.substr(-1) !== '/')
{
url = url.concat('/');
}
this.baseURL = url;
return this;
},
setPath: function (path)
{
if (path.substr(-1) !== '/')
if (path !== '' && path.substr(-1) !== '/')
{
path = path.concat('/');
}
@ -103,13 +129,16 @@ var LoaderPlugin = new Class({
start: function ()
{
console.log(this.scene.sys.settings.key, '- LoaderPlugin start. Files to load:', this.list.size);
// console.log(this.scene.sys.settings.key, '- Loader start. Files to load:', this.list.size);
if (!this.isReady())
{
return;
}
this.progress = 0;
this.totalToLoad = this.list.size;
this.emit('start', this);
if (this.list.size === 0)
@ -134,7 +163,11 @@ var LoaderPlugin = new Class({
updateProgress: function ()
{
this.progress = 1 - (this.list.size / this.totalToLoad);
// console.log(this.progress);
this.emit('progress', this.progress);
},
processLoadQueue: function ()
@ -145,7 +178,7 @@ var LoaderPlugin = new Class({
this.list.each(function (file)
{
if (file.state === CONST.FILE_PENDING && this.inflight.size < this.maxParallelDownloads)
if (file.state === CONST.FILE_POPULATED || (file.state === CONST.FILE_PENDING && this.inflight.size < this.maxParallelDownloads))
{
this.inflight.set(file);
@ -175,7 +208,7 @@ var LoaderPlugin = new Class({
file.crossOrigin = this.crossOrigin;
}
file.load(this.nextFile.bind(this), this.baseURL);
file.load(this);
},
nextFile: function (previousFile, success)
@ -186,15 +219,19 @@ var LoaderPlugin = new Class({
if (success)
{
this.emit('load', previousFile);
this.queue.set(previousFile);
}
else
{
this.emit('loaderror', previousFile);
this.failed.set(previousFile);
}
this.inflight.delete(previousFile);
this.updateProgress();
if (this.list.size > 0)
{
// console.log('nextFile - still something in the list');
@ -211,21 +248,30 @@ var LoaderPlugin = new Class({
{
// console.log('---> LoaderPlugin.finishedLoading PROCESSING', this.queue.size, 'files');
if(this.state === CONST.LOADER_PROCESSING)
if (this.state === CONST.LOADER_PROCESSING)
{
return;
}
this.progress = 1;
this.state = CONST.LOADER_PROCESSING;
this.storage.clear();
this.queue.each(function (file)
if (this.queue.size === 0)
{
// console.log('%c Calling process on ' + file.key, 'color: #000000; background: #ffff00;');
file.onProcess(this.processUpdate.bind(this));
}, this);
// Everything failed, so nothing to process
this.processComplete();
}
else
{
this.queue.each(function (file)
{
// console.log('%c Calling process on ' + file.key, 'color: #000000; background: #ffff00;');
file.onProcess(this.processUpdate.bind(this));
}, this);
}
},
// Called automatically by the File when it has finished processing
@ -284,7 +330,7 @@ var LoaderPlugin = new Class({
processComplete: function ()
{
console.log(this.scene.sys.settings.key, '- Loader Complete. Loaded:', this.storage.size, 'Failed:', this.failed.size);
// console.log(this.scene.sys.settings.key, '- Loader Complete. Loaded:', this.storage.size, 'Failed:', this.failed.size);
this.list.clear();
this.inflight.clear();
@ -515,15 +561,68 @@ var LoaderPlugin = new Class({
this.storage.clear();
this.removeAllListeners('start');
this.removeAllListeners('load');
this.removeAllListeners('loaderror');
this.removeAllListeners('complete');
this.tag = '';
this.path = '';
this.baseURL = '';
var gameConfig = this.systems.game.config;
var sceneConfig = this.systems.settings.loader;
this.setBaseURL(GetFastValue(sceneConfig, 'baseURL', gameConfig.loaderBaseURL));
this.setPath(GetFastValue(sceneConfig, 'path', gameConfig.loaderPath));
this.state = CONST.LOADER_IDLE;
},
loadArray: function (files)
{
if (Array.isArray(files))
{
for (var i = 0; i < files.length; i++)
{
this.file(files[i]);
}
}
return (this.list.size > 0);
},
file: function (file)
{
var entry;
var key = file.key;
switch (file.type)
{
case 'spritesheet':
entry = this.spritesheet(key, file.url, file.config, file.xhrSettings);
break;
case 'atlas':
entry = this.atlas(key, file.textureURL, file.atlasURL, file.textureXhrSettings, file.atlasXhrSettings);
break;
case 'bitmapFont':
entry = this.bitmapFont(key, file.textureURL, file.xmlURL, file.textureXhrSettings, file.xmlXhrSettings);
break;
case 'multiatlas':
entry = this.multiatlas(key, file.textureURLs, file.atlasURLs, file.textureXhrSettings, file.atlasXhrSettings);
break;
case 'audioSprite':
entry = this.audioSprite(key, file.urls, file.json, file.config, file.audioXhrSettings, file.jsonXhrSettings);
break;
// image, json, xml, binary, text, glsl, svg, obj
default:
entry = this[file.type](key, file.url, file.xhrSettings);
break;
}
return entry;
},
shutdown: function ()
{
this.reset();

View file

@ -34,6 +34,9 @@ var FILE_CONST = {
// File has been destroyed
FILE_DESTROYED: 18,
// File was populated from local data and doesn't need an HTTP request
FILE_POPULATED: 19,
TEXTURE_ATLAS_JSON_ARRAY: 20,
TEXTURE_ATLAS_JSON_HASH: 21

View file

@ -12,6 +12,8 @@ var JSONFile = new Class({
initialize:
// url can either be a string, in which case it is treated like a proper url, or an object, in which case it is treated as a ready-made JS Object
function JSONFile (key, url, path, xhrSettings)
{
var fileKey = (typeof key === 'string') ? key : GetFastValue(key, 'key', '');
@ -27,6 +29,14 @@ var JSONFile = new Class({
};
File.call(this, fileConfig);
if (typeof fileConfig.url === 'object')
{
// Object provided instead of a URL, so no need to actually load it (populate data with value)
this.data = fileConfig.url;
this.state = CONST.FILE_POPULATED;
}
},
onProcess: function (callback)

View file

@ -170,8 +170,6 @@ var CanvasRenderer = new Class({
*/
render: function (scene, children, interpolationPercentage, camera)
{
// var w = scene.sys.width;
// var h = scene.sys.height;
var ctx = scene.sys.context;
var settings = scene.sys.settings;
var scissor = (camera.x !== 0 || camera.y !== 0 || camera.width !== ctx.canvas.width || camera.height !== ctx.canvas.height);
@ -230,14 +228,13 @@ var CanvasRenderer = new Class({
{
child.mask.postRenderCanvas(this, child, camera);
}
}
// Call the Scene.render function
scene.render.call(scene, ctx, interpolationPercentage);
ctx.setTransform(1, 0, 0, 1, 0, 0);
// Emit a scene render event?
// scene.sys.events.emit('render', scene, ctx, camera);
if (camera._fadeAlpha > 0 || camera._flashAlpha > 0)
{
ctx.globalCompositeOperation = 'source-over';
@ -260,18 +257,10 @@ var CanvasRenderer = new Class({
{
ctx.restore();
}
// Blast it to the Game Canvas (if needed)
// if (settings.renderToTexture)
// {
// this.gameContext.drawImage(scene.sys.canvas, 0, 0, w, h, settings.x, settings.y, w, h);
// }
},
postRender: function ()
{
// console.log('%c render end ', 'color: #ffffff; background: #ff0000;');
var ctx = this.gameContext;
ctx.globalAlpha = 1;
@ -285,8 +274,6 @@ var CanvasRenderer = new Class({
this.snapshotCallback(CanvasSnapshot(this.gameCanvas, this.snapshotType, this.snapshotEncoder));
this.snapshotCallback = null;
}
// Add Post-render hook
},
snapshot: function (callback, type, encoderOptions)

File diff suppressed because it is too large Load diff

View file

@ -33,97 +33,20 @@ var ScenePlugin = new Class({
{
var eventEmitter = this.systems.events;
eventEmitter.on('preupdate', this.preUpdate, this);
eventEmitter.on('shutdown', this.shutdown, this);
eventEmitter.on('destroy', this.destroy, this);
},
preUpdate: function ()
{
var len = this._queue.length;
if (len === 0)
{
return;
}
var manager = this.manager;
// Process the queue
for (var i = 0; i < len; i++)
{
var action = this._queue[i];
switch (action.type)
{
case 'add':
manager.add(action.key, action.data, action.autoStart);
break;
case 'start':
manager.stop(this.key);
manager.start(action.key, action.data);
break;
case 'launch':
manager.start(action.key, action.data);
break;
case 'pause':
manager.pause(action.key);
break;
case 'resume':
manager.resume(action.key);
break;
case 'stop':
manager.stop(action.key);
break;
case 'swap':
manager.swap(this.key, action.key);
break;
case 'moveUp':
manager.moveUp(this.key);
break;
case 'moveDown':
manager.moveDown(this.key);
break;
case 'bringToTop':
manager.bringToTop(this.key);
break;
case 'sendToBack':
manager.sendToBack(this.key);
break;
case 'swapPosition':
manager.swapPosition(this.key, action.key);
break;
case 'sleep':
manager.sleep(action.key);
break;
case 'wake':
manager.wake(action.key);
break;
}
}
this._queue.length = 0;
},
// Shutdown this Scene and run the given one
start: function (key, data)
{
if (key === undefined) { key = this.key; }
this._queue.push({ type: 'start', key: key, data: data });
if (key !== this.key)
{
this.manager.stop(this.key);
this.manager.start(key);
}
return this;
},
@ -131,7 +54,7 @@ var ScenePlugin = new Class({
// Add the Scene into the Scene Manager and start it if 'autoStart' is true or the Scene config 'active' property is set
add: function (key, sceneConfig, autoStart)
{
this._queue.push({ type: 'add', key: key, data: sceneConfig, autoStart: autoStart });
this.manager.add(key, sceneConfig, autoStart);
return this;
},
@ -139,9 +62,10 @@ var ScenePlugin = new Class({
// Launch the given Scene and run it in parallel with this one
launch: function (key, data)
{
if (key === undefined) { key = this.key; }
this._queue.push({ type: 'launch', key: key, data: data });
if (key && key !== this.key)
{
this.manager.start(key);
}
return this;
},
@ -151,7 +75,7 @@ var ScenePlugin = new Class({
{
if (key === undefined) { key = this.key; }
this._queue.push({ type: 'pause', key: key });
this.manager.pause(key);
return this;
},
@ -161,7 +85,7 @@ var ScenePlugin = new Class({
{
if (key === undefined) { key = this.key; }
this._queue.push({ type: 'resume', key: key });
this.manager.resume(key);
return this;
},
@ -169,7 +93,9 @@ var ScenePlugin = new Class({
// Makes the Scene sleep (no update, no render) but doesn't shutdown
sleep: function (key)
{
this._queue.push({ type: 'sleep', key: key });
if (key === undefined) { key = this.key; }
this.manager.sleep(key);
return this;
},
@ -177,15 +103,20 @@ var ScenePlugin = new Class({
// Makes the Scene wake-up (starts update and render)
wake: function (key)
{
this._queue.push({ type: 'wake', key: key });
if (key === undefined) { key = this.key; }
this.manager.wake(key);
return this;
},
// Makes this Scene sleep then starts the Scene given
swap: function (key)
switch: function (key)
{
this._queue.push({ type: 'swap', key: key });
if (key !== this.key)
{
this.manager.switch(this.key, key);
}
return this;
},
@ -195,7 +126,14 @@ var ScenePlugin = new Class({
{
if (key === undefined) { key = this.key; }
this._queue.push({ type: 'stop', key: key });
this.manager.stop(key);
return this;
},
setActive: function (value)
{
this.settings.active = value;
return this;
},
@ -207,38 +145,11 @@ var ScenePlugin = new Class({
return this;
},
swapPosition: function (key)
isSleeping: function (key)
{
this._queue.push({ type: 'swapPosition', key: key });
},
if (key === undefined) { key = this.key; }
moveUp: function ()
{
this._queue.push({ type: 'moveUp' });
},
moveDown: function ()
{
this._queue.push({ type: 'moveDown' });
},
bringToTop: function ()
{
this._queue.push({ type: 'bringToTop' });
},
sendToBack: function ()
{
this._queue.push({ type: 'sendToBack' });
},
get: function (key)
{
return this.manager.getScene(key);
},
transitionTo: function (key, duration)
{
return this.manager.isSleeping(key);
},
isActive: function (key)
@ -248,6 +159,64 @@ var ScenePlugin = new Class({
return this.manager.isActive(key);
},
isVisible: function (key)
{
if (key === undefined) { key = this.key; }
return this.manager.isVisible(key);
},
swapPosition: function (key)
{
if (key && key !== this.key)
{
this.manager.swapPosition(this.key, key);
}
return this;
},
moveUp: function (key)
{
if (key === undefined) { key = this.key; }
this.manager.moveUp(key);
return this;
},
moveDown: function (key)
{
if (key === undefined) { key = this.key; }
this.manager.moveDown(key);
return this;
},
bringToTop: function (key)
{
if (key === undefined) { key = this.key; }
this.manager.bringToTop(key);
return this;
},
sendToBack: function (key)
{
if (key === undefined) { key = this.key; }
this.manager.sendToBack(key);
return this;
},
get: function (key)
{
return this.manager.getScene(key);
},
shutdown: function ()
{
// TODO

View file

@ -21,8 +21,6 @@ var Settings = {
status: CONST.PENDING,
op: CONST.BOOT,
key: GetValue(config, 'key', ''),
active: GetValue(config, 'active', false),
visible: GetValue(config, 'visible', true),
@ -47,21 +45,13 @@ var Settings = {
physics: GetValue(config, 'physics', {}),
// Loader
loader: GetValue(config, 'loader', {}),
// Plugins
plugins: GetValue(config, 'plugins', false),
// Scene Render Settings (applies only to this Scene)
scaleMode: GetValue(config, 'scaleMode', ScaleModes.DEFAULT),
roundPixels: GetValue(config, 'roundPixels', false),
dirtyRender: GetValue(config, 'dirtyRender', false),
renderToTexture: GetValue(config, 'renderToTexture', false),
// The following only apply if renderToTexture is true
autoResize: GetValue(config, 'autoResize', false)
plugins: GetValue(config, 'plugins', false)
};
}

View file

@ -1,4 +1,5 @@
var Class = require('../utils/Class');
var CONST = require('./const');
var CoreScenePlugins = require('../CoreScenePlugins');
var GetPhysicsPlugins = require('./GetPhysicsPlugins');
var GetScenePlugins = require('./GetScenePlugins');
@ -19,8 +20,7 @@ var Systems = new Class({
this.settings = Settings.create(config);
// Set by the SceneManager - a reference to the Scene canvas / context
// A handy reference to the Scene canvas / context
this.canvas;
this.context;
@ -46,8 +46,13 @@ var Systems = new Class({
init: function (game)
{
this.settings.status = CONST.INIT;
this.game = game;
this.canvas = game.canvas;
this.context = game.context;
var pluginManager = game.plugins;
this.plugins = pluginManager;
@ -79,11 +84,6 @@ var Systems = new Class({
{
this.events.emit('preupdate', time, delta);
if (!this.settings.active)
{
return;
}
this.events.emit('update', time, delta);
this.scene.update.call(this.scene, time, delta);
@ -91,18 +91,15 @@ var Systems = new Class({
this.events.emit('postupdate', time, delta);
},
render: function (interpolation, renderer)
render: function (renderer)
{
if (!this.settings.visible)
{
return;
}
var displayList = this.displayList;
displayList.process();
this.cameras.render(renderer, displayList, interpolation);
this.cameras.render(renderer, displayList);
this.events.emit('render', renderer);
},
// Force a sort of the display list on the next render
@ -120,25 +117,31 @@ var Systems = new Class({
// A paused Scene still renders, it just doesn't run ANY of its update handlers or systems
pause: function ()
{
// Was paused by the SceneManager
if (this.settings.active)
{
this.settings.status = CONST.PAUSED;
this.settings.active = false;
this.settings.active = false;
this.events.emit('pause', this);
this.events.emit('pause', this);
}
},
resume: function ()
{
// Was resumed by the SceneManager
if (!this.settings.active)
{
this.settings.status = CONST.RUNNING;
this.settings.active = true;
this.settings.active = true;
this.events.emit('resume', this);
this.events.emit('resume', this);
}
},
sleep: function ()
{
// Was sent to sleep by the SceneManager
this.settings.status = CONST.SLEEPING;
this.settings.active = false;
this.settings.visible = false;
@ -148,7 +151,7 @@ var Systems = new Class({
wake: function ()
{
// Was woken up by the SceneManager
this.settings.status = CONST.RUNNING;
this.settings.active = true;
this.settings.visible = true;
@ -156,9 +159,43 @@ var Systems = new Class({
this.events.emit('wake', this);
},
isSleeping: function ()
{
return (this.settings.status === CONST.SLEEPING);
},
isActive: function ()
{
return (this.settings.status === CONST.RUNNING);
},
isVisible: function ()
{
return this.settings.visible;
},
setVisible: function (value)
{
this.settings.visible = value;
return this;
},
setActive: function (value)
{
if (value)
{
return this.resume();
}
else
{
return this.pause();
}
},
start: function (data)
{
// Was started by the SceneManager
this.settings.status = CONST.START;
this.settings.data = data;
@ -170,7 +207,7 @@ var Systems = new Class({
shutdown: function ()
{
// Was stopped by the SceneManager
this.settings.status = CONST.SHUTDOWN;
this.settings.active = false;
this.settings.visible = false;
@ -180,6 +217,8 @@ var Systems = new Class({
destroy: function ()
{
this.settings.status = CONST.DESTROYED;
this.events.emit('destroy', this);
}

View file

@ -2,14 +2,13 @@
module.exports = {
PENDING: 0,
INSTALLED: 1,
BOOT: 0,
INIT: 1,
PRELOAD: 2,
CREATE: 3,
UPDATE: 4,
RENDER: 5,
SHUTDOWN: 6
START: 2,
LOADING: 3,
RUNNING: 4,
PAUSED: 5,
SLEEPING: 6,
SHUTDOWN: 7,
DESTROYED: 8
};

View file

@ -80,6 +80,16 @@ var Frame = new Class({
*/
this.centerY = Math.floor(height / 2);
/**
* @property {number} pivotX - The horizontal pivot point of this Frame.
*/
this.pivotX = 0;
/**
* @property {number} height - The vertical pivot point of this Frame.
*/
this.pivotY = 0;
/**
* Is this frame is rotated or not in the Texture?
* Rotation allows you to use rotated frames in texture atlas packing.
@ -93,6 +103,9 @@ var Frame = new Class({
// Over-rides the Renderer setting? -1 = use Renderer Setting, 0 = No rounding, 1 = Round
this.autoRound = -1;
// Any Frame specific custom data can be stored here
this.customData = {};
/**
* The un-modified source frame, trim and UV data.
*

View file

@ -36,6 +36,9 @@ var Texture = new Class({
this.frames = {};
// Any additional data that was set in the source JSON (if any), or any extra data you'd like to store relating to this texture
this.customData = {};
this.firstFrame = '__BASE';
this.frameTotal = 0;
@ -74,7 +77,7 @@ var Texture = new Class({
get: function (name)
{
if (name === undefined || name === null)
if (name === undefined || name === null || (typeof name !== 'string' && typeof name !== 'number'))
{
name = (this.frameTotal === 1) ? '__BASE' : this.firstFrame;
}

View file

@ -323,6 +323,21 @@ var TextureManager = new Class({
}
},
getTextureKeys: function ()
{
var output = [];
for (var key in this.list)
{
if (key !== '__DEFAULT' && key !== '__MISSING')
{
output.push(key);
}
}
return output;
},
getPixel: function (x, y, key, frame)
{
var textureFrame = this.getFrame(key, frame);

View file

@ -1,3 +1,5 @@
var Clone = require('../../utils/object/Clone');
var JSONArray = function (texture, sourceIndex, json)
{
// Malformed?
@ -9,6 +11,7 @@ var JSONArray = function (texture, sourceIndex, json)
// Add in a __BASE entry (for the entire atlas)
var source = texture.source[sourceIndex];
texture.add('__BASE', sourceIndex, 0, 0, source.width, source.height);
// By this stage frames is a fully parsed array
@ -40,6 +43,27 @@ var JSONArray = function (texture, sourceIndex, json)
newFrame.rotated = true;
newFrame.updateUVsInverted();
}
// Copy over any extra data
newFrame.customData = Clone(src);
}
// Copy over any additional data that was in the JSON to Texture.customData
for (var dataKey in json)
{
if (dataKey === 'frames')
{
continue;
}
if (Array.isArray(json[dataKey]))
{
texture.customData[dataKey] = json[dataKey].slice(0);
}
else
{
texture.customData[dataKey] = json[dataKey];
}
}
return texture;

View file

@ -1,3 +1,5 @@
var Clone = require('../../utils/object/Clone');
var JSONHash = function (texture, sourceIndex, json)
{
// Malformed?
@ -9,6 +11,7 @@ var JSONHash = function (texture, sourceIndex, json)
// Add in a __BASE entry (for the entire atlas)
var source = texture.source[sourceIndex];
texture.add('__BASE', sourceIndex, 0, 0, source.width, source.height);
// By this stage frames is a fully parsed Object
@ -40,6 +43,27 @@ var JSONHash = function (texture, sourceIndex, json)
newFrame.rotated = true;
newFrame.updateUVsInverted();
}
// Copy over any extra data
newFrame.customData = Clone(src);
}
// Copy over any additional data that was in the JSON to Texture.customData
for (var dataKey in json)
{
if (dataKey === 'frames')
{
continue;
}
if (Array.isArray(json[dataKey]))
{
texture.customData[dataKey] = json[dataKey].slice(0);
}
else
{
texture.customData[dataKey] = json[dataKey];
}
}
return texture;