Skip to content

Commit 196eda3

Browse files
committed
[#1091] further code revamping/reshuffling to enable instantiable game Application
1 parent 5edbadc commit 196eda3

File tree

6 files changed

+169
-184
lines changed

6 files changed

+169
-184
lines changed

src/application/application.js

+20-13
Original file line numberDiff line numberDiff line change
@@ -12,25 +12,29 @@ import World from "./../physics/world.js";
1212
*/
1313
export default class Application {
1414
constructor() {
15+
16+
/**
17+
* the parent HTML element holding the main canvas of this application
18+
* @type {HTMLElement}
19+
*/
20+
this.parentElement = undefined;
21+
1522
/**
16-
* a reference to the current active stage "default" camera
17-
* @public
23+
* the active stage "default" camera
1824
* @type {Camera2d}
1925
*/
2026
this.viewport = undefined;
2127

2228
/**
2329
* a reference to the game world, <br>
2430
* a world is a virtual environment containing all the game objects
25-
* @public
2631
* @type {World}
2732
*/
2833
this.world = undefined;
2934

3035
/**
3136
* when true, all objects will be added under the root world container.<br>
3237
* When false, a `me.Container` object will be created for each corresponding groups
33-
* @public
3438
* @type {boolean}
3539
* @default true
3640
*/
@@ -39,7 +43,6 @@ import World from "./../physics/world.js";
3943
/**
4044
* Specify the property to be used when sorting renderables.
4145
* Accepted values : "x", "y", "z"
42-
* @public
4346
* @type {string}
4447
* @default "z"
4548
*/
@@ -50,13 +53,17 @@ import World from "./../physics/world.js";
5053
* Use this value to implement frame prediction in drawing events,
5154
* for creating smooth motion while running game update logic at
5255
* a lower fps.
53-
* @public
5456
* @type {DOMHighResTimeStamp}
55-
* @name lastUpdate
56-
* @memberof Application
5757
*/
5858
this.lastUpdate = 0;
5959

60+
/**
61+
* true when this app instance has been initialized
62+
* @type {boolean}
63+
* @default false
64+
*/
65+
this.isInitialized = false;
66+
6067
// to know when we have to refresh the display
6168
this.isDirty = true;
6269

@@ -89,6 +96,7 @@ import World from "./../physics/world.js";
8996
// set the reference to this application instance
9097
this.world.app = this;
9198
this.lastUpdate = globalThis.performance.now();
99+
this.isInitialized = true;
92100
event.emit(event.GAME_INIT, this);
93101
}
94102

@@ -140,12 +148,11 @@ import World from "./../physics/world.js";
140148
}
141149

142150
/**
143-
* Returns the parent container of the specified Child in the game world
144-
* @param {Renderable} child
145-
* @returns {Container}
151+
* Returns the parent HTML Element holding the main canvas of this application
152+
* @returns {HTMLElement}
146153
*/
147-
getParentContainer(child) {
148-
return child.ancestor;
154+
getParentElement() {
155+
return this.parentElement;
149156
}
150157

151158
/**

src/input/pointerevent.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {preventDefault} from "./input.js";
22
import {getBindingKey, triggerKeyEvent} from "./keyboard.js";
3-
import { renderer, scaleRatio, getParent } from "./../video/video.js";
3+
import { renderer } from "./../video/video.js";
44
import { throttle } from "./../utils/function.js";
55
import { remove } from "./../utils/array.js";
66
import * as event from "./../system/event.js";
@@ -195,7 +195,7 @@ function enablePointerEvent() {
195195
if (device.hasPointerLockSupport) {
196196
document.addEventListener("pointerlockchange", () => {
197197
// change the locked status accordingly
198-
locked = document.pointerLockElement === getParent();
198+
locked = document.pointerLockElement === game.getParentElement();
199199
// emit the corresponding internal event
200200
event.emit(event.POINTERLOCKCHANGE, locked);
201201
}, true);
@@ -560,7 +560,7 @@ export function globalToLocal(x, y, v) {
560560
var pixelRatio = globalThis.devicePixelRatio || 1;
561561
x -= rect.left + (globalThis.pageXOffset || 0);
562562
y -= rect.top + (globalThis.pageYOffset || 0);
563-
var scale = scaleRatio;
563+
var scale = renderer.scaleRatio;
564564
if (scale.x !== 1.0 || scale.y !== 1.0) {
565565
x /= scale.x;
566566
y /= scale.y;
@@ -786,7 +786,7 @@ export function releaseAllPointerEvents(region) {
786786
*/
787787
export function requestPointerLock() {
788788
if (device.hasPointerLockSupport) {
789-
var element = getParent();
789+
var element = game.getParentElement();
790790
element.requestPointerLock();
791791
return true;
792792
}

src/system/device.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ export function isFullscreen() {
473473
* @function requestFullscreen
474474
* @memberof device
475475
* @public
476-
* @param {object} [element=default canvas object] - the element to be set in full-screen mode.
476+
* @param {Element} [element] - the element to be set in full-screen mode.
477477
* @example
478478
* // add a keyboard shortcut to toggle Fullscreen mode on/off
479479
* me.input.bindKey(me.input.KEY.F, "toggleFullscreen");

src/video/renderer.js

+20-7
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import Color from "./../math/color.js";
22
import Matrix3d from "./../math/matrix3.js";
3-
import { createCanvas, renderer } from "./video.js";
3+
import { createCanvas } from "./video.js";
44
import * as event from "./../system/event.js";
5-
import * as device from "./../system/device.js";
5+
import { platform } from "../system/device.js";
66
import { setPrefixed } from "./../utils/agent.js";
77
import Rect from "./../geometries/rectangle.js";
88
import RoundRect from "./../geometries/roundrect.js";
@@ -11,6 +11,7 @@ import Polygon from "./../geometries/poly.js";
1111
import Line from "./../geometries/line.js";
1212
import Bounds from "./../physics/bounds.js";
1313
import Path2D from "./../geometries/path2d.js";
14+
import Vector2d from "../math/vector2.js";
1415
import Point from "../geometries/point.js";
1516

1617
/**
@@ -41,6 +42,20 @@ import Point from "../geometries/point.js";
4142
*/
4243
this.settings = options;
4344

45+
/**
46+
* the requested video size ratio
47+
* @public
48+
* @type {Number}
49+
*/
50+
this.designRatio = this.settings.width / this.settings.height;
51+
52+
/**
53+
* the scaling ratio to be applied to the main canvas
54+
* @type {Vector2d}
55+
* @default <1,1>
56+
*/
57+
this.scaleRatio = new Vector2d(this.settings.scale, this.settings.scale);
58+
4459
/**
4560
* true if the current rendering context is valid
4661
* @default true
@@ -70,7 +85,7 @@ import Point from "../geometries/point.js";
7085
this.currentBlendMode = "none";
7186

7287
// create the main screen canvas
73-
if (device.platform.ejecta === true) {
88+
if (platform.ejecta === true) {
7489
// a main canvas is already automatically created by Ejecta
7590
this.canvas = document.getElementById("canvas");
7691
} else if (typeof globalThis.canvas !== "undefined") {
@@ -94,9 +109,9 @@ import Point from "../geometries/point.js";
94109
// default uvOffset
95110
this.uvOffset = 0;
96111

97-
// reset the instantiated renderer on game reset
112+
// reset the renderer on game reset
98113
event.on(event.GAME_RESET, () => {
99-
renderer.reset();
114+
this.reset();
100115
});
101116
}
102117

@@ -323,8 +338,6 @@ import Point from "../geometries/point.js";
323338

324339
/**
325340
* fill the given shape
326-
* @name fill
327-
* @memberof Renderer
328341
* @param {Rect|RoundRect|Polygon|Line|Ellipse} shape - a shape object to fill
329342
*/
330343
fill(shape) {

src/video/utils/resize.js

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import * as device from "./../../system/device.js";
2+
import game from "./../../game.js";
3+
4+
/**
5+
* scale the "displayed" canvas by the given scalar.
6+
* this will modify the size of canvas element directly.
7+
* Only use this if you are not using the automatic scaling feature.
8+
* @param {number} x - x scaling multiplier
9+
* @param {number} y - y scaling multiplier
10+
*/
11+
function scale(renderer, x, y) {
12+
var canvas = renderer.getCanvas();
13+
var context = renderer.getContext();
14+
var settings = renderer.settings;
15+
var pixelRatio = device.devicePixelRatio;
16+
17+
var w = settings.zoomX = canvas.width * x * pixelRatio;
18+
var h = settings.zoomY = canvas.height * y * pixelRatio;
19+
20+
// update the global scale variable
21+
renderer.scaleRatio.set(x * pixelRatio, y * pixelRatio);
22+
23+
// adjust CSS style based on device pixel ratio
24+
canvas.style.width = (w / pixelRatio) + "px";
25+
canvas.style.height = (h / pixelRatio) + "px";
26+
27+
// if anti-alias and blend mode were resetted (e.g. Canvas mode)
28+
renderer.setAntiAlias(context, settings.antiAlias);
29+
renderer.setBlendMode(settings.blendMode, context);
30+
31+
// force repaint
32+
game.repaint();
33+
}
34+
35+
/**
36+
* callback for window resize event
37+
*/
38+
export function onresize(renderer) {
39+
var settings = renderer.settings;
40+
var scaleX = 1, scaleY = 1;
41+
42+
if (settings.autoScale) {
43+
44+
// set max the canvas max size if CSS values are defined
45+
var canvasMaxWidth = Infinity;
46+
var canvasMaxHeight = Infinity;
47+
48+
if (globalThis.getComputedStyle) {
49+
var style = globalThis.getComputedStyle(renderer.getCanvas(), null);
50+
canvasMaxWidth = parseInt(style.maxWidth, 10) || Infinity;
51+
canvasMaxHeight = parseInt(style.maxHeight, 10) || Infinity;
52+
}
53+
54+
// get the maximum canvas size within the parent div containing the canvas container
55+
var nodeBounds = device.getParentBounds(game.getParentElement());
56+
57+
var _max_width = Math.min(canvasMaxWidth, nodeBounds.width);
58+
var _max_height = Math.min(canvasMaxHeight, nodeBounds.height);
59+
60+
// calculate final canvas width & height
61+
var screenRatio = _max_width / _max_height;
62+
63+
if ((settings.scaleMethod === "fill-min" && screenRatio > renderer.designRatio) ||
64+
(settings.scaleMethod === "fill-max" && screenRatio < renderer.designRatio) ||
65+
(settings.scaleMethod === "flex-width")
66+
) {
67+
// resize the display canvas to fill the parent container
68+
var sWidth = Math.min(canvasMaxWidth, settings.height * screenRatio);
69+
scaleX = scaleY = _max_width / sWidth;
70+
renderer.resize(Math.floor(sWidth), settings.height);
71+
}
72+
else if ((settings.scaleMethod === "fill-min" && screenRatio < renderer.designRatio) ||
73+
(settings.scaleMethod === "fill-max" && screenRatio > renderer.designRatio) ||
74+
(settings.scaleMethod === "flex-height")
75+
) {
76+
// resize the display canvas to fill the parent container
77+
var sHeight = Math.min(canvasMaxHeight, settings.width * (_max_height / _max_width));
78+
scaleX = scaleY = _max_height / sHeight;
79+
renderer.resize(settings.width, Math.floor(sHeight));
80+
}
81+
else if (settings.scaleMethod === "flex") {
82+
// resize the display canvas to fill the parent container
83+
renderer.resize(Math.floor(_max_width), Math.floor(_max_height));
84+
}
85+
else if (settings.scaleMethod === "stretch") {
86+
// scale the display canvas to fit with the parent container
87+
scaleX = _max_width / settings.width;
88+
scaleY = _max_height / settings.height;
89+
}
90+
else {
91+
// scale the display canvas to fit the parent container
92+
// make sure we maintain the original aspect ratio
93+
if (screenRatio < renderer.designRatio) {
94+
scaleX = scaleY = _max_width / settings.width;
95+
}
96+
else {
97+
scaleX = scaleY = _max_height / settings.height;
98+
}
99+
}
100+
101+
// adjust scaling ratio based on the new scaling ratio
102+
scale(renderer, scaleX, scaleY);
103+
} else {
104+
// adjust scaling ratio based on the given settings
105+
scale(renderer, settings.scale, settings.scale);
106+
}
107+
}

0 commit comments

Comments
 (0)