diff --git a/packages/physics/src/resources/decorators/layer.js b/packages/physics/src/resources/decorators/layer.js index 47e6132..830e682 100644 --- a/packages/physics/src/resources/decorators/layer.js +++ b/packages/physics/src/resources/decorators/layer.js @@ -1,26 +1,66 @@ +import { + Vector, + Vertice, +} from '@avocado/math'; + +import PolygonShape from '../../shape/polygon'; + export default (Layer) => class PhysicsLayer extends Layer { + #tileBodies = []; + + #world; + + addTileBodies() { + if (!this.hasImpassableLayerZero()) { + return; + } + if (!this.#world) { + return; + } + const hulls = this.tiles.indexHulls(0); + if (!hulls.length > 0) { + return; + } + const {tileset} = this; + if (!tileset) { + return; + } + for (let i = 0; i < hulls.length; ++i) { + const scaled = []; + for (let j = 0; j < hulls[i].length; j++) { + scaled.push(Vector.mul(hulls[i][j], tileset.tileSize)); + } + const [vertices, position] = Vertice.localize(scaled); + const shape = new PolygonShape({position, vertices}); + const body = this.#world.createBody(shape); + body.static = true; + this.#tileBodies.push(body); + this.#world.addBody(body); + } + } + + hasImpassableLayerZero() { + return 1 === this.index; + } + + removeTileBodies() { + if (!this.hasImpassableLayerZero()) { + return; + } + if (this.#tileBodies.length > 0 && this.#world) { + for (let i = 0; i < this.#tileBodies.length; i++) { + this.#world.removeBody(this.#tileBodies[i]); + } + } + this.#tileBodies = []; + } + set world(world) { + this.#world = world; this.entityList.world = world; - // const tileset = this.tileset; - // if (!tileset) { - // return false; - // } - // const halfTileSize = Vector.scale(tileset.tileSize, 0.5); - // this.tiles.forEachTile((tile, x, y, i) => { - // const shape = this.tileset.geometry(tile); - // if (!shape) { - // return; - // } - // shape.position = Vector.add( - // halfTileSize, - // Vector.mul([x, y], tileset.tileSize), - // ); - // const body = world.createBody(shape); - // body.static = true; - // world.addBody(body); - // this.tileGeometry.push(body); - // }); + this.removeTileBodies(); + this.addTileBodies(); } }; diff --git a/packages/physics/src/resources/decorators/layers.js b/packages/physics/src/resources/decorators/layers.js index f04de17..8086d10 100644 --- a/packages/physics/src/resources/decorators/layers.js +++ b/packages/physics/src/resources/decorators/layers.js @@ -1,5 +1,23 @@ export default (Layers) => class PhysicsLayers extends Layers { + addLayer(layer) { + super.addLayer(layer); + layer.on('tile-data-changed', this.onTileDataChanged, this); + } + + onTileDataChanged() { + const layer = this.layers[1]; + layer.removeTileBodies(); + layer.addTileBodies(); + } + + removeLayer(layer) { + if (-1 !== this.layers.indexOf(layer)) { + layer.off('tile-data-changed', this.onTileDataChanged); + } + super.removeLayer(layer); + } + set world(world) { for (let index = 0; index < this.layers.length; index++) { this.layers[index].world = world;