New chunk-based rendering method, reorganized file structure
This commit is contained in:
parent
f989793a55
commit
74fd7c491f
@ -105,7 +105,7 @@ class LoadScene extends Phaser.Scene {
|
|||||||
this.patching = this.add.sprite(this.cameras.main.width / 2, this.cameras.main.height / 2 - 100, "loader_patching");
|
this.patching = this.add.sprite(this.cameras.main.width / 2, this.cameras.main.height / 2 - 100, "loader_patching");
|
||||||
this.patching.setScale(6);
|
this.patching.setScale(6);
|
||||||
|
|
||||||
this.text.setText(" Patching Tiles...");
|
this.text.setText(" Loading Map...");
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.game.scene.start('MapScene');
|
this.game.scene.start('MapScene');
|
||||||
|
79
src/MapScene/FogOfWar.ts
Normal file
79
src/MapScene/FogOfWar.ts
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
// class FogOfWar {
|
||||||
|
// scene: MapScene;
|
||||||
|
|
||||||
|
// tex: Phaser.GameObjects.RenderTexture;
|
||||||
|
// map: Phaser.Tilemaps.Tilemap;
|
||||||
|
// historyLayer: Phaser.Tilemaps.DynamicTilemapLayer;
|
||||||
|
|
||||||
|
// dims: Vec2;
|
||||||
|
|
||||||
|
// constructor(scene: MapScene, dims: Vec2) {
|
||||||
|
// this.scene = scene;
|
||||||
|
// this.dims = dims;
|
||||||
|
|
||||||
|
// this.tex = new Phaser.GameObjects.RenderTexture(this.scene, 0, 0, this.dims.x*16, this.dims.y*16);
|
||||||
|
// this.tex.setScale(4, 4);
|
||||||
|
// this.tex.setAlpha(0.7);
|
||||||
|
// this.scene.add.existing(this.tex);
|
||||||
|
|
||||||
|
// // this.map = this.scene.add.tilemap(null, 16, 16, 0, 0);
|
||||||
|
// // this.map.addTilesetImage("history", "wall_shadow", 16, 16, 0, 0);
|
||||||
|
// // this.map.setLayer("history");
|
||||||
|
// // this.historyLayer = this.map.createBlankDynamicLayer("history", "wall_shadow", 0, 0, this.dims.x, this.dims.y, 16, 16);
|
||||||
|
// // this.historyLayer.setScale(4, 4);
|
||||||
|
|
||||||
|
// // for (let i = 0; i < this.dims.x; i++) {
|
||||||
|
// // for (let j = 0; j < this.dims.y; j++) {
|
||||||
|
// // if ((j % 2 == 0 && i % 2 == 0) || (j % 2 != 0 && i % 2 != 0)) this.historyLayer.putTileAt(0, i, j);
|
||||||
|
// // }
|
||||||
|
// // }
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
// update() {
|
||||||
|
// let resetSquare = new Phaser.GameObjects.Rectangle(this.scene, 0, 0, this.dims.x*16, this.dims.y*16, 0x000000);
|
||||||
|
// this.tex.draw(resetSquare);
|
||||||
|
|
||||||
|
// for (let token of this.scene.tokens) {
|
||||||
|
// let startTile = new Vec2(Math.floor(token.x / 64), Math.floor(token.y / 64))
|
||||||
|
|
||||||
|
// let points: Vec2[] = [];
|
||||||
|
|
||||||
|
// for (let i = 0; i < 288; i++) {
|
||||||
|
// let ray = new Vec2(0.5, 0.5);
|
||||||
|
// let dir = new Vec2(Math.cos(i * 1.25 * (Math.PI / 180)) / 32, Math.sin(i * 1.25 * (Math.PI / 180)) / 32);
|
||||||
|
|
||||||
|
// let dist = 0;
|
||||||
|
// let maxDist = 12;
|
||||||
|
|
||||||
|
// while (this.scene.map.getWall(Math.floor(startTile.x + ray.x), Math.floor(startTile.y + ray.y)) == -1 &&
|
||||||
|
// (dist = Math.sqrt(Math.pow(ray.x, 2) + Math.pow(ray.y, 2))) < maxDist) {
|
||||||
|
// ray.x += dir.x;
|
||||||
|
// ray.y += dir.y;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// ray.x -= dir.x * maxDist * 2.4;
|
||||||
|
// ray.y -= dir.y * maxDist * 2.4;
|
||||||
|
|
||||||
|
// ray.x += dir.x * ((maxDist - dist) * 2.8);
|
||||||
|
// ray.y += dir.y * ((maxDist - dist) * 2.8);
|
||||||
|
|
||||||
|
// points.push(new Vec2(ray.x * 4, ray.y * 4));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// let poly = new Phaser.GameObjects.Polygon(this.scene, token.x / 4, token.y / 4, points, 0xffffff, 0.4);
|
||||||
|
// poly.setScale(4, 4);
|
||||||
|
// poly.setBlendMode('ERASE');
|
||||||
|
// poly.setDisplayOrigin(0, 0);
|
||||||
|
// poly.setOrigin(0, 0);
|
||||||
|
|
||||||
|
// for (let i = 0; i < 10; i++) {
|
||||||
|
// poly.scaleX += 0.04;
|
||||||
|
// poly.scaleY += 0.04;
|
||||||
|
// // poly.x = token.x / 4 + 50 * poly.scaleX;
|
||||||
|
// // poly.y = token.y / 4 + 50 * poly.scaleY;
|
||||||
|
// this.tex.draw(poly);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
@ -13,7 +13,7 @@ class HistoryElement {
|
|||||||
console.log("Undo", this.type);
|
console.log("Undo", this.type);
|
||||||
if (this.type == "tile") {
|
if (this.type == "tile") {
|
||||||
for (let tile of this.data as {pos: Vec2, layer: Layer, lastTile: number, tile: number}[])
|
for (let tile of this.data as {pos: Vec2, layer: Layer, lastTile: number, tile: number}[])
|
||||||
this.scene.map.setTile(tile.pos.x, tile.pos.y, tile.lastTile, tile.layer);
|
this.scene.map.setTile(tile.layer, tile.lastTile, tile.pos.x, tile.pos.y);
|
||||||
}
|
}
|
||||||
else if (this.type == "token_modify") {
|
else if (this.type == "token_modify") {
|
||||||
let data = this.data as { old: string[], new: string[] };
|
let data = this.data as { old: string[], new: string[] };
|
||||||
@ -61,7 +61,7 @@ class HistoryElement {
|
|||||||
console.log("Redo", this.type);
|
console.log("Redo", this.type);
|
||||||
if (this.type == "tile") {
|
if (this.type == "tile") {
|
||||||
for (let tile of this.data as {pos: Vec2, layer: Layer, lastTile: number, tile: number}[])
|
for (let tile of this.data as {pos: Vec2, layer: Layer, lastTile: number, tile: number}[])
|
||||||
this.scene.map.setTile(tile.pos.x, tile.pos.y, tile.tile, tile.layer);
|
this.scene.map.setTile(tile.layer, tile.tile, tile.pos.x, tile.pos.y);
|
||||||
}
|
}
|
||||||
else if (this.type == "token_modify") {
|
else if (this.type == "token_modify") {
|
||||||
let data = this.data as { old: string[], new: string[] };
|
let data = this.data as { old: string[], new: string[] };
|
@ -49,15 +49,15 @@ class UITileSidebar extends UISidebar {
|
|||||||
elemClick(x: number, y: number): void {
|
elemClick(x: number, y: number): void {
|
||||||
if (y < 4) {
|
if (y < 4) {
|
||||||
this.scene.architect.activeTileset = this.scene.map.manager.indexes[this.walls[x + y * 3]];
|
this.scene.architect.activeTileset = this.scene.map.manager.indexes[this.walls[x + y * 3]];
|
||||||
this.scene.architect.activeLayer = Layer.WALL;
|
this.scene.architect.activeLayer = Layer.wall;
|
||||||
}
|
}
|
||||||
else if (y < 8) {
|
else if (y < 8) {
|
||||||
this.scene.architect.activeTileset = this.scene.map.manager.indexes[this.grounds[x + (y - 4) * 3]];
|
this.scene.architect.activeTileset = this.scene.map.manager.indexes[this.grounds[x + (y - 4) * 3]];
|
||||||
this.scene.architect.activeLayer = Layer.GROUND;
|
this.scene.architect.activeLayer = Layer.floor;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.scene.architect.activeTileset = this.scene.map.manager.indexes[this.overlays[x + (y - 8) * 3]];
|
this.scene.architect.activeTileset = this.scene.map.manager.indexes[this.overlays[x + (y - 8) * 3]];
|
||||||
this.scene.architect.activeLayer = Layer.OVERLAY;
|
this.scene.architect.activeLayer = Layer.overlay;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -11,7 +11,7 @@ class ArchitectMode {
|
|||||||
pointerPrimaryDown: boolean = false;
|
pointerPrimaryDown: boolean = false;
|
||||||
|
|
||||||
activeTileset: number = 0;
|
activeTileset: number = 0;
|
||||||
activeLayer: Layer = Layer.WALL;
|
activeLayer: Layer = Layer.wall;
|
||||||
|
|
||||||
manipulated: {pos: Vec2, layer: Layer, lastTile: number, tile: number}[] = [];
|
manipulated: {pos: Vec2, layer: Layer, lastTile: number, tile: number}[] = [];
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ class ArchitectMode {
|
|||||||
this.cursor.setPosition(selectedTilePos.x * 64, selectedTilePos.y * 64);
|
this.cursor.setPosition(selectedTilePos.x * 64, selectedTilePos.y * 64);
|
||||||
|
|
||||||
this.cursor.setVisible((selectedTilePos.x >= 0 && selectedTilePos.y >= 0 &&
|
this.cursor.setVisible((selectedTilePos.x >= 0 && selectedTilePos.y >= 0 &&
|
||||||
selectedTilePos.x < this.scene.map.dimensions.x && selectedTilePos.y < this.scene.map.dimensions.y));
|
selectedTilePos.x < this.scene.map.size.x && selectedTilePos.y < this.scene.map.size.y));
|
||||||
|
|
||||||
// Place Tiles
|
// Place Tiles
|
||||||
switch(this.placeMode) {
|
switch(this.placeMode) {
|
||||||
@ -188,12 +188,12 @@ class ArchitectMode {
|
|||||||
|
|
||||||
placeTileAndPushManip(manipPos: Vec2, solid: boolean) {
|
placeTileAndPushManip(manipPos: Vec2, solid: boolean) {
|
||||||
let tile = solid ? this.activeTileset : -1;
|
let tile = solid ? this.activeTileset : -1;
|
||||||
let layer = (tile == -1 && this.activeLayer == Layer.GROUND) ? Layer.WALL : this.activeLayer;
|
let layer = (tile == -1 && this.activeLayer == Layer.floor) ? Layer.wall : this.activeLayer;
|
||||||
|
|
||||||
let lastTile = this.scene.map.getTile(manipPos.x, manipPos.y, layer);
|
let lastTile = this.scene.map.getTileset(layer, manipPos.x, manipPos.y);
|
||||||
if (tile == lastTile) return;
|
if (tile == lastTile) return;
|
||||||
|
|
||||||
this.scene.map.setTile(manipPos.x, manipPos.y, tile, layer);
|
this.scene.map.setTile(layer, tile, manipPos.x, manipPos.y);
|
||||||
|
|
||||||
this.manipulated.push({
|
this.manipulated.push({
|
||||||
pos: manipPos,
|
pos: manipPos,
|
@ -19,6 +19,8 @@ class UIView {
|
|||||||
this.camera.scrollX = -10000;
|
this.camera.scrollX = -10000;
|
||||||
|
|
||||||
this.o = this.scene.add.container(-10000, 0);
|
this.o = this.scene.add.container(-10000, 0);
|
||||||
|
|
||||||
|
this.createElements();
|
||||||
}
|
}
|
||||||
|
|
||||||
createElements() {
|
createElements() {
|
||||||
@ -81,6 +83,23 @@ class UIView {
|
|||||||
this.displayToken();
|
this.displayToken();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.scene.i.keyPressed('TAB')) this.scene.mode = (this.scene.mode == 0 ? 1 : 0);
|
||||||
|
|
||||||
|
if (this.scene.mode == 0) {
|
||||||
|
if (this.uiActive) this.scene.architect.cleanup();
|
||||||
|
else {
|
||||||
|
this.scene.architect.update();
|
||||||
|
this.scene.token.cleanup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (this.uiActive) this.scene.token.cleanup();
|
||||||
|
else {
|
||||||
|
this.scene.token.update();
|
||||||
|
this.scene.architect.cleanup();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
displayArchitect() {
|
displayArchitect() {
|
9
src/MapScene/Lighting/Lighting.ts
Normal file
9
src/MapScene/Lighting/Lighting.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
class Lighting {
|
||||||
|
constructor(...any) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
90
src/MapScene/Map/MapChunk.ts
Normal file
90
src/MapScene/Map/MapChunk.ts
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
class MapChunk {
|
||||||
|
static CHUNK_SIZE = 16;
|
||||||
|
static TILE_SIZE = 16;
|
||||||
|
static DIRTY_LIMIT = 32;
|
||||||
|
|
||||||
|
private pos: Vec2;
|
||||||
|
private map: MapData;
|
||||||
|
private canvas: Phaser.GameObjects.RenderTexture;
|
||||||
|
|
||||||
|
private dirtyList: Vec2[] = [];
|
||||||
|
private fullyDirty: boolean = false;
|
||||||
|
|
||||||
|
constructor(map: MapData, x: number, y: number) {
|
||||||
|
this.pos = new Vec2(x, y);
|
||||||
|
this.canvas = map.scene.add.renderTexture(
|
||||||
|
x * MapChunk.CHUNK_SIZE * MapChunk.TILE_SIZE * 4, y * MapChunk.CHUNK_SIZE * MapChunk.TILE_SIZE * 4,
|
||||||
|
MapChunk.CHUNK_SIZE * MapChunk.TILE_SIZE, MapChunk.CHUNK_SIZE * MapChunk.TILE_SIZE);
|
||||||
|
|
||||||
|
this.map = map;
|
||||||
|
this.canvas.setScale(4);
|
||||||
|
this.canvas.setOrigin(0, 0);
|
||||||
|
|
||||||
|
for (let i = 0; i < MapChunk.CHUNK_SIZE * MapChunk.CHUNK_SIZE; i++) {
|
||||||
|
let x = i % MapChunk.CHUNK_SIZE;
|
||||||
|
let y = Math.floor(i / MapChunk.CHUNK_SIZE);
|
||||||
|
|
||||||
|
let mX = x + this.pos.x * MapChunk.CHUNK_SIZE;
|
||||||
|
let mY = y + this.pos.y * MapChunk.CHUNK_SIZE;
|
||||||
|
if (mX >= this.map.size.x || mY >= this.map.size.y) continue;
|
||||||
|
|
||||||
|
this.drawTile(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dirty(pos: Vec2): void {
|
||||||
|
if (!this.fullyDirty) {
|
||||||
|
for (let v of this.dirtyList) if (v.equals(pos)) return;
|
||||||
|
this.dirtyList.push(pos);
|
||||||
|
|
||||||
|
if (this.dirtyList.length > MapChunk.DIRTY_LIMIT) {
|
||||||
|
this.fullyDirty = true;
|
||||||
|
this.dirtyList = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rebuild(): boolean {
|
||||||
|
if (this.fullyDirty) {
|
||||||
|
for (let i = 0; i < MapChunk.CHUNK_SIZE * MapChunk.CHUNK_SIZE; i++) {
|
||||||
|
let x = i % MapChunk.CHUNK_SIZE;
|
||||||
|
let y = Math.floor(i / MapChunk.CHUNK_SIZE);
|
||||||
|
|
||||||
|
let mX = x + this.pos.x * MapChunk.CHUNK_SIZE;
|
||||||
|
let mY = y + this.pos.y * MapChunk.CHUNK_SIZE;
|
||||||
|
if (mX >= this.map.size.x || mY >= this.map.size.y) continue;
|
||||||
|
|
||||||
|
this.drawTile(x, y);
|
||||||
|
}
|
||||||
|
this.fullyDirty = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.dirtyList.length == 0) return false;
|
||||||
|
|
||||||
|
for (let elem of this.dirtyList) this.drawTile(elem.x, elem.y);
|
||||||
|
this.dirtyList = [];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private drawTile(x: number, y: number): void {
|
||||||
|
let mX = x + this.pos.x * MapChunk.CHUNK_SIZE;
|
||||||
|
let mY = y + this.pos.y * MapChunk.CHUNK_SIZE;
|
||||||
|
|
||||||
|
let wallTile = this.map.getTile(Layer.wall, mX, mY);
|
||||||
|
if (this.map.getTileset(Layer.wall, mX, mY) == -1 || (wallTile < 54 || wallTile > 60)) {
|
||||||
|
this.canvas.drawFrame(this.map.manager.groundLocations[this.map.getTileset(Layer.floor, mX, mY)].key,
|
||||||
|
this.map.getTile(Layer.floor, mX, mY), x * MapChunk.TILE_SIZE, y * MapChunk.TILE_SIZE);
|
||||||
|
|
||||||
|
if (this.map.getTileset(Layer.overlay, mX, mY) != -1)
|
||||||
|
this.canvas.drawFrame(this.map.manager.overlayLocations[this.map.getTileset(Layer.overlay, mX, mY)].key,
|
||||||
|
this.map.getTile(Layer.overlay, mX, mY), x * MapChunk.TILE_SIZE, y * MapChunk.TILE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.map.getTileset(Layer.wall, mX, mY) != -1)
|
||||||
|
this.canvas.drawFrame(this.map.manager.wallLocations[this.map.getTileset(Layer.wall, mX, mY)].key,
|
||||||
|
this.map.getTile(Layer.wall, mX, mY), x * MapChunk.TILE_SIZE, y * MapChunk.TILE_SIZE);
|
||||||
|
|
||||||
|
if ((x % 2 == 0 && y % 2 == 0) || (x % 2 != 0 && y % 2 != 0)) this.canvas.drawFrame('grid_tile', 0, x * MapChunk.TILE_SIZE, y * MapChunk.TILE_SIZE);
|
||||||
|
}
|
||||||
|
}
|
138
src/MapScene/Map/MapData.ts
Normal file
138
src/MapScene/Map/MapData.ts
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
const enum Layer {
|
||||||
|
floor = 0,
|
||||||
|
wall = 1,
|
||||||
|
overlay = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
class MapData {
|
||||||
|
scene: MapScene;
|
||||||
|
size: Vec2;
|
||||||
|
|
||||||
|
|
||||||
|
manager: TilesetManager;
|
||||||
|
private layers: {[key: number]: { tiles: number[][], tilesets: number[][] }} = {};
|
||||||
|
private chunks: MapChunk[][] = [];
|
||||||
|
|
||||||
|
constructor(scene: MapScene, size: Vec2) {
|
||||||
|
this.scene = scene;
|
||||||
|
this.size = size;
|
||||||
|
this.manager = new TilesetManager(scene);
|
||||||
|
|
||||||
|
this.registerLayer(Layer.floor, () => Math.floor(Math.random() * 6) + 54, 0);
|
||||||
|
this.registerLayer(Layer.wall, 0, -1);
|
||||||
|
this.registerLayer(Layer.overlay, 0, -1);
|
||||||
|
|
||||||
|
for (let i = 0; i < Math.ceil(size.y / MapChunk.CHUNK_SIZE); i++) {
|
||||||
|
this.chunks[i] = [];
|
||||||
|
for (let j = 0; j < Math.ceil(size.x / MapChunk.CHUNK_SIZE); j++) {
|
||||||
|
this.chunks[i][j] = new MapChunk(this, j, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
update(): void {
|
||||||
|
let start = Date.now();
|
||||||
|
for (let arr of this.chunks) for (let chunk of arr) {
|
||||||
|
chunk.rebuild();
|
||||||
|
if (Date.now() - start > 10) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setTile(layer: Layer, tileset: number, xx: number | Vec2, yy?: number): boolean {
|
||||||
|
let x: number, y: number;
|
||||||
|
if (xx instanceof Vec2) { x = xx.x; y = xx.y; }
|
||||||
|
else { x = xx; y = yy; }
|
||||||
|
|
||||||
|
if (x < 0 || y < 0 || x >= this.size.x || y >= this.size.y) return false;
|
||||||
|
|
||||||
|
let oldTileset = this.getTileset(layer, x, y);
|
||||||
|
if (oldTileset == tileset) return false;
|
||||||
|
this.setTileset(layer, x, y, tileset);
|
||||||
|
this.smartTile(x, y);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
setTileset(key: number, x: number | Vec2, a?: number, b?: number): void {
|
||||||
|
if (x instanceof Vec2) this.layers[key].tilesets[x.y][x.x] = a;
|
||||||
|
else this.layers[key].tilesets[a][x] = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
getTile(key: number, xx: number | Vec2, yy?: number): number {
|
||||||
|
let x: number, y: number;
|
||||||
|
if (xx instanceof Vec2) { x = xx.x; y = xx.y; }
|
||||||
|
else { x = xx; y = yy; }
|
||||||
|
|
||||||
|
return this.layers[key].tiles[clamp(y, 0, this.size.y - 1)][clamp(x, 0, this.size.x - 1)];
|
||||||
|
}
|
||||||
|
|
||||||
|
getTileset(key: number, xx: number | Vec2, yy?: number): number {
|
||||||
|
let x: number, y: number;
|
||||||
|
if (xx instanceof Vec2) { x = xx.x; y = xx.y; }
|
||||||
|
else { x = xx; y = yy; }
|
||||||
|
|
||||||
|
return this.layers[key].tilesets[clamp(y, 0, this.size.y - 1)][clamp(x, 0, this.size.x - 1)];
|
||||||
|
}
|
||||||
|
|
||||||
|
private smartTile(x: number, y: number): void {
|
||||||
|
for (let i = clamp(x - 1, this.size.x - 1, 0); i <= clamp(x + 1, this.size.x - 1, 0); i++) {
|
||||||
|
for (let j = clamp(y - 1, this.size.y - 1, 0); j <= clamp(y + 1, this.size.y - 1, 0); j++) {
|
||||||
|
const solids = this.getTilesetsAt(Layer.wall, i, j).map(i => i != -1);
|
||||||
|
|
||||||
|
const wall = SmartTiler.wall(solids, this.getTile(Layer.wall, i, j));
|
||||||
|
if (wall != -1) this.setTileRaw(Layer.wall, i, j, wall);
|
||||||
|
|
||||||
|
const floor = SmartTiler.floor(solids, this.getTile(Layer.floor, i, j));
|
||||||
|
if (floor != -1) this.setTileRaw(Layer.floor, i, j, floor);
|
||||||
|
|
||||||
|
const overlay = SmartTiler.overlay(this.getTilesetsAt(Layer.overlay, i, j)
|
||||||
|
.map(t => t == this.getTileset(Layer.overlay, i, j)), this.getTileset(Layer.overlay, i, j));
|
||||||
|
if (overlay != -1) this.setTileRaw(Layer.overlay, i, j, overlay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private setTileRaw(key: number, x: number | Vec2, a?: number, b?: number, c?: number): void {
|
||||||
|
if (x instanceof Vec2) {
|
||||||
|
this.layers[key].tiles[x.y][x.x] = a;
|
||||||
|
if (b !== undefined) this.setTileset(key, x, b);
|
||||||
|
|
||||||
|
this.chunks[Math.floor(x.y / MapChunk.CHUNK_SIZE)][Math.floor(x.x / MapChunk.CHUNK_SIZE)]
|
||||||
|
.dirty(new Vec2(x.x % MapChunk.CHUNK_SIZE, x.y % MapChunk.CHUNK_SIZE));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.layers[key].tiles[a][x] = b;
|
||||||
|
if (c !== undefined) this.setTileset(key, x, a, c);
|
||||||
|
|
||||||
|
this.chunks[Math.floor(a / MapChunk.CHUNK_SIZE)][Math.floor(x / MapChunk.CHUNK_SIZE)]
|
||||||
|
.dirty(new Vec2(x % MapChunk.CHUNK_SIZE, a % MapChunk.CHUNK_SIZE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getTilesetsAt(layer: Layer, x: number, y: number): number[] {
|
||||||
|
let tilesets: number[] = [];
|
||||||
|
for (let i = -1; i <= 1; i++)
|
||||||
|
for (let j = -1; j <= 1; j++)
|
||||||
|
tilesets.push(this.getTileset(layer, clamp(x + j, 0, this.size.x - 1), clamp(y + i, 0, this.size.y - 1)));
|
||||||
|
return tilesets;
|
||||||
|
}
|
||||||
|
|
||||||
|
private registerLayer(key: number, startTile: any = 0, startTileset: number = -1): void {
|
||||||
|
let layer = {
|
||||||
|
tiles: [],
|
||||||
|
tilesets: []
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < this.size.y; i++) {
|
||||||
|
layer.tiles[i] = [];
|
||||||
|
layer.tilesets[i] = [];
|
||||||
|
for (let j = 0; j < this.size.x; j++) {
|
||||||
|
let tile = typeof(startTile) == "number" ? startTile : startTile();
|
||||||
|
layer.tiles[i][j] = tile;
|
||||||
|
layer.tilesets[i][j] = startTileset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.layers[key] = layer;
|
||||||
|
}
|
||||||
|
}
|
@ -219,7 +219,7 @@ namespace SmartTiler {
|
|||||||
return tile;
|
return tile;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ground(walls: boolean[], current: number): number {
|
export function floor(walls: boolean[], current: number): number {
|
||||||
const TL = 0, T = 1, TR = 2, L = 3, C = 4, R = 5, BL = 6, B = 7, BR = 8;
|
const TL = 0, T = 1, TR = 2, L = 3, C = 4, R = 5, BL = 6, B = 7, BR = 8;
|
||||||
|
|
||||||
if (current == -1) return -1;
|
if (current == -1) return -1;
|
31
src/MapScene/Map/TilesetManager.ts
Normal file
31
src/MapScene/Map/TilesetManager.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
class TilesetManager {
|
||||||
|
scene: MapScene;
|
||||||
|
|
||||||
|
private currentWallInd: number = 0;
|
||||||
|
private currentGroundInd: number = 0;
|
||||||
|
private currentOverlayInd: number = 0;
|
||||||
|
|
||||||
|
wallLocations: {[key: number /*Index*/]: { res: number, ind: number, key: string }} = {};
|
||||||
|
groundLocations: {[key: number /*Index*/]: { res: number, ind: number, key: string }} = {};
|
||||||
|
overlayLocations: {[key: number /*Index*/]: { res: number, ind: number, key: string }} = {};
|
||||||
|
indexes: {[key: string /*Tileset Key*/]: number} = {};
|
||||||
|
|
||||||
|
constructor(scene: MapScene) {
|
||||||
|
this.scene = scene;
|
||||||
|
|
||||||
|
for (let tileset of WALLS ) this.addTileset(tileset.key, Layer.wall);
|
||||||
|
for (let tileset of GROUNDS ) this.addTileset(tileset.key, Layer.floor);
|
||||||
|
for (let tileset of OVERLAYS) this.addTileset(tileset.key, Layer.overlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
private addTileset(key: string, layer: Layer): void {
|
||||||
|
let res = this.scene.textures.get(key).getSourceImage(0).width / 9;
|
||||||
|
let ind = (layer == Layer.wall ? this.currentWallInd : layer == Layer.floor ? this.currentGroundInd : this.currentOverlayInd);
|
||||||
|
this[layer == Layer.wall ? "wallLocations" : layer == Layer.floor ? "groundLocations" : "overlayLocations"][ind] = { res: res, ind: ind, key: key };
|
||||||
|
this.indexes[key] = ind;
|
||||||
|
|
||||||
|
layer == Layer.wall ? this.currentWallInd++ :
|
||||||
|
layer == Layer.floor ? this.currentGroundInd++ :
|
||||||
|
this.currentOverlayInd++;
|
||||||
|
}
|
||||||
|
}
|
58
src/MapScene/MapScene.ts
Normal file
58
src/MapScene/MapScene.ts
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
class MapScene extends Phaser.Scene {
|
||||||
|
i: InputManager;
|
||||||
|
|
||||||
|
history: HistoryManager;
|
||||||
|
|
||||||
|
architect: ArchitectMode;
|
||||||
|
token: TokenMode;
|
||||||
|
|
||||||
|
world: WorldView;
|
||||||
|
map: MapData;
|
||||||
|
lighting: Lighting;
|
||||||
|
ui: UIView;
|
||||||
|
|
||||||
|
|
||||||
|
mode: number = 0;
|
||||||
|
tokens: Token[] = [];
|
||||||
|
|
||||||
|
constructor() { super({key: "MapScene"}); }
|
||||||
|
|
||||||
|
preload(): void {
|
||||||
|
window.addEventListener('resize', () => {
|
||||||
|
let frame = document.getElementById("game");
|
||||||
|
this.game.scale.resize(frame.offsetWidth, frame.offsetHeight);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
create(): void {
|
||||||
|
this.i = new InputManager(this);
|
||||||
|
|
||||||
|
(this.game.renderer as Phaser.Renderer.WebGL.WebGLRenderer).addPipeline('outline', new OutlinePipeline(this.game));
|
||||||
|
(this.game.renderer as Phaser.Renderer.WebGL.WebGLRenderer).addPipeline('brighten', new BrightenPipeline(this.game));
|
||||||
|
|
||||||
|
this.history = new HistoryManager(this);
|
||||||
|
this.world = new WorldView(this);
|
||||||
|
this.ui = new UIView(this);
|
||||||
|
|
||||||
|
const size = new Vec2(300, 300);
|
||||||
|
|
||||||
|
this.map = new MapData(this, size);
|
||||||
|
this.lighting = new Lighting(this, size);
|
||||||
|
|
||||||
|
this.architect = new ArchitectMode(this);
|
||||||
|
this.token = new TokenMode(this);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
update(time: number, delta: number): void {
|
||||||
|
this.i.update();
|
||||||
|
|
||||||
|
this.history.update();
|
||||||
|
this.world.update();
|
||||||
|
this.ui.update();
|
||||||
|
|
||||||
|
this.map.update();
|
||||||
|
this.lighting.update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -15,6 +15,10 @@ class Vec2 {
|
|||||||
this.y = (x as any as {x: number, y:number}).y;
|
this.y = (x as any as {x: number, y:number}).y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
equals(o: Vec2) {
|
||||||
|
return this.x == o.x && this.y == o.y;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Vec3 {
|
class Vec3 {
|
||||||
@ -42,6 +46,10 @@ class Vec3 {
|
|||||||
this.z = (x as any as {x: number, y:number, z:number}).z;
|
this.z = (x as any as {x: number, y:number, z:number}).z;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
equals(o: Vec3) {
|
||||||
|
return this.x == o.x && this.y == o.y && this.z == o.z;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Vec4 {
|
class Vec4 {
|
||||||
@ -73,4 +81,8 @@ class Vec4 {
|
|||||||
this.w = (x as any).w;
|
this.w = (x as any).w;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
equals(o: Vec4) {
|
||||||
|
return this.x == o.x && this.y == o.y && this.z == o.z && this.w == o.w;
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,79 +0,0 @@
|
|||||||
class FogOfWar {
|
|
||||||
scene: MapScene;
|
|
||||||
|
|
||||||
tex: Phaser.GameObjects.RenderTexture;
|
|
||||||
map: Phaser.Tilemaps.Tilemap;
|
|
||||||
historyLayer: Phaser.Tilemaps.DynamicTilemapLayer;
|
|
||||||
|
|
||||||
dims: Vec2;
|
|
||||||
|
|
||||||
constructor(scene: MapScene, dims: Vec2) {
|
|
||||||
this.scene = scene;
|
|
||||||
this.dims = dims;
|
|
||||||
|
|
||||||
this.tex = new Phaser.GameObjects.RenderTexture(this.scene, 0, 0, this.dims.x*16, this.dims.y*16);
|
|
||||||
this.tex.setScale(4, 4);
|
|
||||||
this.tex.setAlpha(0.7);
|
|
||||||
this.scene.add.existing(this.tex);
|
|
||||||
|
|
||||||
// this.map = this.scene.add.tilemap(null, 16, 16, 0, 0);
|
|
||||||
// this.map.addTilesetImage("history", "wall_shadow", 16, 16, 0, 0);
|
|
||||||
// this.map.setLayer("history");
|
|
||||||
// this.historyLayer = this.map.createBlankDynamicLayer("history", "wall_shadow", 0, 0, this.dims.x, this.dims.y, 16, 16);
|
|
||||||
// this.historyLayer.setScale(4, 4);
|
|
||||||
|
|
||||||
// for (let i = 0; i < this.dims.x; i++) {
|
|
||||||
// for (let j = 0; j < this.dims.y; j++) {
|
|
||||||
// if ((j % 2 == 0 && i % 2 == 0) || (j % 2 != 0 && i % 2 != 0)) this.historyLayer.putTileAt(0, i, j);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
update() {
|
|
||||||
let resetSquare = new Phaser.GameObjects.Rectangle(this.scene, 0, 0, this.dims.x*16, this.dims.y*16, 0x000000);
|
|
||||||
this.tex.draw(resetSquare);
|
|
||||||
|
|
||||||
for (let token of this.scene.tokens) {
|
|
||||||
let startTile = new Vec2(Math.floor(token.x / 64), Math.floor(token.y / 64))
|
|
||||||
|
|
||||||
let points: Vec2[] = [];
|
|
||||||
|
|
||||||
for (let i = 0; i < 288; i++) {
|
|
||||||
let ray = new Vec2(0.5, 0.5);
|
|
||||||
let dir = new Vec2(Math.cos(i * 1.25 * (Math.PI / 180)) / 32, Math.sin(i * 1.25 * (Math.PI / 180)) / 32);
|
|
||||||
|
|
||||||
let dist = 0;
|
|
||||||
let maxDist = 12;
|
|
||||||
|
|
||||||
while (this.scene.map.getWall(Math.floor(startTile.x + ray.x), Math.floor(startTile.y + ray.y)) == -1 &&
|
|
||||||
(dist = Math.sqrt(Math.pow(ray.x, 2) + Math.pow(ray.y, 2))) < maxDist) {
|
|
||||||
ray.x += dir.x;
|
|
||||||
ray.y += dir.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
ray.x -= dir.x * maxDist * 2.4;
|
|
||||||
ray.y -= dir.y * maxDist * 2.4;
|
|
||||||
|
|
||||||
ray.x += dir.x * ((maxDist - dist) * 2.8);
|
|
||||||
ray.y += dir.y * ((maxDist - dist) * 2.8);
|
|
||||||
|
|
||||||
points.push(new Vec2(ray.x * 4, ray.y * 4));
|
|
||||||
}
|
|
||||||
|
|
||||||
let poly = new Phaser.GameObjects.Polygon(this.scene, token.x / 4, token.y / 4, points, 0xffffff, 0.4);
|
|
||||||
poly.setScale(4, 4);
|
|
||||||
poly.setBlendMode('ERASE');
|
|
||||||
poly.setDisplayOrigin(0, 0);
|
|
||||||
poly.setOrigin(0, 0);
|
|
||||||
|
|
||||||
for (let i = 0; i < 10; i++) {
|
|
||||||
poly.scaleX += 0.04;
|
|
||||||
poly.scaleY += 0.04;
|
|
||||||
// poly.x = token.x / 4 + 50 * poly.scaleX;
|
|
||||||
// poly.y = token.y / 4 + 50 * poly.scaleY;
|
|
||||||
this.tex.draw(poly);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,76 +0,0 @@
|
|||||||
class MapScene extends Phaser.Scene {
|
|
||||||
i: InputManager;
|
|
||||||
|
|
||||||
history: HistoryManager;
|
|
||||||
|
|
||||||
architect: ArchitectMode;
|
|
||||||
token: TokenMode;
|
|
||||||
|
|
||||||
world: WorldView;
|
|
||||||
map: Tilemap;
|
|
||||||
ui: UIView;
|
|
||||||
|
|
||||||
fog: FogOfWar;
|
|
||||||
|
|
||||||
mode: number = 0;
|
|
||||||
tokens: Token[] = [];
|
|
||||||
|
|
||||||
constructor() { super({key: "MapScene"}); }
|
|
||||||
|
|
||||||
preload(): void {
|
|
||||||
window.addEventListener('resize', () => {
|
|
||||||
let frame = document.getElementById("game");
|
|
||||||
this.game.scale.resize(frame.offsetWidth, frame.offsetHeight);
|
|
||||||
// this.chat.x = -10000 + this.cameras.main.width - 309;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
create(): void {
|
|
||||||
this.i = new InputManager(this);
|
|
||||||
|
|
||||||
(<Phaser.Renderer.WebGL.WebGLRenderer>this.game.renderer).addPipeline('outline', new OutlinePipeline(this.game));
|
|
||||||
(<Phaser.Renderer.WebGL.WebGLRenderer>this.game.renderer).addPipeline('brighten', new BrightenPipeline(this.game));
|
|
||||||
|
|
||||||
this.history = new HistoryManager(this);
|
|
||||||
|
|
||||||
this.world = new WorldView(this);
|
|
||||||
this.ui = new UIView(this);
|
|
||||||
this.ui.createElements();
|
|
||||||
|
|
||||||
this.map = new Tilemap("gameMap", this, 300, 300);
|
|
||||||
|
|
||||||
this.architect = new ArchitectMode(this);
|
|
||||||
this.token = new TokenMode(this);
|
|
||||||
|
|
||||||
this.fog = new FogOfWar(this, new Vec2(300, 300));
|
|
||||||
}
|
|
||||||
|
|
||||||
update(time: number, delta: number): void {
|
|
||||||
this.i.update();
|
|
||||||
|
|
||||||
this.world.update();
|
|
||||||
this.ui.update();
|
|
||||||
// this.chat.update();
|
|
||||||
this.history.update();
|
|
||||||
|
|
||||||
this.fog.update();
|
|
||||||
|
|
||||||
if (this.i.keyPressed('TAB')) this.mode = (this.mode == 0 ? 1 : 0);
|
|
||||||
|
|
||||||
if (this.mode == 0) {
|
|
||||||
if (this.ui.uiActive) this.architect.cleanup();
|
|
||||||
else {
|
|
||||||
this.architect.update();
|
|
||||||
this.token.cleanup();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (this.ui.uiActive) this.token.cleanup();
|
|
||||||
else {
|
|
||||||
this.token.update();
|
|
||||||
this.architect.cleanup();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,183 +0,0 @@
|
|||||||
class Tilemap {
|
|
||||||
scene: MapScene;
|
|
||||||
map: Phaser.Tilemaps.Tilemap;
|
|
||||||
dimensions: Vec2 = new Vec2();
|
|
||||||
|
|
||||||
manager: TilesetManager;
|
|
||||||
layers: {[key: number]: Phaser.Tilemaps.DynamicTilemapLayer[]} = {};
|
|
||||||
|
|
||||||
groundAt: number[][];
|
|
||||||
wallAt: number[][];
|
|
||||||
overlayAt: number[][];
|
|
||||||
|
|
||||||
constructor(key: string, scene: MapScene, xwid: number, ywid: number) {
|
|
||||||
this.scene = scene;
|
|
||||||
this.dimensions = new Vec2(xwid, ywid);
|
|
||||||
|
|
||||||
this.groundAt = [];
|
|
||||||
this.wallAt = [];
|
|
||||||
this.overlayAt = [];
|
|
||||||
for (let i = 0; i < xwid; i++) {
|
|
||||||
this.groundAt[i] = [];
|
|
||||||
this.wallAt[i] = [];
|
|
||||||
this.overlayAt[i] = [];
|
|
||||||
for (let j = 0; j < ywid; j++) {
|
|
||||||
this.groundAt[i][j] = -1;
|
|
||||||
this.wallAt[i][j] = -1;
|
|
||||||
this.overlayAt[i][j] = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.manager = new TilesetManager(scene);
|
|
||||||
|
|
||||||
this.map = this.scene.add.tilemap(null, 16, 16, 0, 0);
|
|
||||||
|
|
||||||
for (let res of this.manager.resolutions()) this.createLayers(parseInt(res));
|
|
||||||
|
|
||||||
for (let x = 0; x < this.dimensions.x; x ++) {
|
|
||||||
for (let y = 0; y < this.dimensions.y; y ++) {
|
|
||||||
this.setTileRaw(x, y, 1, 54 + Math.floor(Math.random() * 6), Layer.GROUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.map.addTilesetImage("grid_tile", "grid_tile", 16, 16, 0, 0);
|
|
||||||
this.map.setLayer("grid");
|
|
||||||
let gridlayer = this.map.createBlankDynamicLayer("grid", "grid_tile", 0, 0, this.dimensions.x, this.dimensions.y, 16, 16);
|
|
||||||
gridlayer.setScale(4, 4);
|
|
||||||
gridlayer.setDepth(500);
|
|
||||||
for (let i = 0; i < xwid; i++) {
|
|
||||||
for (let j = 0; j < ywid; j++) {
|
|
||||||
if ((j % 2 == 0 && i % 2 == 0) || (j % 2 != 0 && i % 2 != 0)) gridlayer.putTileAt(0, i, j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private createLayers(res: number) {
|
|
||||||
this.map.addTilesetImage("tileset_" + res + "_ground", "tileset_" + res + "_ground", res, res, 2, 4);
|
|
||||||
this.map.addTilesetImage("tileset_" + res + "_wall", "tileset_" + res + "_wall", res, res, 2, 4);
|
|
||||||
this.map.addTilesetImage("tileset_" + res + "_overlay", "tileset_" + res + "_overlay", res, res, 2, 4);
|
|
||||||
|
|
||||||
this.map.setLayer("layer_" + res + "_ground");
|
|
||||||
let ground = this.map.createBlankDynamicLayer("layer_" + res + "_ground",
|
|
||||||
"tileset_" + res + "_ground", 0, 0, this.dimensions.x, this.dimensions.y, res, res);
|
|
||||||
ground.setScale(4 / (res / 16), 4 / (res / 16));
|
|
||||||
ground.setDepth(-1500 + res);
|
|
||||||
|
|
||||||
this.map.setLayer("layer_" + res + "_overlay");
|
|
||||||
let overlay = this.map.createBlankDynamicLayer("layer_" + res + "_overlay",
|
|
||||||
"tileset_" + res + "_overlay", 0, 0, this.dimensions.x, this.dimensions.y, res, res);
|
|
||||||
overlay.setScale(4 / (res / 16), 4 / (res / 16));
|
|
||||||
overlay.setDepth(-1000 + res);
|
|
||||||
|
|
||||||
this.map.setLayer("layer_" + res + "_wall");
|
|
||||||
let wall = this.map.createBlankDynamicLayer("layer_" + res + "_wall",
|
|
||||||
"tileset_" + res + "_wall", 0, 0, this.dimensions.x, this.dimensions.y, res, res);
|
|
||||||
wall.setScale(4 / (res / 16), 4 / (res / 16));
|
|
||||||
wall.setDepth(-500 + res);
|
|
||||||
|
|
||||||
this.layers[res] = [ground, wall, overlay];
|
|
||||||
}
|
|
||||||
|
|
||||||
getWall(x: number, y: number): number {
|
|
||||||
return this.wallAt[clamp(x, 0, this.dimensions.x - 1)][clamp(y, 0, this.dimensions.y - 1)];
|
|
||||||
}
|
|
||||||
|
|
||||||
setWall(x: number, y: number, tileset: number): boolean {
|
|
||||||
return this.setTile(x, y, tileset, Layer.WALL);
|
|
||||||
}
|
|
||||||
|
|
||||||
getGround(x: number, y: number): number {
|
|
||||||
return this.groundAt[clamp(x, 0, this.dimensions.x - 1)][clamp(y, 0, this.dimensions.y - 1)];
|
|
||||||
}
|
|
||||||
|
|
||||||
setGround(x: number, y: number, tileset: number): boolean {
|
|
||||||
return this.setTile(x, y, tileset, Layer.GROUND);
|
|
||||||
}
|
|
||||||
|
|
||||||
getOverlay(x: number, y: number): number {
|
|
||||||
return this.overlayAt[clamp(x, 0, this.dimensions.x - 1)][clamp(y, 0, this.dimensions.y - 1)];
|
|
||||||
}
|
|
||||||
|
|
||||||
setOverlay(x: number, y: number, tileset: number): boolean {
|
|
||||||
return this.setTile(x, y, tileset, Layer.OVERLAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
getTile(x: number, y: number, layer: Layer) {
|
|
||||||
return (layer == Layer.WALL ? this.getWall(x, y) : layer == Layer.GROUND ? this.getGround(x, y) : this.getOverlay(x, y));
|
|
||||||
}
|
|
||||||
|
|
||||||
setTile(x: number, y: number, tileset: number, layer: Layer): boolean {
|
|
||||||
if (x < 0 || y < 0 || x > this.dimensions.x - 1 || y > this.dimensions.y - 1) return false;
|
|
||||||
|
|
||||||
let arr = (layer == Layer.GROUND ? this.groundAt : layer == Layer.WALL ? this.wallAt : this.overlayAt);
|
|
||||||
if (arr[x][y] == tileset) return false;
|
|
||||||
|
|
||||||
if (arr[x][y] != -1) {
|
|
||||||
this.layers[this.manager.getTilesetRes(arr[x][y], layer)][layer].removeTileAt(x, y, true);
|
|
||||||
arr[x][y] = -1;
|
|
||||||
}
|
|
||||||
if (tileset != -1) this.layers[this.manager.getTilesetRes(tileset, layer)][layer].putTileAt(
|
|
||||||
this.manager.getGlobalTileIndex(tileset, 0, layer), x, y);
|
|
||||||
|
|
||||||
arr[x][y] = tileset;
|
|
||||||
|
|
||||||
this.calculateSmartTilesAround(x, y);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private setTileRaw(x: number, y: number, tileset: number, tile: number, layer: Layer): void {
|
|
||||||
let arr = (layer == Layer.GROUND ? this.groundAt : layer == Layer.WALL ? this.wallAt : this.overlayAt);
|
|
||||||
|
|
||||||
if (arr[x][y] != -1) {
|
|
||||||
this.layers[this.manager.getTilesetRes(arr[x][y], layer)][layer].removeTileAt(x, y, true);
|
|
||||||
arr[x][y] = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
let loc = this.manager.getTilesetRes(tileset, layer);
|
|
||||||
this.layers[loc][layer].putTileAt(this.manager.getGlobalTileIndex(tileset, tile, layer), x, y);
|
|
||||||
arr[x][y] = tileset;
|
|
||||||
}
|
|
||||||
|
|
||||||
private getTileAt(x: number, y: number, layer: number): number {
|
|
||||||
let arr = (layer == Layer.GROUND ? this.groundAt : layer == Layer.WALL ? this.wallAt : this.overlayAt);
|
|
||||||
if (arr[x][y] == -1) return -1;
|
|
||||||
return this.manager.getLocalTileIndex(arr[x][y], this.layers[this.manager.getTilesetRes(arr[x][y], layer)][layer].getTileAt(x, y, true).index, layer);
|
|
||||||
}
|
|
||||||
|
|
||||||
private calculateSmartTilesAround(x: number, y: number): void {
|
|
||||||
for (let i = clamp(x - 1, this.dimensions.x - 1, 0); i <= clamp(x + 1, this.dimensions.x - 1, 0); i++) {
|
|
||||||
for (let j = clamp(y - 1, this.dimensions.y - 1, 0); j <= clamp(y + 1, this.dimensions.y - 1, 0); j++) {
|
|
||||||
|
|
||||||
let wall = SmartTiler.wall(this.getWallsAround(i, j), this.getTileAt(i, j, Layer.WALL));
|
|
||||||
if (wall != -1) this.setTileRaw(i, j, this.wallAt[i][j], wall, Layer.WALL);
|
|
||||||
|
|
||||||
let ground = SmartTiler.ground(this.getWallsAround(i, j), this.getTileAt(i, j, Layer.GROUND));
|
|
||||||
if (ground != -1) this.setTileRaw(i, j, this.groundAt[i][j], ground, Layer.GROUND);
|
|
||||||
|
|
||||||
let overlay = SmartTiler.overlay(this.getOverlaysAround(i, j, this.overlayAt[i][j]), this.getTileAt(i, j, Layer.OVERLAY));
|
|
||||||
if (overlay != -1) this.setTileRaw(i, j, this.overlayAt[i][j], overlay, Layer.OVERLAY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private getWallsAround(x: number, y: number): boolean[] {
|
|
||||||
let solid: boolean[] = [];
|
|
||||||
for (let i = -1; i <= 1; i++) {
|
|
||||||
for (let j = -1; j <= 1; j++) {
|
|
||||||
solid.push(this.getWall(x + j, y + i) != -1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return solid;
|
|
||||||
}
|
|
||||||
|
|
||||||
private getOverlaysAround(x: number, y: number, targetTileset: number): boolean[] {
|
|
||||||
let solid: boolean[] = [];
|
|
||||||
for (let i = -1; i <= 1; i++) {
|
|
||||||
for (let j = -1; j <= 1; j++) {
|
|
||||||
solid.push(this.getOverlay(x + j, y + i) == targetTileset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return solid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,108 +0,0 @@
|
|||||||
class TilesetCanvas {
|
|
||||||
manager: TilesetManager;
|
|
||||||
|
|
||||||
res: number;
|
|
||||||
width: number;
|
|
||||||
height: number;
|
|
||||||
|
|
||||||
canvas: Phaser.Textures.CanvasTexture;
|
|
||||||
|
|
||||||
indexes: number[] = [];
|
|
||||||
indMap: number[] = [];
|
|
||||||
|
|
||||||
pad: number = 2;
|
|
||||||
|
|
||||||
constructor(manager: TilesetManager, res: number, layer: Layer) {
|
|
||||||
this.manager = manager;
|
|
||||||
|
|
||||||
this.res = res;
|
|
||||||
this.width = Math.floor(1024 / ((this.res + this.pad * 2) * 9));
|
|
||||||
this.height = Math.floor(1024 / ((this.res + this.pad * 2) * 7));
|
|
||||||
|
|
||||||
this.canvas = manager.scene.textures.createCanvas("tileset_" + res +
|
|
||||||
(layer == Layer.WALL ? "_wall" : layer == Layer.GROUND ? "_ground" : "_overlay"),
|
|
||||||
this.width * 9 * (this.res + this.pad * 2), this.height * 7 * (this.res + this.pad * 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
addTileset(key: string, ind: number) {
|
|
||||||
const x = this.indexes.length % this.width;
|
|
||||||
const y = Math.floor(this.indexes.length / this.width);
|
|
||||||
|
|
||||||
this.drawTileset(key, x, y);
|
|
||||||
this.indMap[ind] = this.indexes.length;
|
|
||||||
this.indexes.push(ind);
|
|
||||||
}
|
|
||||||
|
|
||||||
getGlobalIndex(tileset: number, tile: number) {
|
|
||||||
const lX = tile % 9;
|
|
||||||
const lY = Math.floor(tile / 9);
|
|
||||||
const gX = tileset % this.width;
|
|
||||||
const gY = Math.floor(tileset / this.width);
|
|
||||||
|
|
||||||
const xx = lX + gX * 9;
|
|
||||||
const yy = lY + gY * 9;
|
|
||||||
|
|
||||||
return yy * this.width * 9 + xx;
|
|
||||||
}
|
|
||||||
|
|
||||||
getLocalIndex(tile: number): number {
|
|
||||||
const gX = tile % (this.width * 9);
|
|
||||||
const gY = Math.floor(tile / (this.width * 9));
|
|
||||||
|
|
||||||
const lX = gX % 9;
|
|
||||||
const lY = gY % 7;
|
|
||||||
|
|
||||||
return lX + lY * 9;
|
|
||||||
}
|
|
||||||
|
|
||||||
private drawTileset(key: string, x: number, y: number) {
|
|
||||||
let img: HTMLImageElement = this.manager.scene.textures.get(key).getSourceImage() as HTMLImageElement;
|
|
||||||
let refCanvas = document.createElement('canvas');
|
|
||||||
refCanvas.width = img.width;
|
|
||||||
refCanvas.height = img.height;
|
|
||||||
refCanvas.getContext('2d').drawImage(img, 0, 0, img.width, img.height);
|
|
||||||
|
|
||||||
let imageOffX = 9 * (this.res + this.pad * 2) * x;
|
|
||||||
let imageOffY = 7 * (this.res + this.pad * 2) * y;
|
|
||||||
|
|
||||||
for (let i = 0; i < 9; i++) {
|
|
||||||
for (let j = 0; j < 7; j++) {
|
|
||||||
let frame = i + j * 9;
|
|
||||||
|
|
||||||
let tileOffX = imageOffX + i * (this.res + this.pad * 2);
|
|
||||||
let tileOffY = imageOffY + j * (this.res + this.pad * 2);
|
|
||||||
|
|
||||||
for (let k = 0; k < this.res + this.pad * 2; k++) {
|
|
||||||
for (let l = 0; l < this.pad * 2; l++) {
|
|
||||||
|
|
||||||
let sX = clamp(k - this.pad, 0, this.res - 1);
|
|
||||||
let sY = l < this.pad ? 0 : this.res - 1;
|
|
||||||
let oY = l < this.pad ? l : l + this.res;
|
|
||||||
|
|
||||||
let pixel = refCanvas.getContext('2d').getImageData(this.res * i + sX, this.res * j + sY, 1, 1).data;
|
|
||||||
this.canvas.setPixel(tileOffX + k, tileOffY + oY, pixel[0], pixel[1], pixel[2], pixel[3]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let k = 0; k < this.pad * 2; k++) {
|
|
||||||
for (let l = 0; l < this.res; l++) {
|
|
||||||
|
|
||||||
let sX = k < this.pad ? 0 : this.res - 1;
|
|
||||||
let sY = clamp(l, 0, this.res - 1);
|
|
||||||
let oX = k < this.pad ? k : k + this.res;
|
|
||||||
|
|
||||||
let pixel = refCanvas.getContext('2d').getImageData(this.res * i + sX, this.res * j + sY, 1, 1).data;
|
|
||||||
this.canvas.setPixel(tileOffX + oX, tileOffY + l + this.pad, pixel[0], pixel[1], pixel[2], pixel[3]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.canvas.drawFrame(key, frame,
|
|
||||||
9 * (this.res + this.pad * 2) * x + i * (this.res + this.pad * 2) + this.pad,
|
|
||||||
7 * (this.res + this.pad * 2) * y + j * (this.res + this.pad * 2) + this.pad)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
refCanvas.remove();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
const enum Layer {
|
|
||||||
GROUND = 0,
|
|
||||||
WALL = 1,
|
|
||||||
OVERLAY = 2
|
|
||||||
}
|
|
||||||
|
|
||||||
class TilesetManager {
|
|
||||||
scene: MapScene;
|
|
||||||
|
|
||||||
private currentWallInd: number = 0;
|
|
||||||
private currentGroundInd: number = 0;
|
|
||||||
private currentOverlayInd: number = 0;
|
|
||||||
|
|
||||||
private wallLocations: {[key: number /*Index*/]: { res: number, ind: number, key: string }} = {};
|
|
||||||
private groundLocations: {[key: number /*Index*/]: { res: number, ind: number, key: string }} = {};
|
|
||||||
private overlayLocations: {[key: number /*Index*/]: { res: number, ind: number, key: string }} = {};
|
|
||||||
private canvases: {[key: number /*Resolution*/]: TilesetCanvas[] } = {};
|
|
||||||
|
|
||||||
indexes: {[key: string /*Tileset Key*/]: number} = {};
|
|
||||||
|
|
||||||
constructor(scene: MapScene) {
|
|
||||||
this.scene = scene;
|
|
||||||
|
|
||||||
for (let tileset of WALLS ) this.addTileset(tileset.key, Layer.WALL);
|
|
||||||
for (let tileset of GROUNDS) this.addTileset(tileset.key, Layer.GROUND);
|
|
||||||
for (let tileset of OVERLAYS) this.addTileset(tileset.key, Layer.OVERLAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
private addTileset(key: string, layer: Layer): void {
|
|
||||||
let res = this.scene.textures.get(key).getSourceImage(0).width / 9;
|
|
||||||
|
|
||||||
if (this.canvases[res] == undefined)
|
|
||||||
this.canvases[res] = [ new TilesetCanvas(this, res, Layer.GROUND), new TilesetCanvas(this, res, Layer.WALL), new TilesetCanvas(this, res, Layer.OVERLAY) ];
|
|
||||||
|
|
||||||
let ind = (layer == Layer.WALL ? this.currentWallInd : layer == Layer.GROUND ? this.currentGroundInd : this.currentOverlayInd);
|
|
||||||
let canvas = this.canvases[res];
|
|
||||||
this[layer == Layer.WALL ? "wallLocations" : layer == Layer.GROUND ? "groundLocations" : "overlayLocations"][ind] = { res: res, ind: ind, key: key };
|
|
||||||
this.indexes[key] = ind;
|
|
||||||
canvas[layer].addTileset(key, ind);
|
|
||||||
|
|
||||||
layer == Layer.WALL ? this.currentWallInd++ :
|
|
||||||
layer == Layer.GROUND ? this.currentGroundInd++ :
|
|
||||||
this.currentOverlayInd++;
|
|
||||||
}
|
|
||||||
|
|
||||||
resolutions(): string[] {
|
|
||||||
let resList: string[] = [];
|
|
||||||
for (let res of Object.keys(this.canvases)) resList.push(res);
|
|
||||||
return resList;
|
|
||||||
}
|
|
||||||
|
|
||||||
getTilesetRes(tileset: number, layer: Layer): number {
|
|
||||||
return layer == Layer.WALL ? this.wallLocations[tileset].res
|
|
||||||
: layer == Layer.GROUND ? this.groundLocations[tileset].res
|
|
||||||
: this.overlayLocations[tileset].res;
|
|
||||||
}
|
|
||||||
|
|
||||||
getGlobalTileIndex(tileset: number, tile: number, layer: Layer): number {
|
|
||||||
return this.canvases[this.getTilesetRes(tileset, layer)][layer].getGlobalIndex(tileset, tile);
|
|
||||||
}
|
|
||||||
|
|
||||||
getLocalTileIndex(tileset: number, tile: number, layer: Layer): number {
|
|
||||||
return this.canvases[this.getTilesetRes(tileset, layer)][layer].getLocalIndex(tile);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
|
"lib": "es6",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "es5",
|
"target": "es6",
|
||||||
"rootDirs": [
|
"rootDirs": [
|
||||||
"src/",
|
"src/",
|
||||||
"src/*"
|
"src/*"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user