@phaser-plus/perspective2d
Version:
Create games with a linearly transformed projection
434 lines (407 loc) • 14.1 kB
JavaScript
var $8z0rK$phaserpluscore = require("@phaser-plus/core");
var $8z0rK$phaser = require("phaser");
var $8z0rK$toolcasebase = require("@toolcase/base");
function $parcel$export(e, n, v, s) {
Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});
}
$parcel$export(module.exports, "Scene2D", () => $09ff86e408181510$export$2e2bcd8739ae039);
$parcel$export(module.exports, "World", () => $c40a4235a9c7b704$export$2e2bcd8739ae039);
$parcel$export(module.exports, "GameObject2D", () => $a7db11b8d6c6181c$export$2e2bcd8739ae039);
$parcel$export(module.exports, "Grid", () => $16fdcf60a0c7b80c$export$2e2bcd8739ae039);
class $a7db11b8d6c6181c$var$GameObject2D extends (0, $8z0rK$phaserpluscore.GameObject) {
/**
* @private
* @type {World}
*/ context = null;
transform = new (0, $8z0rK$phaser.Math).Vector2(0, 0);
pivot = new (0, $8z0rK$phaser.Math).Vector2(0, 0);
/**
*
* @param {Scene} scene
* @param {World} context
*/ constructor(scene, context){
super(scene, 0, 0);
this.context = context;
}
get projection() {
return this.context.projection;
}
/**
*
* @param {number} x
* @param {number} y
*/ setTransform(x, y) {
this.projection.translate(x, y, this);
this.transform.set(x, y);
return this;
}
setTransformX(x) {
return this.setTransform(x, this.transform.y);
}
setTransformY(y) {
return this.setTransform(this.transform.x, y);
}
/**
*
* @param {string} tag
*/ addTag(tag) {
return this;
}
/**
*
* @param {string} tag
*/ removeTag(tag) {
return this;
}
removeTags() {}
/**
*
* @param {number} time
* @param {number} delta
*/ doUpdate(time, delta) {
super.doUpdate(time, delta);
this.projection.inverse.translate(this.x, this.y, this.transform);
this.pivot.set(this.transform.x, this.transform.y);
}
}
var $a7db11b8d6c6181c$export$2e2bcd8739ae039 = $a7db11b8d6c6181c$var$GameObject2D;
/**
* @callback SortFn
* @param {GameObject2D} objectA
* @param {GameObject2D} objectB
* @returns {number}
*/ class $1f6b557091af54f1$var$DepthSort {
/**
* @private
* @type {string}
*/ sortFn = "normalSort";
setup() {
this.sortFn = "normalSort";
}
disable() {
this.sortFn = "disabledSort";
}
set(inverseX = false, inverseY = false) {
if (!inverseX && !inverseY) this.sortFn = "normalSort";
else if (inverseX && !inverseY) this.sortFn = "inverseXSort";
else if (!inverseX && inverseY) this.sortFn = "inverseYSort";
else if (inverseX && inverseY) this.sortFn = "inverseSort";
}
/**
* @private
* @type {SortFn}
*/ normalSort = (objectA, objectB)=>{
let depth = objectA.depth - objectB.depth;
if (depth !== 0) return depth;
let orderY = objectA.pivot.y - objectB.pivot.y;
if (orderY !== 0) return orderY;
return objectA.pivot.x - objectB.pivot.x;
};
/**
* @private
* @type {SortFn}
*/ inverseXSort = (objectA, objectB)=>{
let depth = objectA.depth - objectB.depth;
if (depth !== 0) return depth;
let orderY = objectA.pivot.y - objectB.pivot.y;
if (orderY !== 0) return orderY;
return objectB.pivot.x - objectA.pivot.x;
};
/**
* @private
* @type {SortFn}
*/ inverseYSort = (objectA, objectB)=>{
let depth = objectA.depth - objectB.depth;
if (depth !== 0) return depth;
let orderY = objectB.pivot.y - objectA.pivot.y;
if (orderY !== 0) return orderY;
return objectA.pivot.x - objectB.pivot.x;
};
/**
* @private
* @type {SortFn}
*/ inverseSort = (objectA, objectB)=>{
let depth = objectA.depth - objectB.depth;
if (depth !== 0) return depth;
let orderY = objectB.pivot.y - objectA.pivot.y;
if (orderY !== 0) return orderY;
return objectB.pivot.x - objectA.pivot.x;
};
/**
* @private
* @type {SortFn}
*/ disabledSort = ()=>{};
get fn() {
return this[this.sortFn];
}
}
var $1f6b557091af54f1$export$2e2bcd8739ae039 = $1f6b557091af54f1$var$DepthSort;
class $16fdcf60a0c7b80c$var$Grid extends (0, $8z0rK$phaserpluscore.GameObject) {
STYLE = {
GRID: 0x59758a,
LINES: 0xffffff
};
/** @private */ TEXTURE_KEY = "";
/** @private */ TILE_PRECISION = 7;
/**
* @private
* @type {GameObjects.Graphics}
*/ canvas = null;
/**
* @private
* @type {GameObjects.TileSprite}
*/ gridTile = null;
/** @protected */ onCreate() {
this.TEXTURE_KEY = `/phaser+grid-${(0, $8z0rK$toolcasebase.generateId)(4)}`;
const { width: width , height: height } = this.game.config;
this.gridTile = this.scene.add.tileSprite(0, 0, width, height).setVisible(false).setOrigin(0);
this.add(this.gridTile);
}
setColors(gridColor, lineColor) {
if (typeof gridColor !== "number" || typeof lineColor !== "number") return;
this.STYLE.GRID = gridColor;
this.STYLE.LINES = lineColor;
}
/** @private */ setCanvasStyle() {
this.canvas.fillStyle(this.STYLE.GRID, 1);
this.canvas.lineStyle(1, this.STYLE.LINES, .3);
}
/** @protected */ onDestroy() {}
/**
*
* @param {Structs.Matrix2} matrix
*/ setProjection(matrix) {
this.canvas = this.scene.add.graphics();
this.setCanvasStyle();
this.add(this.canvas);
if (this.scene.textures.exists(this.TEXTURE_KEY)) this.scene.textures.remove(this.TEXTURE_KEY);
this.gridTile.setVisible(false);
let tile = this.getProjectionTileSize(matrix);
let size = 0;
for (let value of matrix)size = Math.max(size, Math.abs(value));
if (size < 25) this.drawBackground();
else if (tile.x === 0 || tile.y === 0) this.drawLinearTiles(matrix);
else this.drawGridTiles(matrix, tile);
this.canvas.clear();
this.canvas.destroy();
this.gridTile.setTexture(this.TEXTURE_KEY);
this.gridTile.setVisible(true);
}
/**
*
* @param {Cameras.Scene2D.Camera} camera
*/ move(camera) {
this.gridTile.setTilePosition(camera.scrollX, camera.scrollY);
}
/**
* @private
* @param {Structs.Matrix2} matrix
* @param {M.Vector2} tile
*/ drawGridTiles(matrix, tile) {
let polygons = this.TILE_PRECISION;
let pointA = new (0, $8z0rK$phaser.Math).Vector2(0, 0);
let pointB = new (0, $8z0rK$phaser.Math).Vector2(0, 0);
let pointC = new (0, $8z0rK$phaser.Math).Vector2(0, 0);
let pointD = new (0, $8z0rK$phaser.Math).Vector2(0, 0);
this.canvas.fillRect(0, 0, tile.x, tile.y);
for(let x = -polygons; x < polygons; x++)for(let y = -polygons; y < polygons; y++){
matrix.translate(x, y, pointA);
matrix.translate(x, y + 1, pointB);
matrix.translate(x + 1, y, pointC);
matrix.translate(x + 1, y + 1, pointD);
this.canvas.beginPath();
this.canvas.moveTo(pointA.x, pointA.y);
this.canvas.lineTo(pointB.x, pointB.y);
this.canvas.lineTo(pointD.x, pointD.y);
this.canvas.strokePath();
}
this.canvas.generateTexture(this.TEXTURE_KEY, tile.x, tile.y);
}
/** @private */ drawLinearTiles(matrix) {
let crop = new (0, $8z0rK$phaser.Math).Vector2(0, 0);
matrix.translate(2, 2, crop);
this.canvas.fillRect(0, 0, crop.x, crop.y);
this.canvas.lineStyle(1, 0xffffff, .2);
this.canvas.strokePoints([
matrix.translate(.8, 1),
matrix.translate(1.2, 1)
]);
this.canvas.strokePoints([
matrix.translate(1, .8),
matrix.translate(1, 1.2)
]);
this.canvas.generateTexture(this.TEXTURE_KEY, crop.x, crop.y);
}
/** @private */ drawBackground() {
this.canvas.fillRect(0, 0, 100, 100);
this.canvas.lineStyle(1, 0xffffff, .1);
this.canvas.strokeCircle(50, 50, 3);
this.canvas.generateTexture(this.TEXTURE_KEY, 100, 100);
}
/**
* @private
* @param {Structs.Matrix2} matrix
*/ getProjectionTileSize(matrix) {
let refPoint = new (0, $8z0rK$phaser.Math).Vector2(matrix.translate(1, 0).x, matrix.translate(0, 1).y);
refPoint.x = Math.abs(refPoint.x);
refPoint.y = Math.abs(refPoint.y);
let point = new (0, $8z0rK$phaser.Math).Vector2();
let tempPoint = new (0, $8z0rK$phaser.Math).Vector2();
let x = 0;
let shiftX = 0;
while(shiftX < this.TILE_PRECISION){
x += refPoint.x;
shiftX++;
matrix.inverse.translate(x, 0, tempPoint);
tempPoint.x = Math.round(tempPoint.x * 10) / 10;
tempPoint.y = Math.round(tempPoint.y * 10) / 10;
if (tempPoint.y % 1 === 0 && tempPoint.y % 1 === 0) {
point.x = Math.round(x);
break;
}
}
let y = 0;
let shiftY = 0;
while(shiftY < this.TILE_PRECISION){
y += refPoint.y;
shiftY++;
matrix.inverse.translate(0, y, tempPoint);
tempPoint.x = Math.round(tempPoint.x * 10) / 10;
tempPoint.y = Math.round(tempPoint.y * 10) / 10;
if (tempPoint.x % 1 === 0 && tempPoint.y % 1 === 0) {
point.y = Math.round(y);
break;
}
}
return point;
}
}
var $16fdcf60a0c7b80c$export$2e2bcd8739ae039 = $16fdcf60a0c7b80c$var$Grid;
/**
* @typedef GridColors
* @property {number} background
* @property {number} lines
*/ class $c40a4235a9c7b704$var$World extends (0, $8z0rK$phaserpluscore.Layer) {
/**
* @private
* @type {Grid}
*/ grid = null;
/** @private */ gridUpdate = null;
/**
* @private
* @type {Structs.Matrix2}
*/ _projection = (0, $8z0rK$phaserpluscore.Structs).Matrix2.create(50, 50);
sort = new (0, $1f6b557091af54f1$export$2e2bcd8739ae039)();
/** @protected */ onCreate() {
this.grid = new (0, $16fdcf60a0c7b80c$export$2e2bcd8739ae039)(this.scene, 0, 0);
this.grid.depth = -Number.MAX_SAFE_INTEGER;
this.scene.add.existing(this.grid);
this.grid.onCreate();
this.grid.setScrollFactor(0);
this.grid.setVisible(false);
super.onCreate();
this.onLayerUpdate();
}
/**
* @protected
*/ onLayerUpdate() {
super.onLayerUpdate();
this.grid.cameraFilter = this.container.cameraFilter;
this.grid.move(this.camera);
if (this.gridUpdate !== null) {
this.grid.setVisible(this.gridUpdate);
if (this.gridUpdate) this.grid.setProjection(this._projection);
this.gridUpdate = null;
}
this.container.list.sort(this.sort.fn);
if (typeof this.scene.matter !== "undefined") {
if (typeof this.scene.matter.world.debugGraphic !== "undefined") this.scene.matter.world.debugGraphic.cameraFilter = this.container.cameraFilter;
}
}
/** @protected */ onDestroy() {
super.onDestroy();
}
/**
*
* @param {boolean} flag
* @param {GridColors} [colors]
*/ debug(flag = true, colors = {}) {
if (typeof colors === "object") this.grid.setColors(colors.background, colors.lines);
if (typeof flag !== "boolean") return this;
this.gridUpdate = null;
if (this.grid.visible === flag) return this;
this.gridUpdate = flag;
}
/**
*
* @param {Structs.Matrix2} matrix
*/ set projection(matrix) {
this._projection.setValues(matrix.v00, matrix.v01, matrix.v10, matrix.v11);
this.sort.setup();
this.list.forEach((object)=>{
object.setTransform(object.transform.x, object.transform.y);
});
if (this.grid.visible) this.gridUpdate = true;
return this._projection;
}
get projection() {
return this._projection;
}
/**
* @param {string} key
* @param {new GameObject2D} gameObjectClass
*/ register(key, gameObjectClass) {
this.scene.pool.register(key, gameObjectClass, this.createInstanceFn);
return this;
}
/**
* @template {GameObject2D} T
* @param {string} key
* @param {number} x
* @param {number} y
* @param {Array<string>} tags
* @returns {T}
*/ add(key, x, y) {
/** @type {GameObject2D} */ let object = this.scene.pool.obtain(key);
if (object === null) return null;
this.container.add(object);
object.setTransform(x, y);
return object;
}
/**
* @template {GameObject2D} T
* @param {T} gameObject
*/ remove(gameObject) {
this.container.remove(gameObject);
this.scene.pool.release(gameObject);
return this;
}
/**
* @private
* @param {string} _
* @param {new GameObject2D} gameObjectClass
* @param {Scene} scene
*/ createInstanceFn = (_, gameObjectClass, scene)=>{
let object = new gameObjectClass(scene, this);
return object;
};
}
var $c40a4235a9c7b704$export$2e2bcd8739ae039 = $c40a4235a9c7b704$var$World;
class $09ff86e408181510$var$Scene2D extends (0, $8z0rK$phaserpluscore.Scene) {
/**
* @protected
* @type {ObjectLayer}
*/ ui = null;
/**
* @protected
* @type {World}
*/ world = null;
/**
* @protected
* @override
*/ beforeInit() {
this.world = this.features.register("world", (0, $c40a4235a9c7b704$export$2e2bcd8739ae039));
this.ui = this.features.register("ui", (0, $8z0rK$phaserpluscore.ObjectLayer));
}
}
var $09ff86e408181510$export$2e2bcd8739ae039 = $09ff86e408181510$var$Scene2D;