From d14864c604264038466e0118a628936483a5292c Mon Sep 17 00:00:00 2001 From: Bill Rossi Date: Sat, 7 Jun 2025 10:34:40 -0400 Subject: [PATCH] Implement collidable tiles --- src/player.js | 7 ++ src/room.js | 29 +++++- src/tileset.js | 12 +++ tilesets/kenney_rpg.tsj | 217 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 261 insertions(+), 4 deletions(-) diff --git a/src/player.js b/src/player.js index ecb79ce..9b71ec8 100644 --- a/src/player.js +++ b/src/player.js @@ -27,6 +27,13 @@ export default class Player extends Actor { this.x += this.xVel this.y += this.yVel + const tur = this.game.currentRoom.tilesUnderRectangle(this.game.currentRoom.json.layers[0], this).filter(x => x) + const colliders = tur.filter(tile => tile.properties.find(prop => prop.name == "collides" && prop.value)) + if (tur.length >= 1) { + this.x -= this.xVel + this.y -= this.yVel + } + if (!isZeroVector(dir)) this.playerDirection = dir if (this.isInputPressed("interact")) this.createInteractHitbox() diff --git a/src/room.js b/src/room.js index 06fa384..c0057c6 100644 --- a/src/room.js +++ b/src/room.js @@ -9,10 +9,6 @@ export default class Room { this.objects = objectJson.map(RoomObject.fromJson.bind(null, this.game)) } - tick(dt) { - this.objects.forEach(object => object.tick(dt)) - } - get tilesetsToLoad() { const ts = {} this.json.tilesets.forEach((tileset, index) => { @@ -37,6 +33,22 @@ export default class Room { if (layer.type == "tilelayer") this.drawTileLayer(ctx, layer) } + tilesUnderRectangle(layer, rect) { + return [{ x: rect.x, y: rect.y }, + { x: rect.x + rect.width, y: rect.y }, + { x: rect.x, y: rect.y + rect.height }, + { x: rect.x + rect.width, y: rect.y + rect.height } + ].map(point => { + const tileset = this.tilesets[0] + const { x, y } = point + const tileX = Math.floor(x / tileset.tileWidth) + const tileY = Math.floor(y / tileset.tileHeight) + const index = tileX + (tileY * layer.width) + const tileIndex = layer.data[index] - 1 + return tileset.tileAt(tileIndex) + }) + } + drawTileLayer(ctx, layer) { for (let y = 0; y < layer.height; y++) { for (let x = 0; x < layer.width; x++) { @@ -55,6 +67,15 @@ export default class Room { this.json.tilewidth, this.json.tileheight ) + if (tileset.collides(tileIndex)) { + ctx.fillStyle = "#aa660088" + ctx.fillRect( + x * this.json.tilewidth, + y * this.json.tileheight, + this.json.tilewidth, + this.json.tileheight + ) + } } } } diff --git a/src/tileset.js b/src/tileset.js index 3b27c34..754f8f3 100644 --- a/src/tileset.js +++ b/src/tileset.js @@ -3,6 +3,7 @@ export default class Tileset { this.game = game this.json = json this.name = name + this.tiles = json.tiles } get imagesToLoad() { @@ -33,4 +34,15 @@ export default class Tileset { (Math.floor(index / this.columns) * this.tileHeight) ] } + + tileAt(index) { + return this.tiles.find(tile => tile.id == index) + } + + collides(index) { + const tile = this.tileAt(index) + if (!tile) return + + return tile.properties.find(prop => prop.name == "collides").value == "true" + } } diff --git a/tilesets/kenney_rpg.tsj b/tilesets/kenney_rpg.tsj index 479418c..9dda02e 100644 --- a/tilesets/kenney_rpg.tsj +++ b/tilesets/kenney_rpg.tsj @@ -8,6 +8,223 @@ "tilecount":260, "tiledversion":"1.11.2", "tileheight":64, + "tiles":[ + { + "id":60, + "properties":[ + { + "name":"collides", + "type":"bool", + "value":true + }] + }, + { + "id":61, + "properties":[ + { + "name":"collides", + "type":"bool", + "value":true + }] + }, + { + "id":62, + "properties":[ + { + "name":"collides", + "type":"bool", + "value":true + }] + }, + { + "id":63, + "properties":[ + { + "name":"collides", + "type":"bool", + "value":true + }] + }, + { + "id":64, + "properties":[ + { + "name":"collides", + "type":"bool", + "value":true + }] + }, + { + "id":65, + "properties":[ + { + "name":"collides", + "type":"bool", + "value":true + }] + }, + { + "id":66, + "properties":[ + { + "name":"collides", + "type":"bool", + "value":true + }] + }, + { + "id":80, + "properties":[ + { + "name":"collides", + "type":"bool", + "value":true + }] + }, + { + "id":81, + "properties":[ + { + "name":"collides", + "type":"bool", + "value":true + }] + }, + { + "id":82, + "properties":[ + { + "name":"collides", + "type":"bool", + "value":true + }] + }, + { + "id":83, + "properties":[ + { + "name":"collides", + "type":"bool", + "value":true + }] + }, + { + "id":84, + "properties":[ + { + "name":"collides", + "type":"bool", + "value":true + }] + }, + { + "id":85, + "properties":[ + { + "name":"collides", + "type":"bool", + "value":true + }] + }, + { + "id":86, + "properties":[ + { + "name":"collides", + "type":"bool", + "value":true + }] + }, + { + "id":100, + "properties":[ + { + "name":"collides", + "type":"bool", + "value":true + }] + }, + { + "id":101, + "properties":[ + { + "name":"collides", + "type":"bool", + "value":true + }] + }, + { + "id":102, + "properties":[ + { + "name":"collides", + "type":"bool", + "value":true + }] + }, + { + "id":103, + "properties":[ + { + "name":"collides", + "type":"bool", + "value":true + }] + }, + { + "id":144, + "properties":[ + { + "name":"collides", + "type":"bool", + "value":true + }] + }, + { + "id":145, + "properties":[ + { + "name":"collides", + "type":"bool", + "value":true + }] + }, + { + "id":146, + "properties":[ + { + "name":"collides", + "type":"bool", + "value":true + }] + }, + { + "id":164, + "properties":[ + { + "name":"collides", + "type":"bool", + "value":true + }] + }, + { + "id":165, + "properties":[ + { + "name":"collides", + "type":"bool", + "value":true + }] + }, + { + "id":166, + "properties":[ + { + "name":"collides", + "type":"bool", + "value":true + }] + }], "tilewidth":64, "type":"tileset", "version":"1.10"