From bbb99cf935b79b361f6e8419e63ac739d49e6cb8 Mon Sep 17 00:00:00 2001 From: "Z. Cliffe Schreuders" Date: Mon, 17 Nov 2025 20:08:07 +0000 Subject: [PATCH] fix: Add teleportation collision boxes for doors to enable bi-directional teleportation --- js/systems/collision.js | 170 +++++++++++++++++++++++++++++++--------- 1 file changed, 132 insertions(+), 38 deletions(-) diff --git a/js/systems/collision.js b/js/systems/collision.js index 92f0dbb..577f240 100644 --- a/js/systems/collision.js +++ b/js/systems/collision.js @@ -12,6 +12,10 @@ import { getOppositeDirection, calculateDoorPositionsForRoom } from './doors.js' let gameRef = null; let rooms = null; +// Teleportation cooldown system to prevent rapid back-and-forth +let lastTeleportTime = 0; +const TELEPORT_COOLDOWN = 500; // 500ms cooldown between teleports + // Initialize collision system export function initializeCollision(gameInstance, roomsRef) { gameRef = gameInstance; @@ -326,6 +330,49 @@ export function removeTilesUnderDoor(wallLayer, roomId, position) { room.wallCollisionBoxes = []; } room.wallCollisionBoxes.push(northCollisionBox, southCollisionBox); + + // Create teleportation collision box on the inner half of the door (16px wide) + // Position it 8px into the room (inner half of the door tile) + const teleportOffset = direction === 'east' ? TILE_SIZE / 4 : -TILE_SIZE / 4; + const teleportBox = gameRef.add.zone( + doorX + teleportOffset, + doorY, + TILE_SIZE / 2, // 16px wide + TILE_SIZE + ); + teleportBox.setInteractive(); + gameRef.physics.world.enable(teleportBox); + teleportBox.body.setSize(TILE_SIZE / 2, TILE_SIZE); + teleportBox.body.immovable = true; + + // Add overlap callback for bi-directional teleportation + gameRef.physics.add.overlap(player, teleportBox, () => { + if (player) { + const currentTime = Date.now(); + // Check cooldown to prevent rapid teleporting back and forth + if (currentTime - lastTeleportTime > TELEPORT_COOLDOWN) { + // Teleport player 40px through the door + const offset = 40; // 40px teleportation + if (direction === 'east') { + // Teleport to the east (into connected room) + player.x = doorX + offset; + } else { + // Teleport to the west (into connected room) + player.x = doorX - offset; + } + lastTeleportTime = currentTime; + console.log(`Teleported player through door void (from ${roomId}) to x=${player.x}`); + } + } + }); + + // Store teleport box in room for cleanup + if (!room.wallCollisionBoxes) { + room.wallCollisionBoxes = []; + } + room.wallCollisionBoxes.push(teleportBox); + + console.log(`Added bi-directional teleportation box at (${doorX}, ${doorY}) in room ${roomId}`); } } }); @@ -546,45 +593,92 @@ export function removeWallTilesForDoorInRoom(roomId, fromRoomId, direction, door if (oppositeDirection === 'east' || oppositeDirection === 'west') { console.log(`Adding full tile collision boxes above and below side door cutout in ${roomId}`); - // North side collision box (full tile above the door) - const northCollisionBox = gameRef.add.rectangle( - doorX, - doorY - TILE_SIZE, // One full tile above the door - TILE_SIZE, - TILE_SIZE, // Full tile size - 0x0000ff, - 0 // Invisible - ); - northCollisionBox.setVisible(false); - gameRef.physics.add.existing(northCollisionBox, true); - northCollisionBox.body.immovable = true; - - // South side collision box (full tile below the door) - const southCollisionBox = gameRef.add.rectangle( - doorX, - doorY + TILE_SIZE, // One full tile below the door - TILE_SIZE, - TILE_SIZE, // Full tile size - 0x0000ff, - 0 // Invisible - ); - southCollisionBox.setVisible(false); - gameRef.physics.add.existing(southCollisionBox, true); - southCollisionBox.body.immovable = true; - - // Add collision with player - const player = window.player; - if (player && player.body) { - gameRef.physics.add.collider(player, northCollisionBox); - gameRef.physics.add.collider(player, southCollisionBox); - console.log(`Added full tile collision boxes above and below side door in ${roomId}`); + const room = window.rooms ? window.rooms[roomId] : null; + if (room) { + // North side collision box (full tile above the door) + const northCollisionBox = gameRef.add.rectangle( + doorX, + doorY - TILE_SIZE, // One full tile above the door + TILE_SIZE, + TILE_SIZE, // Full tile size + 0x0000ff, + 0 // Invisible + ); + northCollisionBox.setVisible(false); + gameRef.physics.add.existing(northCollisionBox, true); + northCollisionBox.body.immovable = true; + + // South side collision box (full tile below the door) + const southCollisionBox = gameRef.add.rectangle( + doorX, + doorY + TILE_SIZE, // One full tile below the door + TILE_SIZE, + TILE_SIZE, // Full tile size + 0x0000ff, + 0 // Invisible + ); + southCollisionBox.setVisible(false); + gameRef.physics.add.existing(southCollisionBox, true); + southCollisionBox.body.immovable = true; + + // Add collision with player + const player = window.player; + if (player && player.body) { + gameRef.physics.add.collider(player, northCollisionBox); + gameRef.physics.add.collider(player, southCollisionBox); + console.log(`Added full tile collision boxes above and below side door in ${roomId}`); + } + + // Store collision boxes in room for cleanup + if (!room.wallCollisionBoxes) { + room.wallCollisionBoxes = []; + } + room.wallCollisionBoxes.push(northCollisionBox, southCollisionBox); + + // Create teleportation collision box on the inner half of the door (16px wide) + // Position it on the side of the tile that they just came from + // If oppositeDirection is 'east', the door is on the east wall, so position on the east side + const teleportOffset = oppositeDirection === 'east' ? TILE_SIZE / 4 : -TILE_SIZE / 4; + const teleportBox = gameRef.add.zone( + doorX + teleportOffset, + doorY, + TILE_SIZE / 2, // 16px wide + TILE_SIZE + ); + teleportBox.setInteractive(); + gameRef.physics.world.enable(teleportBox); + teleportBox.body.setSize(TILE_SIZE / 2, TILE_SIZE); + teleportBox.body.immovable = true; + + // Add overlap callback for teleportation + gameRef.physics.add.overlap(player, teleportBox, () => { + if (player) { + const currentTime = Date.now(); + // Check cooldown to prevent rapid teleporting back and forth + if (currentTime - lastTeleportTime > TELEPORT_COOLDOWN) { + // Teleport player through the door + const offset = 34; // 34px teleportation + if (oppositeDirection === 'east') { + // Door opening in connected room is on east side, so push player west (back) + player.x = doorX - offset; + } else { + // Door opening in connected room is on west side, so push player east (back) + player.x = doorX + offset; + } + lastTeleportTime = currentTime; + console.log(`Teleported player through door void to x=${player.x}`); + } + } + }); + + // Store teleport box in room for cleanup + if (!room.wallCollisionBoxes) { + room.wallCollisionBoxes = []; + } + room.wallCollisionBoxes.push(teleportBox); + + console.log(`Added teleportation box at (${doorX}, ${doorY}) in room ${roomId}`); } - - // Store collision boxes in room for cleanup - if (!room.wallCollisionBoxes) { - room.wallCollisionBoxes = []; - } - room.wallCollisionBoxes.push(northCollisionBox, southCollisionBox); } }); }