feat(objects/room): RoomTileMap accuracy & adjustements

This commit is contained in:
Walid 2023-07-23 17:41:57 +01:00
parent f82de52fda
commit c217245058
Signed by: Walidoux
GPG Key ID: CCF21881FE8BEBAF
3 changed files with 284 additions and 332 deletions

14
TODO.md Normal file
View File

@ -0,0 +1,14 @@
# 🏁 To-do's
## Rooms
- [ ] Jaaj
## 🐛 Patch Notes
- Door walls: In order for the game to render the top-front wall of a door, it needs to make sure that the tile is actually a door in the first place, then it needs to check if the two neighboor tiles have walls too.
- Duplicate doors: If it appears to be more than one door in a single room the game logic will pick the first one in a concurrent way.
## 🧹 Refactors
- Look for `hasWall` method that has O(n²) loop conditionals, and fix enum `WallType` type condition in `RoomTileMap`

View File

@ -1,7 +1,7 @@
import type { IPosition2D, ITileInfo, TileMap } from '../../types/Room'; import type { IPosition2D, ITileInfo, TileMap } from '../../types/Room'
import { WallType } from '../../enums/WallType'; import { WallType } from '../../enums/WallType'
import { StairType } from '../../enums/StairType'; import { StairType } from '../../enums/StairType'
import { Direction } from '../../enums/Direction'; import { Direction } from '../../enums/Direction'
/** /**
* RoomTileMap class that manage all the things about the room model. * RoomTileMap class that manage all the things about the room model.
@ -16,14 +16,14 @@ export class RoomTileMap {
* @member {TileMap} * @member {TileMap}
* @private * @private
*/ */
private readonly _tileMap: TileMap; private readonly _tileMap: TileMap
/** /**
* @param {string} [tileMap] - The room tile map string that need to be parsed. * @param {string} [tileMap] - The room tile map string that need to be parsed.
*/ */
constructor(tileMap: string) { constructor(tileMap: string) {
/** Parse the tile map string to convert it into a matrix */ /** Parse the tile map string to convert it into a matrix */
this._tileMap = this._parse(tileMap); this._tileMap = this._parse(tileMap)
} }
/** /**
@ -34,11 +34,11 @@ export class RoomTileMap {
* @private * @private
*/ */
private _parse(tileMap: string): TileMap { private _parse(tileMap: string): TileMap {
tileMap = tileMap.replace(/ /g, ''); tileMap = tileMap.replace(/ /g, '')
tileMap = tileMap.replace(/\n\n/g, '\n'); tileMap = tileMap.replace(/\n\n/g, '\n')
return tileMap.split(/\r?\n/).map((line) => { return tileMap.split(/\r?\n/).map((line) => {
return line.split(''); return line.split('')
}); })
} }
/** /**
@ -49,7 +49,7 @@ export class RoomTileMap {
* @public * @public
*/ */
public get tileMap(): TileMap { public get tileMap(): TileMap {
return this._tileMap; return this._tileMap
} }
/** /**
@ -65,7 +65,7 @@ export class RoomTileMap {
this._tileMap[position.y] === undefined || this._tileMap[position.y] === undefined ||
this._tileMap[position.y][position.x] === undefined this._tileMap[position.y][position.x] === undefined
? 'x' ? 'x'
: this._tileMap[position.y][position.x]; : this._tileMap[position.y][position.x]
} }
/** /**
@ -76,8 +76,8 @@ export class RoomTileMap {
* @public * @public
*/ */
public getTileHeight(position: IPosition2D): number { public getTileHeight(position: IPosition2D): number {
const tile = this.getTile(position); const tile = this.getTile(position)
return tile === 'x' ? 0 : isNaN(Number(tile)) ? tile.charCodeAt(0) - 96 + 9 : Number(tile); return tile === 'x' ? 0 : isNaN(Number(tile)) ? tile.charCodeAt(0) - 96 + 9 : Number(tile)
} }
/** /**
@ -94,7 +94,7 @@ export class RoomTileMap {
height: this.getTileHeight(position), height: this.getTileHeight(position),
stairType: this._getStairType(position), stairType: this._getStairType(position),
wallType: this._getWallType(position) wallType: this._getWallType(position)
}; }
} }
/** /**
@ -105,16 +105,26 @@ export class RoomTileMap {
* @private * @private
*/ */
private _getWallType(position: IPosition2D): WallType | undefined { private _getWallType(position: IPosition2D): WallType | undefined {
const topLeftTile: IPosition2D = { x: position.x - 1, y: position.y - 1 }; const tiles = {
const topTile: IPosition2D = { x: position.x, y: position.y - 1 }; topLeft: { x: position.x - 1, y: position.y - 1 },
const midLeftTile: IPosition2D = { x: position.x - 1, y: position.y }; leftMid: { x: position.x, y: position.y - 1 },
topMid: { x: position.x - 1, y: position.y }
}
if (this.isDoor(position)) return; if (this.isDoor(position)) return
if (!this.isTile(topLeftTile) && !this.isTile(topTile) && !this.isTile(midLeftTile) && this.isTile(position)) if (this.isDoor({ ...position, x: position.x - 1 })) return WallType.DOOR_WALL
return WallType.CORNER_WALL;
if (!this.isTile(midLeftTile) && this.isTile(position)) return WallType.LEFT_WALL; if (
if (!this.isTile(topTile) && this.isTile(position)) return WallType.RIGHT_WALL; !this.isTile(tiles.topLeft) &&
!this.isTile(tiles.leftMid) &&
!this.isTile(tiles.topMid) &&
this.isTile(position)
)
return WallType.CORNER_WALL
if (!this.isTile(tiles.topMid) && this.isTile(position) && !this.hasWall('x', position)) return WallType.LEFT_WALL
if (!this.isTile(tiles.leftMid) && this.isTile(position) && !this.hasWall('x', { ...position, y: position.y - 1 }))
return WallType.RIGHT_WALL
} }
/** /**
@ -125,89 +135,89 @@ export class RoomTileMap {
* @private * @private
*/ */
private _getStairType(position: IPosition2D): { type: StairType; direction: Direction } | undefined { private _getStairType(position: IPosition2D): { type: StairType; direction: Direction } | undefined {
const topLeftTile: IPosition2D = { x: position.x - 1, y: position.y - 1 }; const tiles = {
const topTile: IPosition2D = { x: position.x, y: position.y - 1 }; topLeft: { x: position.x - 1, y: position.y - 1 },
const topRightTile: IPosition2D = { x: position.x + 1, y: position.y - 1 }; topMid: { x: position.x, y: position.y - 1 },
topRight: { x: position.x + 1, y: position.y - 1 },
const midLeftTile: IPosition2D = { x: position.x - 1, y: position.y }; midLeft: { x: position.x - 1, y: position.y },
const midRightTile: IPosition2D = { x: position.x + 1, y: position.y }; midRight: { x: position.x + 1, y: position.y },
botLeft: { x: position.x - 1, y: position.y + 1 },
const botLeftTile: IPosition2D = { x: position.x - 1, y: position.y + 1 }; botMid: { x: position.x, y: position.y + 1 },
const botTile: IPosition2D = { x: position.x, y: position.y + 1 }; botRight: { x: position.x + 1, y: position.y + 1 }
const botRightTile: IPosition2D = { x: position.x + 1, y: position.y + 1 }; }
if ( if (
this.isTile(position) && this.isTile(position) &&
this.isTile(topRightTile) && this.isTile(tiles.topRight) &&
this._getTileDifference(topRightTile, position) === 1 && this._getTileDifference(tiles.topRight, position) === 1 &&
this._getTileDifference(midRightTile, position) === 1 && this._getTileDifference(tiles.midRight, position) === 1 &&
this._getTileDifference(topTile, position) === 1 this._getTileDifference(tiles.topMid, position) === 1
) )
return { type: StairType.INNER_CORNER_STAIR, direction: Direction.NORTH_EAST }; return { type: StairType.INNER_CORNER_STAIR, direction: Direction.NORTH_EAST }
if ( if (
this.isTile(position) && this.isTile(position) &&
this.isTile(botRightTile) && this.isTile(tiles.botRight) &&
this._getTileDifference(botRightTile, position) === 1 && this._getTileDifference(tiles.botRight, position) === 1 &&
this._getTileDifference(midRightTile, position) === 1 && this._getTileDifference(tiles.midRight, position) === 1 &&
this._getTileDifference(botTile, position) === 1 this._getTileDifference(tiles.botMid, position) === 1
) )
return { type: StairType.INNER_CORNER_STAIR, direction: Direction.SOUTH_EAST }; return { type: StairType.INNER_CORNER_STAIR, direction: Direction.SOUTH_EAST }
if ( if (
this.isTile(position) && this.isTile(position) &&
this.isTile(botLeftTile) && this.isTile(tiles.botLeft) &&
this._getTileDifference(botLeftTile, position) === 1 && this._getTileDifference(tiles.botLeft, position) === 1 &&
this._getTileDifference(midLeftTile, position) === 1 && this._getTileDifference(tiles.midLeft, position) === 1 &&
this._getTileDifference(botTile, position) === 1 this._getTileDifference(tiles.botMid, position) === 1
) )
return { type: StairType.INNER_CORNER_STAIR, direction: Direction.SOUTH_WEST }; return { type: StairType.INNER_CORNER_STAIR, direction: Direction.SOUTH_WEST }
if ( if (
this.isTile(position) && this.isTile(position) &&
this.isTile(topLeftTile) && this.isTile(tiles.topLeft) &&
this._getTileDifference(topLeftTile, position) === 1 && this._getTileDifference(tiles.topLeft, position) === 1 &&
this._getTileDifference(midLeftTile, position) === 1 && this._getTileDifference(tiles.midLeft, position) === 1 &&
this._getTileDifference(topTile, position) === 1 this._getTileDifference(tiles.topMid, position) === 1
) )
return { type: StairType.INNER_CORNER_STAIR, direction: Direction.NORTH_WEST }; return { type: StairType.INNER_CORNER_STAIR, direction: Direction.NORTH_WEST }
if (this.isTile(position) && this.isTile(topTile) && this._getTileDifference(topTile, position) === 1) if (this.isTile(position) && this.isTile(tiles.topMid) && this._getTileDifference(tiles.topMid, position) === 1)
return { type: StairType.STAIR, direction: Direction.NORTH }; return { type: StairType.STAIR, direction: Direction.NORTH }
if ( if (
this.isTile(position) && this.isTile(position) &&
this.isTile(topRightTile) && this.isTile(tiles.topRight) &&
this._getTileDifference(topRightTile, position) === 1 && this._getTileDifference(tiles.topRight, position) === 1 &&
this._getTileDifference(midRightTile, position) === 0 && this._getTileDifference(tiles.midRight, position) === 0 &&
this._getTileDifference(topTile, position) === 0 this._getTileDifference(tiles.topMid, position) === 0
) )
return { type: StairType.OUTER_CORNER_STAIR, direction: Direction.NORTH_EAST }; return { type: StairType.OUTER_CORNER_STAIR, direction: Direction.NORTH_EAST }
if (this.isTile(position) && this.isTile(midRightTile) && this._getTileDifference(midRightTile, position) === 1) if (this.isTile(position) && this.isTile(tiles.midRight) && this._getTileDifference(tiles.midRight, position) === 1)
return { type: StairType.STAIR, direction: Direction.EAST }; return { type: StairType.STAIR, direction: Direction.EAST }
if ( if (
this.isTile(position) && this.isTile(position) &&
this.isTile(botRightTile) && this.isTile(tiles.botRight) &&
this._getTileDifference(botRightTile, position) === 1 && this._getTileDifference(tiles.botRight, position) === 1 &&
this._getTileDifference(midRightTile, position) === 0 && this._getTileDifference(tiles.midRight, position) === 0 &&
this._getTileDifference(botTile, position) === 0 this._getTileDifference(tiles.botMid, position) === 0
) )
return { type: StairType.OUTER_CORNER_STAIR, direction: Direction.SOUTH_EAST }; return { type: StairType.OUTER_CORNER_STAIR, direction: Direction.SOUTH_EAST }
if (this.isTile(position) && this.isTile(botTile) && this._getTileDifference(botTile, position) === 1) if (this.isTile(position) && this.isTile(tiles.botMid) && this._getTileDifference(tiles.botMid, position) === 1)
return { type: StairType.STAIR, direction: Direction.SOUTH }; return { type: StairType.STAIR, direction: Direction.SOUTH }
if ( if (
this.isTile(position) && this.isTile(position) &&
this.isTile(botLeftTile) && this.isTile(tiles.botLeft) &&
this._getTileDifference(botLeftTile, position) === 1 && this._getTileDifference(tiles.botLeft, position) === 1 &&
this._getTileDifference(midLeftTile, position) === 0 && this._getTileDifference(tiles.midLeft, position) === 0 &&
this._getTileDifference(botTile, position) === 0 this._getTileDifference(tiles.botMid, position) === 0
) )
return { type: StairType.OUTER_CORNER_STAIR, direction: Direction.SOUTH_WEST }; return { type: StairType.OUTER_CORNER_STAIR, direction: Direction.SOUTH_WEST }
if (this.isTile(position) && this.isTile(midLeftTile) && this._getTileDifference(midLeftTile, position) === 1) if (this.isTile(position) && this.isTile(tiles.midLeft) && this._getTileDifference(tiles.midLeft, position) === 1)
return { type: StairType.STAIR, direction: Direction.WEST }; return { type: StairType.STAIR, direction: Direction.WEST }
if ( if (
this.isTile(position) && this.isTile(position) &&
this.isTile(topLeftTile) && this.isTile(tiles.topLeft) &&
this._getTileDifference(topLeftTile, position) === 1 && this._getTileDifference(tiles.topLeft, position) === 1 &&
this._getTileDifference(midLeftTile, position) === 0 && this._getTileDifference(tiles.midLeft, position) === 0 &&
this._getTileDifference(topTile, position) === 0 this._getTileDifference(tiles.topMid, position) === 0
) )
return { type: StairType.OUTER_CORNER_STAIR, direction: Direction.NORTH_WEST }; return { type: StairType.OUTER_CORNER_STAIR, direction: Direction.NORTH_WEST }
} }
/** /**
@ -219,7 +229,7 @@ export class RoomTileMap {
* @private * @private
*/ */
private _getTileDifference(position1: IPosition2D, position2: IPosition2D): number { private _getTileDifference(position1: IPosition2D, position2: IPosition2D): number {
return Number(this.getTileHeight(position1)) - Number(this.getTileHeight(position2)); return Number(this.getTileHeight(position1)) - Number(this.getTileHeight(position2))
} }
/** /**
@ -230,7 +240,7 @@ export class RoomTileMap {
* @public * @public
*/ */
public isTile(position: IPosition2D): boolean { public isTile(position: IPosition2D): boolean {
return this.getTile(position) !== 'x'; return this.getTile(position) !== 'x'
} }
/** /**
@ -241,23 +251,23 @@ export class RoomTileMap {
* @public * @public
*/ */
public isDoor(position: IPosition2D): boolean { public isDoor(position: IPosition2D): boolean {
const topLeftTile: IPosition2D = { x: position.x - 1, y: position.y - 1 }; const tiles = {
const topTile: IPosition2D = { x: position.x, y: position.y - 1 }; topLeft: { x: position.x - 1, y: position.y - 1 },
topMid: { x: position.x, y: position.y - 1 },
const midLeftTile: IPosition2D = { x: position.x - 1, y: position.y }; midLeft: { x: position.x - 1, y: position.y },
const midTile: IPosition2D = { x: position.x, y: position.y }; mid: { x: position.x, y: position.y },
botLeft: { x: position.x - 1, y: position.y + 1 },
const botLeftTile: IPosition2D = { x: position.x - 1, y: position.y + 1 }; botMid: { x: position.x, y: position.y + 1 }
const botTile: IPosition2D = { x: position.x, y: position.y + 1 }; }
return ( return (
!this.isTile(topTile) && !this.isTile(tiles.topMid) &&
!this.isTile(topLeftTile) && !this.isTile(tiles.topLeft) &&
!this.isTile(midLeftTile) && !this.isTile(tiles.midLeft) &&
!this.isTile(botLeftTile) && !this.isTile(tiles.botLeft) &&
!this.isTile(botTile) && !this.isTile(tiles.botMid) &&
this.isTile(midTile) this.isTile(tiles.mid)
); )
} }
/** /**
@ -267,59 +277,66 @@ export class RoomTileMap {
* @public * @public
*/ */
public get maxZ(): number { public get maxZ(): number {
let z = 0; let z = 0
for (let y = 0; y < this._tileMap.length; y++) { for (let y = 0; y < this._tileMap.length; y++) {
for (let x = 0; x < this._tileMap[y].length; x++) { for (let x = 0; x < this._tileMap[y].length; x++) {
const height = this.getTileHeight({ x, y }); const height = this.getTileHeight({ x, y })
if (height > z) z = height; if (height > z) z = height
} }
} }
return z;
return z
} }
/** /**
* Indicate if the given tile position have a left or a right wall. * Indicate if the given tile position have a left or a right wall.
* *
* @param {IPosition2D} [position] - The given tile position that we wan't to check if it have walls. * @param {IPosition2D} [position] - The given tile position that we wan't to check if it have walls.
* @return {{ x: boolean, y: boolean }} * @return { x: boolean, y: boolean }
* @public * @public
*/ */
public hasWall(position: IPosition2D): { x: boolean; y: boolean } { public hasWall(axis: keyof IPosition2D, position: IPosition2D): boolean {
// TODO: Integrate it in _getWallType() const handleXAxis = (coordinates: IPosition2D): boolean => {
let wallX = false; let wallX = false
let wallY = false;
for (let i = position.y - 1; i >= 0; i--) { for (let i = coordinates.x - 1; i >= 0; i--) {
const wall: WallType | undefined = this._getWallType({ x: position.x, y: i }); const wall = this._getWallType({ x: i, y: coordinates.y })
if (wall) {
if (wall === WallType.RIGHT_WALL || wall === (WallType.CORNER_WALL as WallType)) { if (wall === WallType.LEFT_WALL || wall === WallType.CORNER_WALL) wallX = true
wallY = true;
for (let j = coordinates.y - 1; j >= 0; j--) {
const wall2 = this._getWallType({ x: i, y: j })
if (wall2 === WallType.RIGHT_WALL || wall2 === WallType.CORNER_WALL) wallX = true
} }
} }
for (let j = position.x - 1; j >= 0; j--) {
const wall2: WallType | undefined = this._getWallType({ x: j, y: i }); return wallX
if (wall2) { }
if (wall2 === WallType.LEFT_WALL || wall2 === (WallType.CORNER_WALL as WallType)) {
wallY = true; const handleYAxis = (coordinates: IPosition2D): boolean => {
let wallY = false
for (let i = coordinates.y - 1; i >= 0; i--) {
const wall = this._getWallType({ x: coordinates.x, y: i })
if (wall != null) {
if (wall === WallType.RIGHT_WALL || wall === WallType.CORNER_WALL) wallY = true
}
for (let j = coordinates.x - 1; j >= 0; j--) {
const wall2 = this._getWallType({ x: j, y: i })
if (wall2 != null) {
if (wall2 === WallType.LEFT_WALL || wall2 === WallType.CORNER_WALL) wallY = true
} }
} }
} }
return wallY
} }
for (let i = position.x - 1; i >= 0; i--) {
const wall: WallType | undefined = this._getWallType({ x: i, y: position.y }); if (axis === 'x') return handleXAxis(position)
if (wall) { else return handleYAxis(position)
if (wall === WallType.LEFT_WALL || wall === (WallType.CORNER_WALL as WallType)) {
wallX = true;
}
}
for (let j = position.y - 1; j >= 0; j--) {
const wall2: WallType | undefined = this._getWallType({ x: i, y: j });
if (wall2) {
if (wall2 === WallType.RIGHT_WALL || wall2 === (WallType.CORNER_WALL as WallType)) {
wallX = true;
}
}
}
}
return { x: wallX, y: wallY };
} }
} }

