From 25137b90e31d7c42ddeb7657a6c8ed0b872cbd06 Mon Sep 17 00:00:00 2001 From: Olivier Biot Date: Sun, 26 Mar 2023 08:29:49 +0800 Subject: [PATCH] [#1091] remove more internal references to me.game - the `sortOn` property is now a proper getter/setter for the App World instance `sortOn` property - Container now defines a `getRootAncestor()` method that will return the reference to the root container parent (aka world container) - remove more internal reference to me.game in Container and Trigger --- CHANGELOG.md | 4 +++ src/application/application.js | 23 +++++++----- src/renderable/container.js | 66 +++++++++++++++++++++------------- src/renderable/trigger.js | 12 ++++--- 4 files changed, 67 insertions(+), 38 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 14b352a7cb..43c862b0b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ ### Added - Renderer: add new `toBlob()`, `toDataURL()` and `toImageBitmap()` methods to `CanvasTexture` - Renderer: add new `toBlob()`, `toDataURL()` and `toImageBitmap()` methods to the all Renderers +- Container: new `getRootAncestor()` method that returns the root container's parent (aka World Container) + +### Changed +- Application: the `sortOn` property is now a proper getter/setter for the App World instance `sortOn` property ### Fixed - Renderer: add missing export for the `CanvasTexture` class diff --git a/src/application/application.js b/src/application/application.js index 989cafd526..e90d9b94b1 100644 --- a/src/application/application.js +++ b/src/application/application.js @@ -72,14 +72,6 @@ import { CANVAS, WEBGL, AUTO } from "../const.js"; */ this.mergeGroup = true; - /** - * Specify the property to be used when sorting renderables. - * Accepted values : "x", "y", "z" - * @type {string} - * @default "z" - */ - this.sortOn = "z"; - /** * Last time the game update loop was executed.
* Use this value to implement frame prediction in drawing events, @@ -221,7 +213,7 @@ import { CANVAS, WEBGL, AUTO } from "../const.js"; } // create a new physic world - this.world = new World(); + this.world = new World(0, 0, this.settings.width, this.settings.height); // set the reference to this application instance this.world.app = this; this.lastUpdate = globalThis.performance.now(); @@ -249,6 +241,19 @@ import { CANVAS, WEBGL, AUTO } from "../const.js"; this.updateFrameRate(); } + /** + * Specify the property to be used when sorting renderables for this application game world. + * Accepted values : "x", "y", "z" + * @type {string} + * @see World.sortOn + */ + get sortOn() { + return this.world.sortOn; + } + set sortOn(value) { + this.world.sortOn = value; + } + /** * Fired when a level is fully loaded and all renderable instantiated.
* Additionnaly the level id will also be passed to the called function. diff --git a/src/renderable/container.js b/src/renderable/container.js index 3d71c0eddb..09fb547827 100644 --- a/src/renderable/container.js +++ b/src/renderable/container.js @@ -57,12 +57,12 @@ let globalFloatingCounter = 0; this.children = undefined; /** - * The property of the child object that should be used to sort on
+ * The property of the child object that should be used to sort on this container * value : "x", "y", "z" * @type {string} - * @default me.game.sortOn + * @default "z" */ - this.sortOn = game.sortOn; + this.sortOn = "z"; /** * Specify if the children list should be automatically sorted when adding a new child @@ -170,9 +170,9 @@ let globalFloatingCounter = 0; * Add a child to the container
* if auto-sort is disable, the object will be appended at the bottom of the list. * Adding a child to the container will automatically remove it from its other container. - * Meaning a child can only have one parent. This is important if you add a renderable - * to a container then add it to the me.game.world container it will move it out of the - * orginal container. Then when the me.game.world.reset() is called the renderable + * Meaning a child can only have one parent. This is important if you add a renderable + * to a container then add it to the World container it will move it out of the + * orginal container. Then when the World container reset() method is called the renderable * will not be in any container.
* if the given child implements a onActivateEvent method, that method will be called * once the child is added to this container. @@ -219,7 +219,7 @@ let globalFloatingCounter = 0; // force repaint in case this is a static non-animated object if (this.isAttachedToRoot() === true) { - game.repaint(); + this.isDirty = true; } // force bounds update if required @@ -229,7 +229,7 @@ let globalFloatingCounter = 0; // if a physic body is defined, add it to the game world if (child.body instanceof Body) { - game.world.addBody(child.body); + this.getRootAncestor().addBody(child.body); } // triggered callback if defined @@ -268,7 +268,7 @@ let globalFloatingCounter = 0; // force repaint in case this is a static non-animated object if (this.isAttachedToRoot() === true) { - game.repaint(); + this.isDirty = true; } // force bounds update if required @@ -278,7 +278,7 @@ let globalFloatingCounter = 0; // if a physic body is defined, add it to the game world if (child.body instanceof Body) { - game.world.addBody(child.body); + this.getRootAncestor().addBody(child.body); } // triggered callback if defined @@ -300,14 +300,14 @@ let globalFloatingCounter = 0; * @param {Function} callback - fnction to execute on each element * @param {object} [thisArg] - value to use as this(i.e reference Object) when executing callback. * @example - * // iterate through all children of the root container - * me.game.world.forEach((child) => { + * // iterate through all children of this container + * container.forEach((child) => { * // do something with the child * child.doSomething(); * }); - * me.game.world.forEach((child, index) => { ... }); - * me.game.world.forEach((child, index, array) => { ... }); - * me.game.world.forEach((child, index, array) => { ... }, thisArg); + * container.forEach((child, index) => { ... }); + * container.forEach((child, index, array) => { ... }); + * container.forEach((child, index, array) => { ... }, thisArg); */ forEach(callback, thisArg) { var context = this, i = 0; @@ -411,15 +411,15 @@ let globalFloatingCounter = 0; * var ent = myContainer.getChildByProp("name", "mainPlayer"); * * // or query the whole world : - * var ent = me.game.world.getChildByProp("name", "mainPlayer"); + * var ent = container.getChildByProp("name", "mainPlayer"); * * // partial property matches are also allowed by using a RegExp. * // the following matches "redCOIN", "bluecoin", "bagOfCoins", etc : - * var allCoins = me.game.world.getChildByProp("name", /coin/i); + * var allCoins = container.getChildByProp("name", /coin/i); * * // searching for numbers or other data types : - * var zIndex10 = me.game.world.getChildByProp("z", 10); - * var inViewport = me.game.world.getChildByProp("inViewport", true); + * var zIndex10 = container.getChildByProp("z", 10); + * var inViewport = container.getChildByProp("inViewport", true); */ getChildByProp(prop, value) { var objList = []; @@ -531,7 +531,6 @@ let globalFloatingCounter = 0; /** * Checks if this container is root or if it's attached to the root container. - * @private * @returns {boolean} */ isAttachedToRoot() { @@ -549,6 +548,25 @@ let globalFloatingCounter = 0; } } + /** + * Returns the instance of the root container (i.e. the current application World container). + * @returns {Container} + */ + getRootAncestor() { + if (this.root === true) { + return this; + } else { + var ancestor = this.ancestor; + while (ancestor) { + if (ancestor.root === true) { + break; + } + ancestor = ancestor.ancestor; + } + return ancestor; + } + } + /** * update the cointainer's bounding rect (private) * @ignore @@ -610,7 +628,7 @@ let globalFloatingCounter = 0; // remove the body first to avoid a condition where a body can be detached // from its parent, before the body is removed from the game world if (child.body instanceof Body) { - game.world.removeBody(child.body); + this.getRootAncestor().removeBody(child.body); } if (!keepalive) { @@ -633,7 +651,7 @@ let globalFloatingCounter = 0; // force repaint in case this is a static non-animated object if (this.isAttachedToRoot() === true) { - game.repaint(); + this.isDirty = true; } // force bounds update if required @@ -746,7 +764,7 @@ let globalFloatingCounter = 0; // clear the defer id this.pendingSort = null; // make sure we redraw everything - game.repaint(); + this.isDirty = true; }, this); } } @@ -815,7 +833,7 @@ let globalFloatingCounter = 0; /** * container update function.
- * automatically called by the game manager {@link game} + * automatically called by the application update loop {@link Application} * @protected * @param {number} dt - time since the last update in milliseconds. * @returns {boolean} true if the Container is dirty diff --git a/src/renderable/trigger.js b/src/renderable/trigger.js index 44d94c2c84..0d6a68d106 100644 --- a/src/renderable/trigger.js +++ b/src/renderable/trigger.js @@ -2,7 +2,6 @@ import Renderable from "./renderable.js"; import collision from "./../physics/collision.js"; import Body from "./../physics/body.js"; import level from "./../level/level.js"; -import { game } from "../index.js"; import pool from "./../system/pooling.js"; /** @@ -26,7 +25,7 @@ import pool from "./../system/pooling.js"; * @param {boolean} [settings.flatten] - Flatten all objects into the target container. See {@link level.load} * @param {boolean} [settings.setViewportBounds] - Resize the viewport to match the level. See {@link level.load} * @example - * me.game.world.addChild(new me.Trigger( + * world.addChild(new me.Trigger( * x, y, { * shapes: [new me.Rect(0, 0, 100, 100)], * "duration" : 250, @@ -87,9 +86,10 @@ import pool from "./../system/pooling.js"; * @ignore */ getTriggerSettings() { + var world = this.ancestor.getRootAncestor(); // Lookup for the container instance if (typeof(this.triggerSettings.container) === "string") { - this.triggerSettings.container = game.world.getChildByName(this.triggerSettings.container)[0]; + this.triggerSettings.container = world.getChildByName(this.triggerSettings.container)[0]; } return this.triggerSettings; } @@ -98,8 +98,9 @@ import pool from "./../system/pooling.js"; * @ignore */ onFadeComplete() { + var world = this.ancestor.getRootAncestor(); level.load(this.gotolevel, this.getTriggerSettings()); - game.viewport.fadeOut(this.fade, this.duration); + world.app.viewport.fadeOut(this.fade, this.duration); } /** @@ -110,6 +111,7 @@ import pool from "./../system/pooling.js"; */ triggerEvent() { var triggerSettings = this.getTriggerSettings(); + var world = this.ancestor.getRootAncestor(); if (triggerSettings.event === "level") { this.gotolevel = triggerSettings.to; @@ -118,7 +120,7 @@ import pool from "./../system/pooling.js"; if (this.fade && this.duration) { if (!this.fading) { this.fading = true; - game.viewport.fadeIn(this.fade, this.duration, + world.app.viewport.fadeIn(this.fade, this.duration, this.onFadeComplete.bind(this)); } } else {