mirror of
https://github.com/photonstorm/phaser
synced 2024-11-23 13:13:43 +00:00
Huge refactor to sort out the game loop flow.
This commit is contained in:
parent
0b63a4fa01
commit
6ee499132c
22 changed files with 392 additions and 569 deletions
|
@ -270,29 +270,23 @@ When the DOM Content Loaded event happens, the Game calls Game.boot. This sets-u
|
||||||
|
|
||||||
### A single tick
|
### A single tick
|
||||||
|
|
||||||
Every time RAF ticks it calls the following:
|
Every time RAF ticks it calls the following (in order)
|
||||||
|
|
||||||
1. --removed--
|
1. `Game.step` is called, which calls ...
|
||||||
2. Calls `StateManager.step`, which ...
|
2. `Game.mainloop.step` which checks frame rate, updates delta values, etc
|
||||||
3. Iterates through all _active_ States, and ...
|
3. This calls `State.sys.begin` once for all _active_ States
|
||||||
4. Calls `State.sys.mainloop.step`, which ...
|
4. While the frame delta is within range it calls `State.sys.update`
|
||||||
5. Checks if the frame rate is throttled, and returns if so, otherwise ...
|
5. This iterates all `State.children`, and calls `update` if they exist
|
||||||
6. It updates the frame delta values, then ...
|
6. It then calls `State.update` (dev level callback)
|
||||||
7. Calls `State.sys.begin` (which is an empty function by default)
|
7. When the loop exits (because the frameDelta is > the step size) it ..
|
||||||
8. While the frame delta is within range, it ...
|
8. `Renderer.preRender` which resets the canvas, cls, then ...
|
||||||
9. Calls `State.sys.update` (empty by default)
|
9. Calls `State.sys.render` on all _active_ States, which each calls ...
|
||||||
10. If then iterates through all `State.children`, and if they exist calls `update` on each of them
|
10. `State.sys.updates.start` which processes the Update Managers list
|
||||||
11. It then calls `State.update`
|
11. If the State is visible, it then calls `Game.renderer.render`, which ...
|
||||||
12. When the while loop exits (because the frameDelta is > the step size), it ...
|
12. Iterates through all children calling `child.render` on each one.
|
||||||
13. Calls `State.sys.preRender` (empty)
|
13. It then calls `State.sys.updates.stop` - which stops the Update Manager
|
||||||
14. Calls `State.sys.updates.start` - this process the Update Managers list
|
14. Then calls `State.render` (dev level callback)
|
||||||
15. If the State is visible, it then calls `Game.renderer.render`, passing in the State ...
|
15. Finally mainloop calls `Renderer.postRender` and resets the panic flags.
|
||||||
16. If the Renderer is running it performs all of the related set-up calls (setting the blend mode, clearing the canvas, etc), then ...
|
|
||||||
17. Starts the Batch Manager (`src/renderer/webgl/BatchManager.start`)
|
|
||||||
18. Calls `StateManager.renderChildren`, which ...
|
|
||||||
19. Iterates through all children of the current State, calling `child.render` on each one.
|
|
||||||
20. It then calls `State.sys.updates.stop` - which stops the Update Manager
|
|
||||||
21. Finally it calls `State.sys.end` which just resets the frame delta / panic flags.
|
|
||||||
|
|
||||||
In a tree form it maps to the following:
|
In a tree form it maps to the following:
|
||||||
|
|
||||||
|
@ -321,6 +315,9 @@ In a tree form it maps to the following:
|
||||||
+- State.sys.end (resets frame delta and panic flags)
|
+- State.sys.end (resets frame delta and panic flags)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
The above is subject to change heavily! There are currently lots of empty function calls in there (State.sys.update for example), so we may well optimize this path considerably.
|
The above is subject to change heavily! There are currently lots of empty function calls in there (State.sys.update for example), so we may well optimize this path considerably.
|
||||||
|
|
||||||
In essence though the concept is: Once per frame we update all the timing values, update the core systems, update the children, and repeat this until our step value is high enough, then we render everything.
|
In essence though the concept is: Once per frame we update all the timing values, update the core systems, update the children, and repeat this until our step value is high enough, then we render everything.
|
||||||
|
|
|
@ -51,6 +51,7 @@ var Config = function (config)
|
||||||
this.bannerTextColor = GetObjectValue(config, 'banner.text', defaultBannerTextColor);
|
this.bannerTextColor = GetObjectValue(config, 'banner.text', defaultBannerTextColor);
|
||||||
this.bannerBackgroundColor = GetObjectValue(config, 'banner.background', defaultBannerColor);
|
this.bannerBackgroundColor = GetObjectValue(config, 'banner.background', defaultBannerColor);
|
||||||
|
|
||||||
|
this.fps = GetObjectValue(config, 'fps', 60);
|
||||||
this.forceSetTimeOut = GetObjectValue(config, 'forceSetTimeOut', false);
|
this.forceSetTimeOut = GetObjectValue(config, 'forceSetTimeOut', false);
|
||||||
this.transparent = GetObjectValue(config, 'transparent', false);
|
this.transparent = GetObjectValue(config, 'transparent', false);
|
||||||
this.pixelArt = GetObjectValue(config, 'pixelArt', false);
|
this.pixelArt = GetObjectValue(config, 'pixelArt', false);
|
||||||
|
|
|
@ -12,6 +12,7 @@ var AddToDOM = require('../dom/AddToDOM');
|
||||||
var RequestAnimationFrame = require('../dom/RequestAnimationFrame');
|
var RequestAnimationFrame = require('../dom/RequestAnimationFrame');
|
||||||
var DOMContentLoaded = require('../dom/DOMContentLoaded');
|
var DOMContentLoaded = require('../dom/DOMContentLoaded');
|
||||||
|
|
||||||
|
var MainLoop = require('./MainLoop');
|
||||||
var CreateRenderer = require('./CreateRenderer');
|
var CreateRenderer = require('./CreateRenderer');
|
||||||
var StateManager = require('../state/StateManager');
|
var StateManager = require('../state/StateManager');
|
||||||
var TextureManager = require('../textures/TextureManager');
|
var TextureManager = require('../textures/TextureManager');
|
||||||
|
@ -58,6 +59,12 @@ var Game = function (config)
|
||||||
*/
|
*/
|
||||||
this.device = Device;
|
this.device = Device;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property {Phaser.MainLoop} mainloop - Main Loop handler.
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
this.mainloop = new MainLoop(this.config.fps);
|
||||||
|
|
||||||
// Wait for the DOM Ready event, then call boot.
|
// Wait for the DOM Ready event, then call boot.
|
||||||
DOMContentLoaded(this.boot.bind(this));
|
DOMContentLoaded(this.boot.bind(this));
|
||||||
|
|
||||||
|
@ -87,7 +94,15 @@ Game.prototype = {
|
||||||
|
|
||||||
this.config.postBoot();
|
this.config.postBoot();
|
||||||
|
|
||||||
this.raf.start(this.state.step.bind(this.state), this.config.forceSetTimeOut);
|
this.mainloop.start();
|
||||||
|
|
||||||
|
this.raf.start(this.step.bind(this), this.config.forceSetTimeOut);
|
||||||
|
},
|
||||||
|
|
||||||
|
step: function (timestamp)
|
||||||
|
{
|
||||||
|
// Pass in via game to 'start' instead of every update?
|
||||||
|
this.mainloop.step(timestamp, this.state.active, this.renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
232
v3/src/boot/MainLoop.js
Normal file
232
v3/src/boot/MainLoop.js
Normal file
|
@ -0,0 +1,232 @@
|
||||||
|
/**
|
||||||
|
* @author Richard Davey <rich@photonstorm.com>
|
||||||
|
* @copyright 2016 Photon Storm Ltd.
|
||||||
|
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// My thanks to Isaac Sukin for creating MainLoop.js, on which lots of this is based.
|
||||||
|
|
||||||
|
var MainLoop = function (framerate)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @property {number} timestep - The amount of time (in milliseconds) to simulate each time update() runs.
|
||||||
|
*/
|
||||||
|
this.timestep = 1000 / framerate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property {number} physicsStep - 1 / framerate.
|
||||||
|
*/
|
||||||
|
this.physicsStep = 1 / framerate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property {number} frameDelta - The cumulative amount of in-app time that hasn't been simulated yet.
|
||||||
|
*/
|
||||||
|
this.frameDelta = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The timestamp in milliseconds of the last time the main loop was run.
|
||||||
|
* Used to compute the time elapsed between frames.
|
||||||
|
* @property {number} lastFrameTimeMs
|
||||||
|
*/
|
||||||
|
this.lastFrameTimeMs = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property {number} fps - An exponential moving average of the frames per second.
|
||||||
|
*/
|
||||||
|
this.fps = 60;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property {number} lastFpsUpdate - The timestamp (in milliseconds) of the last time the `fps` moving average was updated.
|
||||||
|
*/
|
||||||
|
this.lastFpsUpdate = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property {number} framesThisSecond - The number of frames delivered in the current second.
|
||||||
|
*/
|
||||||
|
this.framesThisSecond = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property {number} numUpdateSteps - The number of times update() is called in a given frame.
|
||||||
|
*/
|
||||||
|
this.numUpdateSteps = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The minimum amount of time in milliseconds that must pass since the last frame was executed
|
||||||
|
* before another frame can be executed.
|
||||||
|
* The multiplicative inverse caps the FPS (the default of zero means there is no cap)
|
||||||
|
* @property {number} minFrameDelay
|
||||||
|
*/
|
||||||
|
this.minFrameDelay = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property {boolean} running - Whether the main loop is running.
|
||||||
|
*/
|
||||||
|
this.running = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* `true` if `MainLoop.start()` has been called and the most recent time it
|
||||||
|
* was called has not been followed by a call to `MainLoop.stop()`. This is
|
||||||
|
* different than `running` because there is a delay of a few milliseconds
|
||||||
|
* after `MainLoop.start()` is called before the application is considered
|
||||||
|
* "running." This delay is due to waiting for the next frame.
|
||||||
|
* @property {boolean} started
|
||||||
|
*/
|
||||||
|
this.started = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the simulation has fallen too far behind real time.
|
||||||
|
* Specifically, `panic` will be set to `true` if too many updates occur in
|
||||||
|
* one frame. This is only relevant inside of animate(), but a reference is
|
||||||
|
* held externally so that this variable is not marked for garbage
|
||||||
|
* collection every time the main loop runs.
|
||||||
|
* @property {boolean} panic - Whether the simulation has fallen too far behind real time.
|
||||||
|
*/
|
||||||
|
this.panic = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
MainLoop.prototype.constructor = MainLoop;
|
||||||
|
|
||||||
|
MainLoop.prototype = {
|
||||||
|
|
||||||
|
setMaxFPS: function (fps)
|
||||||
|
{
|
||||||
|
if (fps === 0)
|
||||||
|
{
|
||||||
|
this.stop();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.minFrameDelay = 1000 / fps;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getMaxFPS: function ()
|
||||||
|
{
|
||||||
|
return 1000 / this.minFrameDelay;
|
||||||
|
},
|
||||||
|
|
||||||
|
resetFrameDelta: function ()
|
||||||
|
{
|
||||||
|
var oldFrameDelta = this.frameDelta;
|
||||||
|
|
||||||
|
this.frameDelta = 0;
|
||||||
|
|
||||||
|
return oldFrameDelta;
|
||||||
|
},
|
||||||
|
|
||||||
|
start: function ()
|
||||||
|
{
|
||||||
|
if (this.started)
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.started = true;
|
||||||
|
this.running = true;
|
||||||
|
|
||||||
|
this.lastFrameTimeMs = window.performance.now();
|
||||||
|
this.lastFpsUpdate = window.performance.now();
|
||||||
|
this.framesThisSecond = 0;
|
||||||
|
},
|
||||||
|
|
||||||
|
// timestamp = DOMHighResTimeStamp
|
||||||
|
// active = array containing: ({ index: i, state: state })
|
||||||
|
|
||||||
|
step: function (timestamp, active, renderer)
|
||||||
|
{
|
||||||
|
// Throttle the frame rate (if minFrameDelay is set to a non-zero value by
|
||||||
|
// `MainLoop.setMaxAllowedFPS()`).
|
||||||
|
if (active.length === 0 || timestamp < this.lastFrameTimeMs + this.minFrameDelay)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// frameDelta is the cumulative amount of in-app time that hasn't been
|
||||||
|
// simulated yet. Add the time since the last frame. We need to track total
|
||||||
|
// not-yet-simulated time (as opposed to just the time elapsed since the
|
||||||
|
// last frame) because not all actually elapsed time is guaranteed to be
|
||||||
|
// simulated each frame. See the comments below for details.
|
||||||
|
this.frameDelta += timestamp - this.lastFrameTimeMs;
|
||||||
|
this.lastFrameTimeMs = timestamp;
|
||||||
|
|
||||||
|
// Run any updates that are not dependent on time in the simulation.
|
||||||
|
// Here we'll need to run things like tween.update, input.update, etc.
|
||||||
|
|
||||||
|
for (var i = 0; i < active.length; i++)
|
||||||
|
{
|
||||||
|
active[i].state.sys.begin(timestamp, this.frameDelta);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the estimate of the frame rate, `fps`. Every second, the number
|
||||||
|
// of frames that occurred in that second are included in an exponential
|
||||||
|
// moving average of all frames per second, with an alpha of 0.25. This
|
||||||
|
// means that more recent seconds affect the estimated frame rate more than
|
||||||
|
// older seconds.
|
||||||
|
if (timestamp > this.lastFpsUpdate + 1000)
|
||||||
|
{
|
||||||
|
// Compute the new exponential moving average with an alpha of 0.25.
|
||||||
|
// Using constants inline is okay here.
|
||||||
|
this.fps = 0.25 * this.framesThisSecond + 0.75 * this.fps;
|
||||||
|
|
||||||
|
this.lastFpsUpdate = timestamp;
|
||||||
|
this.framesThisSecond = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.framesThisSecond++;
|
||||||
|
|
||||||
|
this.numUpdateSteps = 0;
|
||||||
|
|
||||||
|
while (this.frameDelta >= this.timestep)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < active.length; i++)
|
||||||
|
{
|
||||||
|
active[i].state.sys.update(this.timestep, this.physicsStep);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.frameDelta -= this.timestep;
|
||||||
|
|
||||||
|
if (++this.numUpdateSteps >= 240)
|
||||||
|
{
|
||||||
|
this.panic = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render
|
||||||
|
|
||||||
|
var interpolation = this.frameDelta / this.timestep;
|
||||||
|
|
||||||
|
renderer.preRender();
|
||||||
|
|
||||||
|
for (i = 0; i < active.length; i++)
|
||||||
|
{
|
||||||
|
active[i].state.sys.render(interpolation, renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer.postRender();
|
||||||
|
|
||||||
|
if (this.panic)
|
||||||
|
{
|
||||||
|
// This pattern introduces non-deterministic behavior, but in this case
|
||||||
|
// it's better than the alternative (the application would look like it
|
||||||
|
// was running very quickly until the simulation caught up to real
|
||||||
|
// time).
|
||||||
|
var discardedTime = Math.round(this.resetFrameDelta());
|
||||||
|
|
||||||
|
console.warn('Main loop panicked, tab probably put in the background. Discarding ' + discardedTime + 'ms');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.panic = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
stop: function ()
|
||||||
|
{
|
||||||
|
this.running = false;
|
||||||
|
this.started = false;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = MainLoop;
|
|
@ -8,6 +8,9 @@ var Component = require('../components');
|
||||||
var MATH_CONST = require('../math/const');
|
var MATH_CONST = require('../math/const');
|
||||||
var WrapAngle = require('../math/angle/Wrap');
|
var WrapAngle = require('../math/angle/Wrap');
|
||||||
|
|
||||||
|
// Swap to extending a BaseTransform
|
||||||
|
// var BaseTransform = require('');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Camera is your view into the game world. It has a position and size and renders only those objects within its field of view.
|
* A Camera is your view into the game world. It has a position and size and renders only those objects within its field of view.
|
||||||
* The game automatically creates a single Stage sized camera on boot. Move the camera around the world with Phaser.Camera.x/y
|
* The game automatically creates a single Stage sized camera on boot. Move the camera around the world with Phaser.Camera.x/y
|
||||||
|
@ -30,11 +33,6 @@ var Camera = function (state, x, y, viewportWidth, viewportHeight)
|
||||||
*/
|
*/
|
||||||
this.state = state;
|
this.state = state;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property {Phaser.Game} game - A reference to the currently running Game.
|
|
||||||
*/
|
|
||||||
this.game = state.game;
|
|
||||||
|
|
||||||
this.viewportWidth = viewportWidth;
|
this.viewportWidth = viewportWidth;
|
||||||
|
|
||||||
this.viewportHeight = viewportHeight;
|
this.viewportHeight = viewportHeight;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
var CHECKSUM = {
|
var CHECKSUM = {
|
||||||
build: '56117780-e25d-11e6-9df1-9b17ba01ef95'
|
build: '1f102830-e320-11e6-897c-f1a016edce8a'
|
||||||
};
|
};
|
||||||
module.exports = CHECKSUM;
|
module.exports = CHECKSUM;
|
|
@ -1,8 +1,3 @@
|
||||||
/**
|
|
||||||
* @author Richard Davey <rich@photonstorm.com>
|
|
||||||
* @copyright 2016 Photon Storm Ltd.
|
|
||||||
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The GameObject Factory is a global level container of Factory instances.
|
* The GameObject Factory is a global level container of Factory instances.
|
||||||
|
|
|
@ -24,7 +24,7 @@ var GameObject = function (state, x, y, texture, frame, parent)
|
||||||
{
|
{
|
||||||
this.state = state;
|
this.state = state;
|
||||||
|
|
||||||
this.game = state.game;
|
this.game = state.sys.game;
|
||||||
|
|
||||||
this.name = '';
|
this.name = '';
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ var Children = require('../../components/Children');
|
||||||
*/
|
*/
|
||||||
var Blitter = function (state, x, y, key, frame)
|
var Blitter = function (state, x, y, key, frame)
|
||||||
{
|
{
|
||||||
var _texture = state.game.textures.get(key);
|
var _texture = state.sys.textures.get(key);
|
||||||
var _frame = _texture.get(frame);
|
var _frame = _texture.get(frame);
|
||||||
|
|
||||||
GameObject.call(this, state, x, y, _texture, _frame);
|
GameObject.call(this, state, x, y, _texture, _frame);
|
||||||
|
|
|
@ -1,8 +1,3 @@
|
||||||
/**
|
|
||||||
* @author Richard Davey <rich@photonstorm.com>
|
|
||||||
* @copyright 2016 Photon Storm Ltd.
|
|
||||||
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
|
|
||||||
*/
|
|
||||||
|
|
||||||
var Blitter = require('./Blitter');
|
var Blitter = require('./Blitter');
|
||||||
var FactoryContainer = require('../../gameobjects/FactoryContainer');
|
var FactoryContainer = require('../../gameobjects/FactoryContainer');
|
||||||
|
@ -11,36 +6,15 @@ var BlitterFactory = {
|
||||||
|
|
||||||
KEY: 'blitter',
|
KEY: 'blitter',
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new `Blitter` object.
|
|
||||||
*
|
|
||||||
* An Image is a light-weight object you can use to display anything that doesn't need physics or animation.
|
|
||||||
*
|
|
||||||
* It can still rotate, scale, crop and receive input events.
|
|
||||||
* This makes it perfect for logos, backgrounds, simple buttons and other non-Sprite graphics.
|
|
||||||
*
|
|
||||||
* @method Phaser.GameObject.Factory#image
|
|
||||||
* @param {number} [x=0] - The x coordinate of the Image. The coordinate is relative to any parent container this Image may be in.
|
|
||||||
* @param {number} [y=0] - The y coordinate of the Image. The coordinate is relative to any parent container this Image may be in.
|
|
||||||
* @param {string|Phaser.RenderTexture|Phaser.BitmapData|Phaser.Video|PIXI.Texture} [key] - The image used as a texture by this display object during rendering. If a string Phaser will get for an entry in the Image Cache. Or it can be an instance of a RenderTexture, BitmapData, Video or PIXI.Texture.
|
|
||||||
* @param {string|number} [frame] - If a Texture Atlas or Sprite Sheet is used this allows you to specify the frame to be used. Use either an integer for a Frame ID or a string for a frame name.
|
|
||||||
* @param {Phaser.Group} [group] - Optional Group to add the object to. If not specified it will be added to the World group.
|
|
||||||
* @return {Phaser.Image} The newly created Image object.
|
|
||||||
*/
|
|
||||||
add: function (x, y, key, frame, group)
|
add: function (x, y, key, frame, group)
|
||||||
{
|
{
|
||||||
if (group === undefined) { group = this.state; }
|
if (group === undefined) { group = this.state; }
|
||||||
|
|
||||||
// console.log('ImageFactory.add', key, x, y, frame, group);
|
|
||||||
// console.log('into State', this.state);
|
|
||||||
|
|
||||||
return group.children.add(new Blitter(this.state, x, y, key, frame));
|
return group.children.add(new Blitter(this.state, x, y, key, frame));
|
||||||
},
|
},
|
||||||
|
|
||||||
make: function (x, y, key, frame)
|
make: function (x, y, key, frame)
|
||||||
{
|
{
|
||||||
// console.log('ImageFactory.make', key, x, y, frame);
|
|
||||||
|
|
||||||
return new Blitter(this.state, x, y, key, frame);
|
return new Blitter(this.state, x, y, key, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ var GameObject = require('../GameObject');
|
||||||
*/
|
*/
|
||||||
var Image = function (state, x, y, key, frame)
|
var Image = function (state, x, y, key, frame)
|
||||||
{
|
{
|
||||||
var _texture = state.game.textures.get(key);
|
var _texture = state.sys.textures.get(key);
|
||||||
var _frame = _texture.get(frame);
|
var _frame = _texture.get(frame);
|
||||||
|
|
||||||
GameObject.call(this, state, x, y, _texture, _frame);
|
GameObject.call(this, state, x, y, _texture, _frame);
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
// Include all of the Game Object Factories
|
// Include all of the Game Object Factories
|
||||||
|
|
||||||
require('./image/ImageFactory');
|
require('./blitter/BlitterFactory');
|
||||||
require('./container/ContainerFactory');
|
require('./container/ContainerFactory');
|
||||||
|
require('./image/ImageFactory');
|
||||||
|
require('./sprite/SpriteFactory');
|
||||||
|
|
|
@ -10,7 +10,7 @@ var Children = require('../../components/Children');
|
||||||
|
|
||||||
var Sprite = function (state, x, y, key, frame)
|
var Sprite = function (state, x, y, key, frame)
|
||||||
{
|
{
|
||||||
var _texture = state.game.textures.get(key);
|
var _texture = state.sys.textures.get(key);
|
||||||
var _frame = _texture.get(frame);
|
var _frame = _texture.get(frame);
|
||||||
|
|
||||||
GameObject.call(this, state, x, y, _texture, _frame);
|
GameObject.call(this, state, x, y, _texture, _frame);
|
||||||
|
|
|
@ -226,16 +226,8 @@ WebGLRenderer.prototype = {
|
||||||
// this.projection.y = -(this.height / 2) / res;
|
// this.projection.y = -(this.height / 2) / res;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
// Call at the start of the render loop
|
||||||
* Renders the State.
|
preRender: function ()
|
||||||
*
|
|
||||||
* @method render
|
|
||||||
* @param {Phaser.State} state - The State to be rendered.
|
|
||||||
* @param {number} interpolationPercentage - The cumulative amount of time that hasn't been simulated yet, divided
|
|
||||||
* by the amount of time that will be simulated the next time update()
|
|
||||||
* runs. Useful for interpolating frames.
|
|
||||||
*/
|
|
||||||
render: function (state, interpolationPercentage)
|
|
||||||
{
|
{
|
||||||
// console.log('%c render start ', 'color: #ffffff; background: #00ff00;');
|
// console.log('%c render start ', 'color: #ffffff; background: #00ff00;');
|
||||||
|
|
||||||
|
@ -249,50 +241,50 @@ WebGLRenderer.prototype = {
|
||||||
|
|
||||||
var gl = this.gl;
|
var gl = this.gl;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// This is the old render loop - add what you need here to replace it,
|
|
||||||
// but please allow each State to render to its own Quad FBO
|
|
||||||
|
|
||||||
//var fbo = state.sys.fbo;
|
|
||||||
|
|
||||||
//fbo.activate();
|
|
||||||
|
|
||||||
// clear is needed for the FBO, otherwise corruption ...
|
// clear is needed for the FBO, otherwise corruption ...
|
||||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
this.setBlendMode(BlendModes.NORMAL);
|
this.setBlendMode(BlendModes.NORMAL);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders a single State.
|
||||||
|
*
|
||||||
|
* @method render
|
||||||
|
* @param {Phaser.State} state - The State to be rendered.
|
||||||
|
* @param {number} interpolationPercentage - The cumulative amount of time that hasn't been simulated yet, divided
|
||||||
|
* by the amount of time that will be simulated the next time update()
|
||||||
|
* runs. Useful for interpolating frames.
|
||||||
|
*/
|
||||||
|
render: function (state, interpolationPercentage)
|
||||||
|
{
|
||||||
|
var batch = this.batch;
|
||||||
|
|
||||||
// Could move to the State Systems or MainLoop
|
// Could move to the State Systems or MainLoop
|
||||||
for (var c = 0; c < state.sys.children.list.length; c++)
|
for (var c = 0; c < state.sys.children.list.length; c++)
|
||||||
{
|
{
|
||||||
var child = state.sys.children.list[c];
|
var child = state.sys.children.list[c];
|
||||||
|
|
||||||
child.renderWebGL(this, child, interpolationPercentage);
|
child.renderWebGL(this, child, interpolationPercentage);
|
||||||
var batch = this.batch;
|
|
||||||
if (batch && batch.isFull())
|
if (batch && batch.isFull())
|
||||||
|
{
|
||||||
batch.flush();
|
batch.flush();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
var batch = this.batch;
|
},
|
||||||
if (batch)
|
|
||||||
batch.flush();
|
|
||||||
|
|
||||||
//this.batch.stop();
|
// Called at the end of the render loop (tidy things up, etc)
|
||||||
|
postRender: function ()
|
||||||
// Call state.render here, so we can do some extra shizzle on the top
|
{
|
||||||
// Maybe pass in the FBO texture too?
|
if (this.batch)
|
||||||
|
{
|
||||||
//fbo.render(null);
|
this.batch.flush();
|
||||||
|
}
|
||||||
// Unbind the fbo texture and replace it with an empty texture.
|
|
||||||
// If we forget this we corrupt the main context texture!
|
|
||||||
// or get `RENDER WARNING: there is no texture bound to the unit 0` spam in the console
|
|
||||||
//gl.bindTexture(gl.TEXTURE_2D, this.emptyTexture);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// console.log('%c render end ', 'color: #ffffff; background: #ff0000;');
|
|
||||||
|
|
||||||
// Add Post-render hook
|
// Add Post-render hook
|
||||||
|
|
||||||
|
// console.log('%c render end ', 'color: #ffffff; background: #ff0000;');
|
||||||
},
|
},
|
||||||
|
|
||||||
destroy: function ()
|
destroy: function ()
|
||||||
|
|
|
@ -2,7 +2,7 @@ var CONST = require('./const');
|
||||||
var ScaleModes = require('../renderer/ScaleModes');
|
var ScaleModes = require('../renderer/ScaleModes');
|
||||||
var GetObjectValue = require('../utils/GetObjectValue');
|
var GetObjectValue = require('../utils/GetObjectValue');
|
||||||
|
|
||||||
var Settings = function (state, config)
|
var Settings = function (config)
|
||||||
{
|
{
|
||||||
if (typeof config === 'string')
|
if (typeof config === 'string')
|
||||||
{
|
{
|
||||||
|
@ -14,37 +14,32 @@ var Settings = function (state, config)
|
||||||
config = {};
|
config = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
this.state = state; // Do we actually need this reference? This could just be a property bucket
|
return {
|
||||||
|
|
||||||
this.status = CONST.PENDING;
|
status: CONST.PENDING,
|
||||||
|
|
||||||
// Which part of this State is currently being processed?
|
op: CONST.BOOT,
|
||||||
// preload, create, update, shutdown, etc
|
|
||||||
this.op = CONST.BOOT;
|
|
||||||
|
|
||||||
this.key = GetObjectValue(config, 'key', '');
|
key: GetObjectValue(config, 'key', ''),
|
||||||
this.active = GetObjectValue(config, 'active', false);
|
active: GetObjectValue(config, 'active', false),
|
||||||
this.visible = GetObjectValue(config, 'visible', true);
|
visible: GetObjectValue(config, 'visible', true),
|
||||||
this.scaleMode = GetObjectValue(config, 'scaleMode', ScaleModes.DEFAULT);
|
scaleMode: GetObjectValue(config, 'scaleMode', ScaleModes.DEFAULT),
|
||||||
this.fps = GetObjectValue(config, 'fps', 60);
|
x: GetObjectValue(config, 'x', 0),
|
||||||
this.x = GetObjectValue(config, 'x', 0);
|
y: GetObjectValue(config, 'y', 0),
|
||||||
this.y = GetObjectValue(config, 'y', 0);
|
|
||||||
|
|
||||||
// -1 means the State Manager will set it to be the Game dimensions
|
// -1 means the State Manager will set it to be the Game dimensions
|
||||||
this.width = GetObjectValue(config, 'width', -1);
|
width: GetObjectValue(config, 'width', -1),
|
||||||
this.height = GetObjectValue(config, 'height', -1);
|
height: GetObjectValue(config, 'height', -1),
|
||||||
|
|
||||||
// Renderer Settings
|
// Renderer Settings
|
||||||
|
|
||||||
this.clearBeforeRender = GetObjectValue(config, 'clearBeforeRender', true);
|
clearBeforeRender: GetObjectValue(config, 'clearBeforeRender', true),
|
||||||
this.transparent = GetObjectValue(config, 'transparent', false);
|
transparent: GetObjectValue(config, 'transparent', false),
|
||||||
this.autoResize = GetObjectValue(config, 'autoResize', false);
|
autoResize: GetObjectValue(config, 'autoResize', false),
|
||||||
this.roundPixels = GetObjectValue(config, 'roundPixels', false);
|
roundPixels: GetObjectValue(config, 'roundPixels', false),
|
||||||
this.drawToPrimaryCanvas = GetObjectValue(config, 'drawToPrimaryCanvas', false);
|
drawToPrimaryCanvas: GetObjectValue(config, 'drawToPrimaryCanvas', false),
|
||||||
|
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Unless we add some actual functions in here, we'll make this just return an Object instead of an instance
|
|
||||||
Settings.prototype.constructor = Settings;
|
|
||||||
|
|
||||||
module.exports = Settings;
|
module.exports = Settings;
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
|
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var Settings = require('./Settings');
|
|
||||||
var Systems = require('./Systems');
|
var Systems = require('./Systems');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -15,39 +14,22 @@ var Systems = require('./Systems');
|
||||||
*/
|
*/
|
||||||
var State = function (config)
|
var State = function (config)
|
||||||
{
|
{
|
||||||
// The properties a State *must* have, that cannot be changed without breaking it:
|
// The State Systems. You must never overwrite this property, or all hell will break lose.
|
||||||
|
|
||||||
this.game = null;
|
|
||||||
|
|
||||||
// Maybe just an object? Doesn't have to instantiate I don't think ...
|
|
||||||
this.settings = new Settings(this, config);
|
|
||||||
|
|
||||||
this.sys = new Systems(this, config);
|
this.sys = new Systems(this, config);
|
||||||
|
|
||||||
// Reference to sys.children, set during sys.init only
|
this.settings = this.sys.settings;
|
||||||
this.children;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
State.prototype.constructor = State;
|
State.prototype.constructor = State;
|
||||||
|
|
||||||
State.prototype = {
|
State.prototype = {
|
||||||
|
|
||||||
// Can be overridden by your own States
|
// Should be overridden by your own States
|
||||||
preUpdate: function ()
|
|
||||||
{
|
|
||||||
},
|
|
||||||
|
|
||||||
// Can be overridden by your own States
|
|
||||||
update: function ()
|
update: function ()
|
||||||
{
|
{
|
||||||
},
|
},
|
||||||
|
|
||||||
// Can be overridden by your own States
|
// Should be overridden by your own States
|
||||||
postUpdate: function ()
|
|
||||||
{
|
|
||||||
},
|
|
||||||
|
|
||||||
// Can be overridden by your own States
|
|
||||||
render: function ()
|
render: function ()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ var State = require('./State');
|
||||||
var Settings = require('./Settings');
|
var Settings = require('./Settings');
|
||||||
var Systems = require('./Systems');
|
var Systems = require('./Systems');
|
||||||
var GetObjectValue = require('../utils/GetObjectValue');
|
var GetObjectValue = require('../utils/GetObjectValue');
|
||||||
// var LoaderEvent = require('../loader/events/');
|
var EventDispatcher = require('../events/EventDispatcher');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The State Manager is responsible for loading, setting up and switching game states.
|
* The State Manager is responsible for loading, setting up and switching game states.
|
||||||
|
@ -72,9 +72,6 @@ StateManager.prototype = {
|
||||||
*/
|
*/
|
||||||
boot: function ()
|
boot: function ()
|
||||||
{
|
{
|
||||||
// this.game.onPause.add(this.pause, this);
|
|
||||||
// this.game.onResume.add(this.resume, this);
|
|
||||||
|
|
||||||
for (var i = 0; i < this._pending.length; i++)
|
for (var i = 0; i < this._pending.length; i++)
|
||||||
{
|
{
|
||||||
var entry = this._pending[i];
|
var entry = this._pending[i];
|
||||||
|
@ -185,11 +182,9 @@ StateManager.prototype = {
|
||||||
|
|
||||||
createStateFromInstance: function (key, newState)
|
createStateFromInstance: function (key, newState)
|
||||||
{
|
{
|
||||||
newState.game = this.game;
|
|
||||||
|
|
||||||
newState.settings.key = key;
|
newState.settings.key = key;
|
||||||
|
|
||||||
newState.sys.init();
|
newState.sys.init(this.game);
|
||||||
|
|
||||||
if (this.game.config.renderType === CONST.WEBGL)
|
if (this.game.config.renderType === CONST.WEBGL)
|
||||||
{
|
{
|
||||||
|
@ -203,9 +198,7 @@ StateManager.prototype = {
|
||||||
{
|
{
|
||||||
var newState = new State(stateConfig);
|
var newState = new State(stateConfig);
|
||||||
|
|
||||||
newState.game = this.game;
|
newState.sys.init(this.game);
|
||||||
|
|
||||||
newState.sys.init();
|
|
||||||
|
|
||||||
if (this.game.config.renderType === CONST.WEBGL)
|
if (this.game.config.renderType === CONST.WEBGL)
|
||||||
{
|
{
|
||||||
|
@ -230,7 +223,7 @@ StateManager.prototype = {
|
||||||
newState.settings = new Settings(newState, key);
|
newState.settings = new Settings(newState, key);
|
||||||
newState.sys = new Systems(newState);
|
newState.sys = new Systems(newState);
|
||||||
|
|
||||||
newState.sys.init();
|
newState.sys.init(this.game);
|
||||||
|
|
||||||
if (this.game.config.renderType === CONST.WEBGL)
|
if (this.game.config.renderType === CONST.WEBGL)
|
||||||
{
|
{
|
||||||
|
@ -253,9 +246,9 @@ StateManager.prototype = {
|
||||||
newState.create = GetObjectValue(stateConfig, 'create', NOOP);
|
newState.create = GetObjectValue(stateConfig, 'create', NOOP);
|
||||||
newState.shutdown = GetObjectValue(stateConfig, 'shutdown', NOOP);
|
newState.shutdown = GetObjectValue(stateConfig, 'shutdown', NOOP);
|
||||||
|
|
||||||
newState.preUpdate = GetObjectValue(stateConfig, 'preUpdate', NOOP);
|
// Game Loop level callbacks
|
||||||
|
|
||||||
newState.update = GetObjectValue(stateConfig, 'update', NOOP);
|
newState.update = GetObjectValue(stateConfig, 'update', NOOP);
|
||||||
newState.postUpdate = GetObjectValue(stateConfig, 'postUpdate', NOOP);
|
|
||||||
newState.render = GetObjectValue(stateConfig, 'render', NOOP);
|
newState.render = GetObjectValue(stateConfig, 'render', NOOP);
|
||||||
|
|
||||||
return newState;
|
return newState;
|
||||||
|
@ -375,7 +368,6 @@ StateManager.prototype = {
|
||||||
// No preload? Then there was nothing to load either
|
// No preload? Then there was nothing to load either
|
||||||
this.startCreate(state);
|
this.startCreate(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -411,8 +403,6 @@ StateManager.prototype = {
|
||||||
this.active.sort(this.sortStates.bind(this));
|
this.active.sort(this.sortStates.bind(this));
|
||||||
|
|
||||||
state.sys.updates.running = true;
|
state.sys.updates.running = true;
|
||||||
|
|
||||||
state.sys.mainloop.start();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
pause: function (key)
|
pause: function (key)
|
||||||
|
@ -446,96 +436,7 @@ StateManager.prototype = {
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
// See if we can reduce this down to just update and render
|
|
||||||
|
|
||||||
// timestamp = DOMHighResTimeStamp
|
|
||||||
step: function (timestamp)
|
|
||||||
{
|
|
||||||
for (var i = 0; i < this.active.length; i++)
|
|
||||||
{
|
|
||||||
var state = this.active[i].state;
|
|
||||||
|
|
||||||
if (state.sys.mainloop.running)
|
|
||||||
{
|
|
||||||
state.sys.mainloop.step(timestamp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/*
|
|
||||||
preUpdate: function ()
|
|
||||||
{
|
|
||||||
for (var i = 0; i < this.active.length; i++)
|
|
||||||
{
|
|
||||||
var state = this.active[i].state;
|
|
||||||
|
|
||||||
for (var c = 0; c < state.sys.children.list.length; c++)
|
|
||||||
{
|
|
||||||
state.sys.children.list[c].preUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
state.preUpdate();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
update: function ()
|
|
||||||
{
|
|
||||||
for (var i = 0; i < this.active.length; i++)
|
|
||||||
{
|
|
||||||
var state = this.active[i].state;
|
|
||||||
|
|
||||||
// Invoke State Main Loop here - updating all of its systems (tweens, physics, etc)
|
|
||||||
|
|
||||||
// This shouldn't be called if the State is still loading
|
|
||||||
// Have a State.STATUS const in the Settings, dictating what is going on
|
|
||||||
|
|
||||||
for (var c = 0; c < state.sys.children.list.length; c++)
|
|
||||||
{
|
|
||||||
var child = state.sys.children.list[c];
|
|
||||||
|
|
||||||
if (child.exists)
|
|
||||||
{
|
|
||||||
child.update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
state.update();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
postUpdate: function ()
|
|
||||||
{
|
|
||||||
for (var i = 0; i < this.active.length; i++)
|
|
||||||
{
|
|
||||||
var state = this.active[i].state;
|
|
||||||
|
|
||||||
for (var c = 0; c < state.sys.children.list.length; c++)
|
|
||||||
{
|
|
||||||
state.sys.children.list[c].postUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
state.postUpdate();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
render: function ()
|
|
||||||
{
|
|
||||||
for (var i = 0; i < this.active.length; i++)
|
|
||||||
{
|
|
||||||
var state = this.active[i].state;
|
|
||||||
|
|
||||||
// Can put all kinds of other checks in here, like MainLoop, FPS, etc.
|
|
||||||
if (!state.settings.visible || state.sys.color.alpha === 0 || state.sys.children.list.length === 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.game.renderer.render(state);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
*/
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -6,34 +6,37 @@
|
||||||
|
|
||||||
var EventDispatcher = require('../events/EventDispatcher');
|
var EventDispatcher = require('../events/EventDispatcher');
|
||||||
var GameObjectFactory = require('./systems/GameObjectFactory');
|
var GameObjectFactory = require('./systems/GameObjectFactory');
|
||||||
// var GameObjectCreator = require('./systems/GameObjectCreator');
|
var GameObjectCreator = require('./systems/GameObjectCreator');
|
||||||
var Loader = require('./systems/Loader');
|
var Loader = require('./systems/Loader');
|
||||||
var MainLoop = require('./systems/MainLoop');
|
|
||||||
var UpdateManager = require('./systems/UpdateManager');
|
var UpdateManager = require('./systems/UpdateManager');
|
||||||
var Component = require('../components');
|
var Component = require('../components');
|
||||||
var Camera = require('../camera/Camera');
|
var Camera = require('../camera/Camera');
|
||||||
|
var Settings = require('./Settings');
|
||||||
|
|
||||||
var Systems = function (state, config)
|
var Systems = function (state, config)
|
||||||
{
|
{
|
||||||
this.state = state;
|
this.state = state;
|
||||||
|
|
||||||
|
this.game = null;
|
||||||
|
|
||||||
this.config = config;
|
this.config = config;
|
||||||
|
|
||||||
this.events;
|
this.settings = Settings(config);
|
||||||
|
|
||||||
// Reference to the global Game level TextureManager.
|
// Reference to the global Game level systems
|
||||||
this.textures;
|
this.textureManager;
|
||||||
|
this.stateManager;
|
||||||
|
|
||||||
// State specific managers (Factory, Tweens, Loader, Physics, etc)
|
// CORE SYSTEMS / PROPERTIES
|
||||||
|
|
||||||
|
// Reference to State specific managers (Factory, Tweens, Loader, Physics, etc)
|
||||||
this.add;
|
this.add;
|
||||||
this.make;
|
this.make;
|
||||||
this.input;
|
|
||||||
this.load;
|
this.load;
|
||||||
this.tweens;
|
this.events;
|
||||||
this.mainloop;
|
|
||||||
this.updates;
|
this.updates;
|
||||||
|
|
||||||
// State specific properties (transform, data, children, etc)
|
// State properties
|
||||||
this.camera;
|
this.camera;
|
||||||
this.children;
|
this.children;
|
||||||
this.color;
|
this.color;
|
||||||
|
@ -47,40 +50,35 @@ Systems.prototype.constructor = Systems;
|
||||||
|
|
||||||
Systems.prototype = {
|
Systems.prototype = {
|
||||||
|
|
||||||
init: function ()
|
init: function (game)
|
||||||
{
|
{
|
||||||
console.log('State.Systems.init');
|
console.log('State.Systems.init');
|
||||||
|
|
||||||
this.textures = this.state.game.textures;
|
this.game = game;
|
||||||
|
|
||||||
// All of the systems can use the State level EventDispatcher, or their own
|
|
||||||
this.events = new EventDispatcher();
|
|
||||||
|
|
||||||
// State specific managers (Factory, Tweens, Loader, Physics, etc)
|
// State specific managers (Factory, Tweens, Loader, Physics, etc)
|
||||||
// All these to be set by a State Config package
|
|
||||||
|
|
||||||
|
this.textures = game.textures;
|
||||||
|
this.events = new EventDispatcher();
|
||||||
this.add = new GameObjectFactory(this.state);
|
this.add = new GameObjectFactory(this.state);
|
||||||
// this.make = GameObjectCreator(this.state);
|
this.make = GameObjectCreator(this.state);
|
||||||
this.mainloop = new MainLoop(this.state, this.state.settings.fps);
|
|
||||||
this.updates = new UpdateManager(this.state);
|
this.updates = new UpdateManager(this.state);
|
||||||
this.load = new Loader(this.state);
|
this.load = new Loader(this.state);
|
||||||
|
|
||||||
// this.tweens = new Phaser.TweenManager(this.state);
|
|
||||||
// this.input = new Phaser.State.Input(this.state);
|
|
||||||
// this.physics = new Phaser.Physics.Arcade(this.state, 800, 600);
|
|
||||||
|
|
||||||
// State specific properties (transform, data, children, etc)
|
// State specific properties (transform, data, children, etc)
|
||||||
|
|
||||||
this.camera = new Camera(this.state, 0, 0, 800, 600);
|
this.camera = new Camera(this.state, 0, 0, 800, 600);
|
||||||
this.children = new Component.Children(this.state);
|
this.children = new Component.Children(this.state);
|
||||||
this.color = new Component.Color(this.state);
|
this.color = new Component.Color(this.state);
|
||||||
this.data = new Component.Data(this.state);
|
this.data = new Component.Data(this.state);
|
||||||
this.transform = this.camera.transform;
|
this.transform = this.camera.transform;
|
||||||
|
|
||||||
// Boot
|
this.inject();
|
||||||
|
},
|
||||||
|
|
||||||
// this.input.init();
|
inject: function ()
|
||||||
|
{
|
||||||
// Defaults
|
// Defaults properties injected into the State
|
||||||
|
|
||||||
this.state.events = this.events;
|
this.state.events = this.events;
|
||||||
this.state.add = this.add;
|
this.state.add = this.add;
|
||||||
|
@ -88,43 +86,47 @@ Systems.prototype = {
|
||||||
this.state.children = this.children;
|
this.state.children = this.children;
|
||||||
this.state.color = this.color;
|
this.state.color = this.color;
|
||||||
this.state.data = this.data;
|
this.state.data = this.data;
|
||||||
|
this.state.state = this.game.state; // StateManager
|
||||||
|
|
||||||
this.state.camera = this.camera;
|
this.state.camera = this.camera;
|
||||||
this.state.transform = this.camera.transform;
|
this.state.transform = this.camera.transform;
|
||||||
this.state.textures = this.textures;
|
this.state.textures = this.textures;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// this.state.input = this.input;
|
|
||||||
// this.state.state = this.state.game.state;
|
|
||||||
|
|
||||||
// Here we can check which Systems to install as properties into the State object
|
|
||||||
// (default systems always exist in here, regardless)
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Called just once per frame, regardless of speed
|
||||||
begin: function (timestamp, frameDelta)
|
begin: function (timestamp, frameDelta)
|
||||||
{
|
{
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Potentially called multiple times per frame (on super-fast systems)
|
||||||
update: function (timestep, physicsStep)
|
update: function (timestep, physicsStep)
|
||||||
{
|
{
|
||||||
},
|
for (var c = 0; c < this.children.list.length; c++)
|
||||||
|
|
||||||
preRender: function ()
|
|
||||||
{
|
|
||||||
},
|
|
||||||
|
|
||||||
end: function (fps, panic)
|
|
||||||
{
|
|
||||||
if (panic)
|
|
||||||
{
|
{
|
||||||
// This pattern introduces non-deterministic behavior, but in this case
|
var child = this.children.list[c];
|
||||||
// it's better than the alternative (the application would look like it
|
|
||||||
// was running very quickly until the simulation caught up to real
|
|
||||||
// time).
|
|
||||||
var discardedTime = Math.round(this.mainloop.resetFrameDelta());
|
|
||||||
|
|
||||||
console.warn('Main loop panicked, probably because the browser tab was put in the background. Discarding ' + discardedTime + 'ms');
|
if (child.exists)
|
||||||
|
{
|
||||||
|
child.update(timestep);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.state.update(timestep, physicsStep);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Called just once per frame, regardless of speed
|
||||||
|
render: function (interpolationPercentage, renderer)
|
||||||
|
{
|
||||||
|
this.updates.start();
|
||||||
|
|
||||||
|
if (this.settings.visible && this.color.alpha !== 0)
|
||||||
|
{
|
||||||
|
renderer.render(this.state, interpolationPercentage);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updates.stop();
|
||||||
|
|
||||||
|
this.state.render(interpolationPercentage);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -26,15 +26,10 @@ var GameObjectCreator = {
|
||||||
|
|
||||||
function init (state)
|
function init (state)
|
||||||
{
|
{
|
||||||
console.log('Creating GameObjectCreator instance for State', state);
|
|
||||||
|
|
||||||
GameObjectCreator.state = state;
|
GameObjectCreator.state = state;
|
||||||
|
|
||||||
// Load the factories into this Object
|
// Load the factories into this Object
|
||||||
|
return FactoryContainer.load(GameObjectCreator, false);
|
||||||
FactoryContainer.load(GameObjectCreator, false);
|
|
||||||
|
|
||||||
return GameObjectCreator;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = init;
|
module.exports = init;
|
||||||
|
|
|
@ -26,15 +26,10 @@ var GameObjectFactory = {
|
||||||
|
|
||||||
function init (state)
|
function init (state)
|
||||||
{
|
{
|
||||||
console.log('Creating GameObjectFactory instance for State');
|
|
||||||
|
|
||||||
GameObjectFactory.state = state;
|
GameObjectFactory.state = state;
|
||||||
|
|
||||||
// Load the factories into this Object
|
// Load the factories into this Object
|
||||||
|
|
||||||
return FactoryContainer.load(GameObjectFactory, true);
|
return FactoryContainer.load(GameObjectFactory, true);
|
||||||
|
|
||||||
// return GameObjectFactory;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = init;
|
module.exports = init;
|
||||||
|
|
|
@ -1,251 +0,0 @@
|
||||||
/**
|
|
||||||
* @author Richard Davey <rich@photonstorm.com>
|
|
||||||
* @copyright 2016 Photon Storm Ltd.
|
|
||||||
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// My thanks to Isaac Sukin for creating MainLoop.js, on which lots of this is based.
|
|
||||||
|
|
||||||
var MainLoop = function (state, framerate)
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @property {Phaser.State} state
|
|
||||||
*/
|
|
||||||
this.state = state;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @property {Phaser.Game} game - A reference to the currently running Game.
|
|
||||||
*/
|
|
||||||
this.game = state.game;
|
|
||||||
|
|
||||||
// The amount of time (in milliseconds) to simulate each time update() runs.
|
|
||||||
this.timestep = 1000 / framerate;
|
|
||||||
|
|
||||||
this.physicsStep = 1 / framerate;
|
|
||||||
|
|
||||||
// The cumulative amount of in-app time that hasn't been simulated yet.
|
|
||||||
// See the comments inside animate() for details.
|
|
||||||
this.frameDelta = 0;
|
|
||||||
|
|
||||||
// The timestamp in milliseconds of the last time the main loop was run.
|
|
||||||
// Used to compute the time elapsed between frames.
|
|
||||||
this.lastFrameTimeMs = 0;
|
|
||||||
|
|
||||||
// An exponential moving average of the frames per second.
|
|
||||||
this.fps = 60;
|
|
||||||
|
|
||||||
// The timestamp (in milliseconds) of the last time the `fps` moving
|
|
||||||
// average was updated.
|
|
||||||
this.lastFpsUpdate = 0;
|
|
||||||
|
|
||||||
// The number of frames delivered in the current second.
|
|
||||||
this.framesThisSecond = 0;
|
|
||||||
|
|
||||||
// The number of times update() is called in a given frame. This is only
|
|
||||||
// relevant inside of animate(), but a reference is held externally so that
|
|
||||||
// this variable is not marked for garbage collection every time the main
|
|
||||||
// loop runs.
|
|
||||||
this.numUpdateSteps = 0;
|
|
||||||
|
|
||||||
// The minimum amount of time in milliseconds that must pass since the last
|
|
||||||
// frame was executed before another frame can be executed. The
|
|
||||||
// multiplicative inverse caps the FPS (the default of zero means there is
|
|
||||||
// no cap).
|
|
||||||
this.minFrameDelay = 0;
|
|
||||||
|
|
||||||
// Whether the main loop is running.
|
|
||||||
this.running = false;
|
|
||||||
|
|
||||||
// `true` if `MainLoop.start()` has been called and the most recent time it
|
|
||||||
// was called has not been followed by a call to `MainLoop.stop()`. This is
|
|
||||||
// different than `running` because there is a delay of a few milliseconds
|
|
||||||
// after `MainLoop.start()` is called before the application is considered
|
|
||||||
// "running." This delay is due to waiting for the next frame.
|
|
||||||
this.started = false;
|
|
||||||
|
|
||||||
// Whether the simulation has fallen too far behind real time.
|
|
||||||
// Specifically, `panic` will be set to `true` if too many updates occur in
|
|
||||||
// one frame. This is only relevant inside of animate(), but a reference is
|
|
||||||
// held externally so that this variable is not marked for garbage
|
|
||||||
// collection every time the main loop runs.
|
|
||||||
this.panic = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
MainLoop.prototype.constructor = MainLoop;
|
|
||||||
|
|
||||||
MainLoop.prototype = {
|
|
||||||
|
|
||||||
setMaxFPS: function (fps)
|
|
||||||
{
|
|
||||||
if (fps === 0)
|
|
||||||
{
|
|
||||||
this.stop();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.minFrameDelay = 1000 / fps;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
getMaxFPS: function ()
|
|
||||||
{
|
|
||||||
return 1000 / this.minFrameDelay;
|
|
||||||
},
|
|
||||||
|
|
||||||
resetFrameDelta: function ()
|
|
||||||
{
|
|
||||||
var oldFrameDelta = this.frameDelta;
|
|
||||||
|
|
||||||
this.frameDelta = 0;
|
|
||||||
|
|
||||||
return oldFrameDelta;
|
|
||||||
},
|
|
||||||
|
|
||||||
start: function ()
|
|
||||||
{
|
|
||||||
if (this.started)
|
|
||||||
{
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.started = true;
|
|
||||||
this.running = true;
|
|
||||||
|
|
||||||
this.lastFrameTimeMs = window.performance.now();
|
|
||||||
this.lastFpsUpdate = window.performance.now();
|
|
||||||
this.framesThisSecond = 0;
|
|
||||||
},
|
|
||||||
|
|
||||||
// timestamp = DOMHighResTimeStamp
|
|
||||||
step: function (timestamp)
|
|
||||||
{
|
|
||||||
// Throttle the frame rate (if minFrameDelay is set to a non-zero value by
|
|
||||||
// `MainLoop.setMaxAllowedFPS()`).
|
|
||||||
if (timestamp < this.lastFrameTimeMs + this.minFrameDelay)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// frameDelta is the cumulative amount of in-app time that hasn't been
|
|
||||||
// simulated yet. Add the time since the last frame. We need to track total
|
|
||||||
// not-yet-simulated time (as opposed to just the time elapsed since the
|
|
||||||
// last frame) because not all actually elapsed time is guaranteed to be
|
|
||||||
// simulated each frame. See the comments below for details.
|
|
||||||
this.frameDelta += timestamp - this.lastFrameTimeMs;
|
|
||||||
this.lastFrameTimeMs = timestamp;
|
|
||||||
|
|
||||||
// Run any updates that are not dependent on time in the simulation.
|
|
||||||
|
|
||||||
// Here we'll need to run things like tween.update, input.update, etc.
|
|
||||||
this.state.sys.begin(timestamp, this.frameDelta);
|
|
||||||
|
|
||||||
// Update the estimate of the frame rate, `fps`. Every second, the number
|
|
||||||
// of frames that occurred in that second are included in an exponential
|
|
||||||
// moving average of all frames per second, with an alpha of 0.25. This
|
|
||||||
// means that more recent seconds affect the estimated frame rate more than
|
|
||||||
// older seconds.
|
|
||||||
if (timestamp > this.lastFpsUpdate + 1000)
|
|
||||||
{
|
|
||||||
// Compute the new exponential moving average with an alpha of 0.25.
|
|
||||||
// Using constants inline is okay here.
|
|
||||||
this.fps = 0.25 * this.framesThisSecond + 0.75 * this.fps;
|
|
||||||
|
|
||||||
this.lastFpsUpdate = timestamp;
|
|
||||||
this.framesThisSecond = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.framesThisSecond++;
|
|
||||||
|
|
||||||
this.numUpdateSteps = 0;
|
|
||||||
|
|
||||||
var step = this.timestep;
|
|
||||||
|
|
||||||
while (this.frameDelta >= step)
|
|
||||||
{
|
|
||||||
// this.update(this.timestep);
|
|
||||||
|
|
||||||
this.state.sys.update(step, this.physicsStep);
|
|
||||||
|
|
||||||
for (var c = 0; c < this.state.sys.children.list.length; c++)
|
|
||||||
{
|
|
||||||
var child = this.state.sys.children.list[c];
|
|
||||||
|
|
||||||
if (child.exists)
|
|
||||||
{
|
|
||||||
child.update(step);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dev level callback
|
|
||||||
this.state.update(step);
|
|
||||||
|
|
||||||
this.frameDelta -= this.timestep;
|
|
||||||
|
|
||||||
if (++this.numUpdateSteps >= 240)
|
|
||||||
{
|
|
||||||
this.panic = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.state.sys.preRender();
|
|
||||||
|
|
||||||
this.state.sys.updates.start();
|
|
||||||
|
|
||||||
if (this.state.settings.visible && this.state.sys.color.alpha !== 0)
|
|
||||||
{
|
|
||||||
this.game.renderer.render(this.state, this.frameDelta / this.timestep);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.state.sys.updates.stop();
|
|
||||||
|
|
||||||
// Run any updates that are not dependent on time in the simulation.
|
|
||||||
this.state.sys.end(this.fps, this.panic);
|
|
||||||
|
|
||||||
this.panic = false;
|
|
||||||
},
|
|
||||||
|
|
||||||
/*
|
|
||||||
update: function (timestep)
|
|
||||||
{
|
|
||||||
this.state.sys.update(timestep);
|
|
||||||
|
|
||||||
var c;
|
|
||||||
var child;
|
|
||||||
|
|
||||||
for (var c = 0; c < this.state.sys.children.list.length; c++)
|
|
||||||
{
|
|
||||||
var child = this.state.sys.children.list[c];
|
|
||||||
|
|
||||||
if (child.exists)
|
|
||||||
{
|
|
||||||
child.update(timestep);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dev level callback
|
|
||||||
this.state.update(timestep);
|
|
||||||
|
|
||||||
for (c = 0; c < this.state.sys.children.list.length; c++)
|
|
||||||
{
|
|
||||||
var child = this.state.sys.children.list[c];
|
|
||||||
|
|
||||||
if (child.exists)
|
|
||||||
{
|
|
||||||
child.update(timestep);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
*/
|
|
||||||
|
|
||||||
stop: function ()
|
|
||||||
{
|
|
||||||
this.running = false;
|
|
||||||
this.started = false;
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = MainLoop;
|
|
|
@ -13,8 +13,6 @@ var UpdateManager = function (state)
|
||||||
{
|
{
|
||||||
this.state = state;
|
this.state = state;
|
||||||
|
|
||||||
this.game = state.game;
|
|
||||||
|
|
||||||
this.list = [];
|
this.list = [];
|
||||||
|
|
||||||
// this.i = 1;
|
// this.i = 1;
|
||||||
|
|
Loading…
Reference in a new issue