View File

@ -1,15 +1,16 @@
import { Container, Ticker } from 'pixi.js'; import { Container, Ticker } from 'pixi.js'
import type { Room } from './Room'; import type { Room } from './Room'
import type { IPosition3D, ITileInfo } from '../../types/Room'; import type { IPosition3D, ITileInfo } from '../../types/Room'
import { Tile } from './parts/Tile'; import { Tile } from './parts/Tile'
import { Wall } from './parts/Wall'; import { Wall } from './parts/Wall'
import { Stair } from './parts/Stair'; import { Stair } from './parts/Stair'
import { WallType } from '../../enums/WallType'; import { WallType } from '../../enums/WallType'
import type { StairType } from '../../enums/StairType'; import { Cursor } from './parts/Cursor'
import { Cursor } from './parts/Cursor'; import { RoomObjectLayer } from './layers/RoomObjectLayer'
import { RoomObjectLayer } from './layers/RoomObjectLayer'; import { RoomPartLayer } from './layers/RoomPartLayer'
import { RoomPartLayer } from './layers/RoomPartLayer'; import type { RoomPart } from './parts/RoomPart'
import type { EventManager } from '../interactions/EventManager'
/** /**
* RoomView class that manage all the rendering part of the room. * RoomView class that manage all the rendering part of the room.
@ -24,7 +25,7 @@ export class RoomVisualization extends Container {
* @member {Room} * @member {Room}
* @private * @private
*/ */
private readonly _room: Room; private readonly _room: Room
/** /**
* The container that will contains all the objects like avatars or furnitures. * The container that will contains all the objects like avatars or furnitures.
@ -32,7 +33,7 @@ export class RoomVisualization extends Container {
* @member {RoomObjectLayer} * @member {RoomObjectLayer}
* @private * @private
*/ */
private readonly _objectLayer: RoomObjectLayer; private readonly _objectLayer: RoomObjectLayer
/** /**
* The container that will contains all the parts like tiles, walls and stairs. * The container that will contains all the parts like tiles, walls and stairs.
@ -40,7 +41,7 @@ export class RoomVisualization extends Container {
* @member {RoomPartLayer} * @member {RoomPartLayer}
* @private * @private
*/ */
private readonly _partLayer: RoomPartLayer; private readonly _partLayer: RoomPartLayer
/** /**
* List containing all the walls instances. * List containing all the walls instances.
@ -48,7 +49,7 @@ export class RoomVisualization extends Container {
* @member {Wall} * @member {Wall}
* @private * @private
*/ */
private _walls: Wall[] = []; private _walls: Wall[] = []
/** /**
* List containing all the tiles and stairs instances. * List containing all the tiles and stairs instances.
@ -56,15 +57,7 @@ export class RoomVisualization extends Container {
* @member {Tile | Stair} * @member {Tile | Stair}
* @private * @private
*/ */
private _tiles: Array<Tile | Stair> = []; private _tiles: Array<Tile | Stair> = []
/**
* Infos related to the door tile.
*
* @member {ITileInfo}
* @private
*/
private _doorTile!: ITileInfo;
/** /**
* The room tile cursor instance. * The room tile cursor instance.
@ -72,7 +65,7 @@ export class RoomVisualization extends Container {
* @member {Cursor} * @member {Cursor}
* @private * @private
*/ */
private _cursor!: Cursor; private _cursor!: Cursor
/** /**
* The room animation ticker instance that will manage all the objects animations * The room animation ticker instance that will manage all the objects animations
@ -80,24 +73,24 @@ export class RoomVisualization extends Container {
* @member {Ticker} * @member {Ticker}
* @private * @private
*/ */
private readonly _animationTicker = new Ticker(); private readonly _animationTicker = new Ticker()
/** /**
* @param {Room} [room] - The room instance that we want to visualize. * @param {Room} [room] - The room instance that we want to visualize.
*/ */
constructor(room: Room) { constructor(room: Room) {
super(); super()
this._room = room; this._room = room
this._objectLayer = new RoomObjectLayer(this._room); this._objectLayer = new RoomObjectLayer(this._room)
this._partLayer = new RoomPartLayer(this._room); this._partLayer = new RoomPartLayer(this._room)
/** Start the animation ticker */ /** Start the animation ticker */
this._animationTicker.maxFPS = 4; this._animationTicker.maxFPS = 4
this._animationTicker.start(); this._animationTicker.start()
/** Render everything */ /** Render everything */
this._draw(); this._draw()
} }
/** /**
@ -107,18 +100,19 @@ export class RoomVisualization extends Container {
* @private * @private
*/ */
private _draw(): void { private _draw(): void {
this._destroyParts(); this._destroyParts()
this._destroyCursor(); this._destroyCursor()
let doorsCount = 0
for (let y = 0; y < this._room.tileMap.tileMap.length; y++) { for (let y = 0; y < this._room.tileMap.tileMap.length; y++) {
for (let x = 0; x < this._room.tileMap.tileMap[y].length; x++) { for (let x = 0; x < this._room.tileMap.tileMap[y].length; x++) {
const tileInfo = this._room.tileMap.getTileInfo({ x, y }); const tileInfo = this._room.tileMap.getTileInfo({ x, y })
// todo: avoid duplicate tile doors if (tileInfo.door) doorsCount++
if (tileInfo.door && this._doorTile != null) tileInfo.door = false; if (doorsCount > 1) tileInfo.door = false
if (tileInfo.door && this._doorTile == null) this._doorTile = tileInfo;
this._createPart(tileInfo, { x, y, z: tileInfo.height }); this._createPart(tileInfo, { x, y, z: tileInfo.height })
} }
} }
} }
@ -130,9 +124,11 @@ export class RoomVisualization extends Container {
* @private * @private
*/ */
private _destroyParts(): void { private _destroyParts(): void {
[...this._tiles, ...this._walls].forEach((part) => part.destroy()); ;[...this._tiles, ...this._walls].forEach((part) => {
this._tiles = []; return part.destroy()
this._walls = []; })
this._tiles = []
this._walls = []
} }
/** /**
@ -142,7 +138,7 @@ export class RoomVisualization extends Container {
* @private * @private
*/ */
public update(): void { public update(): void {
this._draw(); this._draw()
} }
/** /**
@ -154,39 +150,81 @@ export class RoomVisualization extends Container {
* @private * @private
*/ */
private _createPart(tileInfo: ITileInfo, position: IPosition3D): void { private _createPart(tileInfo: ITileInfo, position: IPosition3D): void {
if (tileInfo.wallType !== null || tileInfo.door) { if (tileInfo.wallType != null) {
if ( if (
tileInfo.wallType === WallType.CORNER_WALL && tileInfo.wallType === WallType.CORNER_WALL &&
!this._room.tileMap.hasWall(position).x && !this._room.tileMap.hasWall('x', position) &&
!this._room.tileMap.hasWall(position).y !this._room.tileMap.hasWall('y', position)
) { ) {
this._createWall(position, WallType.CORNER_WALL); this._createWall(position, WallType.CORNER_WALL)
this._createWall(position, WallType.LEFT_WALL); this._createWall(position, WallType.LEFT_WALL)
this._createWall(position, WallType.RIGHT_WALL); this._createWall(position, WallType.RIGHT_WALL)
} else if (tileInfo.wallType === WallType.CORNER_WALL && !this._room.tileMap.hasWall(position).x) { } else if (tileInfo.wallType === WallType.CORNER_WALL && !this._room.tileMap.hasWall('x', position)) {
this._createWall(position, WallType.LEFT_WALL); this._createWall(position, WallType.LEFT_WALL)
} else if (tileInfo.wallType === WallType.CORNER_WALL && !this._room.tileMap.hasWall(position).y) { } else if (tileInfo.wallType === WallType.CORNER_WALL && !this._room.tileMap.hasWall('y', position)) {
this._createWall(position, WallType.RIGHT_WALL); this._createWall(position, WallType.RIGHT_WALL)
} }
if (tileInfo.wallType === WallType.LEFT_WALL && !this._room.tileMap.hasWall(position).y) if (tileInfo.wallType === WallType.LEFT_WALL) this._createWall(position, WallType.LEFT_WALL)
this._createWall(position, WallType.LEFT_WALL); if (tileInfo.wallType === WallType.RIGHT_WALL) this._createWall(position, WallType.RIGHT_WALL)
if (tileInfo.wallType === WallType.RIGHT_WALL && !this._room.tileMap.hasWall(position).y)
this._createWall(position, WallType.RIGHT_WALL);
if (tileInfo.door) this._createWall(position, WallType.DOOR_WALL); if (tileInfo.door) this._createWall(position, WallType.DOOR_WALL)
} }
if (tileInfo.stairType != null) { if (tileInfo.stairType != null) {
position.direction = tileInfo.stairType.direction; position.direction = tileInfo.stairType.direction
this._createStair(position, tileInfo.stairType.type);
} else if (tileInfo.door) { const stair = new Stair(this._room, {
this._createDoor(position); position,
} else if (tileInfo.tile) { material: this._room.floorMaterial,
this._createTile(position, tileInfo); thickness: this._room.floorThickness,
type: tileInfo.stairType.type
})
this._createTile(stair, this._partLayer.tiles)
this._tiles.push(stair)
} else if (tileInfo.tile || tileInfo.door) {
const tile = new Tile(
this._room,
{
position,
material: this._room.floorMaterial,
thickness: !tileInfo.door ? this._room.floorThickness : undefined
},
!tileInfo.door ? tileInfo : undefined
)
this._createTile(tile, this._partLayer.tiles)
this._tiles.push(tile)
} }
} }
/**
* Creates a (tile|stair|door).
*
* @param {RoomPart} [part] - The room (tile|stair|door)'s position.
* @param {EventManager} [eventManager]
* @return {void}
* @private
*/
private _createTile(part: RoomPart, eventManager: EventManager): void {
part.onPointerDown = (event) => eventManager.onPointerDown != null && eventManager.onPointerDown(event)
part.onPointerUp = (event) => eventManager.onPointerUp != null && eventManager.onPointerUp(event)
part.onPointerMove = (event) => eventManager.onPointerMove != null && eventManager.onPointerMove(event)
part.onDoubleClick = (event) => eventManager.onDoubleClick != null && eventManager.onDoubleClick(event)
part.onPointerOut = (event) => {
if (eventManager.onPointerOut != null) eventManager.onPointerOut(event)
this._destroyCursor()
}
part.onPointerOver = (event) => {
if (eventManager.onPointerOver != null) eventManager.onPointerOver(event)
this._createCursor(part._position)
}
this.addChild(part)
}
/** /**
* Destroy the current cursor and draw a new one at the new position. * Destroy the current cursor and draw a new one at the new position.
* *
@ -195,15 +233,17 @@ export class RoomVisualization extends Container {
* @private * @private
*/ */
private _createCursor(position: IPosition3D): void { private _createCursor(position: IPosition3D): void {
this._destroyCursor()
if (this._cursor != null) { if (this._cursor != null) {
this._cursor.visible = true; this._cursor.visible = true
return this._cursor.moveTo(position); return this._cursor.moveTo(position)
} }
this._destroyCursor(); const cursor = new Cursor(this._room, { position })
const cursor = new Cursor(this._room, { position });
this.addChild(cursor); this.addChild(cursor)
this._cursor = cursor; this._cursor = cursor
} }
/** /**
@ -213,84 +253,7 @@ export class RoomVisualization extends Container {
* @private * @private
*/ */
private _destroyCursor(): void { private _destroyCursor(): void {
if (this._cursor != null) this._cursor.visible = false; if (this._cursor != null) this._cursor.visible = false
}
/**
* Create a tile.
*
* @param {IPosition3D} [position] - The tile position.
* @param {ITileInfo} [tileInfo]
* @return {void}
* @private
*/
private _createTile(position: IPosition3D, tileInfo: ITileInfo): void {
const tile = new Tile(
this._room,
{ position, material: this._room.floorMaterial, thickness: this._room.floorThickness },
tileInfo
);
/** Register interactions */
tile.onPointerDown = (event) => {
if (this._partLayer.tiles.onPointerDown != null) this._partLayer.tiles.onPointerDown(event);
};
tile.onPointerUp = (event) => {
if (this._partLayer.tiles.onPointerUp != null) this._partLayer.tiles.onPointerUp(event);
};
tile.onPointerMove = (event) => {
if (this._partLayer.tiles.onPointerMove != null) this._partLayer.tiles.onPointerMove(event);
};
tile.onPointerOut = (event) => {
if (this._partLayer.tiles.onPointerOut != null) this._partLayer.tiles.onPointerOut(event);
this._destroyCursor();
};
tile.onPointerOver = (event) => {
if (this._partLayer.tiles.onPointerOver != null) this._partLayer.tiles.onPointerOver(event);
this._createCursor(position);
};
tile.onDoubleClick = (event) => {
if (this._partLayer.tiles.onDoubleClick != null) this._partLayer.tiles.onDoubleClick(event);
};
this.addChild(tile);
this._tiles.push(tile);
}
/**
* Create a door.
*
* @param {IPosition3D} [position] - The door position.
* @return {void}
* @private
*/
private _createDoor(position: IPosition3D): void {
const tile = new Tile(this._room, { position, material: this._room.floorMaterial });
/** Register interactions */
tile.onPointerDown = (event) => {
if (this._partLayer.tiles.onPointerDown != null) this._partLayer.tiles.onPointerDown(event);
};
tile.onPointerUp = (event) => {
if (this._partLayer.tiles.onPointerUp != null) this._partLayer.tiles.onPointerUp(event);
};
tile.onPointerMove = (event) => {
if (this._partLayer.tiles.onPointerMove != null) this._partLayer.tiles.onPointerMove(event);
};
tile.onPointerOut = (event) => {
if (this._partLayer.tiles.onPointerOut != null) this._partLayer.tiles.onPointerOut(event);
this._destroyCursor();
};
tile.onPointerOver = (event) => {
if (this._partLayer.tiles.onPointerOver != null) this._partLayer.tiles.onPointerOver(event);
this._createCursor(position);
};
tile.onDoubleClick = (event) => {
if (this._partLayer.tiles.onDoubleClick != null) this._partLayer.tiles.onDoubleClick(event);
};
this.addChild(tile);
this._tiles.push(tile);
} }
/** /**
@ -308,54 +271,12 @@ export class RoomVisualization extends Container {
thickness: this._room.wallThickness, thickness: this._room.wallThickness,
height: this._room.wallHeight, height: this._room.wallHeight,
type type
}); })
// todo!(): register event interactions for walls */ // todo!(): register event interactions for walls */
this.addChild(wall); this.addChild(wall)
this._walls.push(wall); this._walls.push(wall)
}
/**
* Create stairs.
*
* @param {IPosition3D} [position] - The stairs position.
* @param {StairType} [type] - The stairs type.
* @return {void}
* @private
*/
private _createStair(position: IPosition3D, type: StairType): void {
const stair = new Stair(this._room, {
position,
material: this._room.floorMaterial,
thickness: this._room.floorThickness,
type
});
/** Register interactions */
stair.onPointerDown = (event) => {
if (this._partLayer.tiles.onPointerDown != null) this._partLayer.tiles.onPointerDown(event);
};
stair.onPointerUp = (event) => {
if (this._partLayer.tiles.onPointerUp != null) this._partLayer.tiles.onPointerUp(event);
};
stair.onPointerMove = (event) => {
if (this._partLayer.tiles.onPointerMove != null) this._partLayer.tiles.onPointerMove(event);
};
stair.onPointerOut = (event) => {
if (this._partLayer.tiles.onPointerOut != null) this._partLayer.tiles.onPointerOut(event);
this._destroyCursor();
};
stair.onPointerOver = (event) => {
if (this._partLayer.tiles.onPointerOver != null) this._partLayer.tiles.onPointerOver(event);
this._createCursor(position);
};
stair.onDoubleClick = (event) => {
if (this._partLayer.tiles.onDoubleClick != null) this._partLayer.tiles.onDoubleClick(event);
};
this.addChild(stair);
this._tiles.push(stair);
} }
/** /**
@ -366,7 +287,7 @@ export class RoomVisualization extends Container {
* @public * @public
*/ */
public get room(): Room { public get room(): Room {
return this._room; return this._room
} }
/** /**
@ -377,7 +298,7 @@ export class RoomVisualization extends Container {
* @public * @public
*/ */
public get objectLayer(): RoomObjectLayer { public get objectLayer(): RoomObjectLayer {
return this._objectLayer; return this._objectLayer
} }
/** /**
@ -388,7 +309,7 @@ export class RoomVisualization extends Container {
* @public * @public
*/ */
public get partLayer(): RoomPartLayer { public get partLayer(): RoomPartLayer {
return this._partLayer; return this._partLayer
} }
/** /**
@ -399,6 +320,6 @@ export class RoomVisualization extends Container {
* @public * @public
*/ */
public get animationTicker(): Ticker { public get animationTicker(): Ticker {
return this._animationTicker; return this._animationTicker
} }
} }