fix: Correct side door (E/W) placement, sprites, and animations

This commit fixes several issues with East/West side doors:

1. **Sprite Flipping**: Changed flip direction - East doors are now flipped
   horizontally instead of West doors (opposite direction as requested)

2. **Door Positioning**: Updated E/W door placement from 2 tiles to 3 tiles
   from the top corner for better alignment with room layout

3. **Wall Passage Cutout**: Increased wall tile removal area for side doors
   from 1 tile to 3 tiles vertically, creating a wider passage (matching the
   inset spacing used for N/S doors)

4. **Side Door Animation**:
   - Added `isSideDoor` property to doorProperties to track door type
   - Created new 'door_side_open' animation using frames 1-4 (frames 2-5
     in 1-indexed notation) of door_side_sheet_32 sprite
   - Updated animated door creation to use side door sprite and animation
     for E/W doors

5. **Sprite Alignment**: Door sprites now properly align with the tile grid
   at 3 tiles from corner position

Changes made in:
- js/systems/doors.js: Door placement, sprite creation, and animations
- js/systems/collision.js: Wall tile removal for wider passages
- js/core/game.js: Side door animation definition

Tested with: scenarios/test_horizontal_layout.json
This commit is contained in:
Z. Cliffe Schreuders
2025-11-17 12:28:19 +00:00
parent aef6e97df0
commit c3440986a3
3 changed files with 95 additions and 51 deletions

View File

@@ -523,14 +523,14 @@ export async function create() {
// Store player globally for access from other modules
window.player = player;
// Create door opening animation
// Create door opening animation (for N/S doors)
this.anims.create({
key: 'door_open',
frames: this.anims.generateFrameNumbers('door_sheet', { start: 0, end: 4 }),
frameRate: 8,
repeat: 0
});
// Create door top animation (6th frame)
this.anims.create({
key: 'door_top',
@@ -538,6 +538,14 @@ export async function create() {
frameRate: 1,
repeat: 0
});
// Create side door opening animation (for E/W doors) - frames 2-5 (1-indexed) = frames 1-4 (0-indexed)
this.anims.create({
key: 'door_side_open',
frames: this.anims.generateFrameNumbers('door_side_sheet_32', { start: 1, end: 4 }),
frameRate: 8,
repeat: 0
});
// Create plant bump animations
this.anims.create({

View File

@@ -369,9 +369,9 @@ export function removeWallTilesForDoorInRoom(roomId, fromRoomId, direction, door
doorWidth = TILE_SIZE * 2;
doorHeight = TILE_SIZE;
} else if (direction === 'east' || direction === 'west') {
// For east/west connections: single tile per room, positioned 3 tiles down from top
// Doors are 3 tiles down from top (below top 2 wall tiles)
doorY = roomPosition.y + (TILE_SIZE * 2); // 2 tiles down from top (at tile 3)
// For east/west connections: positioned 3 tiles down from top corner
// Passage cutout is 3 tiles wide vertically
doorY = roomPosition.y + (TILE_SIZE * 3); // 3 tiles from top corner
if (direction === 'east') {
// Original door is east, so new door should be west
@@ -380,9 +380,9 @@ export function removeWallTilesForDoorInRoom(roomId, fromRoomId, direction, door
// Original door is west, so new door should be east
doorX = roomPosition.x + roomWidth - TILE_SIZE;
}
// Single tile per room for east/west doors
// Side doors have a 3-tile wide passage (vertically)
doorWidth = TILE_SIZE;
doorHeight = TILE_SIZE;
doorHeight = TILE_SIZE * 3;
} else {
console.log(`Unknown direction: ${direction}`);
return;

View File

@@ -221,7 +221,7 @@ function placeEastDoorSingle(roomId, roomPosition, roomDimensions, connectedRoom
const roomWidthPx = roomDimensions.widthPx;
const doorX = roomPosition.x + roomWidthPx - TILE_SIZE;
const doorY = roomPosition.y + (TILE_SIZE * 2); // Below visual wall
const doorY = roomPosition.y + (TILE_SIZE * 3); // 3 tiles from top corner
return { x: doorX, y: doorY, connectedRoom };
}
@@ -237,11 +237,11 @@ function placeEastDoorsMultiple(roomId, roomPosition, roomDimensions, connectedR
const doorX = roomPosition.x + roomWidthPx - TILE_SIZE;
if (connectedRooms.length === 1) {
const doorY = roomPosition.y + (TILE_SIZE * 2);
const doorY = roomPosition.y + (TILE_SIZE * 3);
doorPositions.push({ x: doorX, y: doorY, connectedRoom: connectedRooms[0] });
} else {
// Multiple doors - space vertically
const topY = roomPosition.y + (TILE_SIZE * 2);
const topY = roomPosition.y + (TILE_SIZE * 3);
const bottomY = roomPosition.y + roomHeightPx - (TILE_SIZE * 3);
const spacing = (bottomY - topY) / (connectedRooms.length - 1);
@@ -259,7 +259,7 @@ function placeEastDoorsMultiple(roomId, roomPosition, roomDimensions, connectedR
*/
function placeWestDoorSingle(roomId, roomPosition, roomDimensions, connectedRoom) {
const doorX = roomPosition.x + TILE_SIZE;
const doorY = roomPosition.y + (TILE_SIZE * 2);
const doorY = roomPosition.y + (TILE_SIZE * 3); // 3 tiles from top corner
return { x: doorX, y: doorY, connectedRoom };
}
@@ -274,11 +274,11 @@ function placeWestDoorsMultiple(roomId, roomPosition, roomDimensions, connectedR
const doorX = roomPosition.x + TILE_SIZE;
if (connectedRooms.length === 1) {
const doorY = roomPosition.y + (TILE_SIZE * 2);
const doorY = roomPosition.y + (TILE_SIZE * 3);
doorPositions.push({ x: doorX, y: doorY, connectedRoom: connectedRooms[0] });
} else {
// Multiple doors - space vertically
const topY = roomPosition.y + (TILE_SIZE * 2);
const topY = roomPosition.y + (TILE_SIZE * 3);
const bottomY = roomPosition.y + roomHeightPx - (TILE_SIZE * 3);
const spacing = (bottomY - topY) / (connectedRooms.length - 1);
@@ -403,7 +403,7 @@ export function createDoorSpritesForRoom(roomId, position) {
const { x: doorX, y: doorY, direction, connectedRoom } = doorInfo;
// Set door size and texture based on direction
let doorWidth, doorHeight, doorTexture, flipX;
let doorWidth, doorHeight, doorTexture, flipX, isSideDoor;
if (direction === 'north' || direction === 'south') {
// North/South doors: 1 tile wide, 2 tiles tall
@@ -411,13 +411,16 @@ export function createDoorSpritesForRoom(roomId, position) {
doorHeight = TILE_SIZE * 2;
doorTexture = 'door_32';
flipX = false;
isSideDoor = false;
} else {
// East/West doors: 1 tile wide, 1 tile tall (single tile per room)
doorWidth = TILE_SIZE;
doorHeight = TILE_SIZE;
doorTexture = 'door_side_sheet_32';
// West-facing doors (left room) should be flipped horizontally
flipX = (direction === 'west');
// East-facing doors (right room) should be flipped horizontally
// West-facing doors use the default orientation
flipX = (direction === 'east');
isSideDoor = true;
}
console.log(`Creating door sprite at (${doorX}, ${doorY}) for ${roomId} -> ${connectedRoom} (${direction})`);
@@ -488,7 +491,8 @@ export function createDoorSpritesForRoom(roomId, position) {
lockType: lockProps.lockType || connectedRoomData?.lockType || null,
requires: lockProps.requires || connectedRoomData?.requires || null,
keyPins: keyPinsArray, // Include keyPins from scenario (supports both cases)
difficulty: lockProps.difficulty || connectedRoomData?.difficulty // Include difficulty from scenario
difficulty: lockProps.difficulty || connectedRoomData?.difficulty, // Include difficulty from scenario
isSideDoor: isSideDoor // Track if this is a side (E/W) door for animation purposes
};
// Debug door properties
@@ -770,36 +774,64 @@ function createAnimatedDoorOnOppositeSide(roomId, fromRoomId, direction, doorWor
// Create the animated door sprite
let animatedDoorSprite;
let doorTopSprite;
const isSideDoor = (direction === 'east' || direction === 'west');
try {
// Create main door sprite
animatedDoorSprite = gameRef.add.sprite(doorX, doorY, 'door_sheet');
// Calculate the bottom of the door (where it meets the ground)
const doorBottomY = doorY + (TILE_SIZE * 2) / 2; // doorY is center, so add half height to get bottom
// Set sprite properties
animatedDoorSprite.setOrigin(0.5, 0.5);
animatedDoorSprite.setDepth(doorBottomY + 0.45); // Bottom Y + door layer offset
animatedDoorSprite.setVisible(true);
// Play the opening animation
animatedDoorSprite.play('door_open');
// Create door top sprite (6th frame) at high z-index
doorTopSprite = gameRef.add.sprite(doorX, doorY, 'door_sheet');
doorTopSprite.setOrigin(0.5, 0.5);
doorTopSprite.setDepth(doorBottomY + 0.55); // Bottom Y + door top layer offset
doorTopSprite.setVisible(true);
doorTopSprite.play('door_top');
// Store references to the animated doors in the room
if (!room.animatedDoors) {
room.animatedDoors = [];
if (isSideDoor) {
// Create side door sprite (E/W doors)
animatedDoorSprite = gameRef.add.sprite(doorX, doorY, 'door_side_sheet_32');
// Set sprite properties
animatedDoorSprite.setOrigin(0.5, 0.5);
animatedDoorSprite.setDepth(doorY + 0.45); // World Y + door layer offset
animatedDoorSprite.setVisible(true);
// Apply flip based on direction (East doors are flipped, West are not)
if (oppositeDirection === 'west') {
animatedDoorSprite.setFlipX(true);
}
// Play the side door opening animation
animatedDoorSprite.play('door_side_open');
// Store reference to the animated door in the room
if (!room.animatedDoors) {
room.animatedDoors = [];
}
room.animatedDoors.push(animatedDoorSprite);
console.log(`Created animated side door sprite at (${doorX}, ${doorY}) in room ${roomId}`);
} else {
// Create main door sprite (N/S doors)
animatedDoorSprite = gameRef.add.sprite(doorX, doorY, 'door_sheet');
// Calculate the bottom of the door (where it meets the ground)
const doorBottomY = doorY + (TILE_SIZE * 2) / 2; // doorY is center, so add half height to get bottom
// Set sprite properties
animatedDoorSprite.setOrigin(0.5, 0.5);
animatedDoorSprite.setDepth(doorBottomY + 0.45); // Bottom Y + door layer offset
animatedDoorSprite.setVisible(true);
// Play the opening animation
animatedDoorSprite.play('door_open');
// Create door top sprite (6th frame) at high z-index
doorTopSprite = gameRef.add.sprite(doorX, doorY, 'door_sheet');
doorTopSprite.setOrigin(0.5, 0.5);
doorTopSprite.setDepth(doorBottomY + 0.55); // Bottom Y + door top layer offset
doorTopSprite.setVisible(true);
doorTopSprite.play('door_top');
// Store references to the animated doors in the room
if (!room.animatedDoors) {
room.animatedDoors = [];
}
room.animatedDoors.push(animatedDoorSprite);
room.animatedDoors.push(doorTopSprite);
console.log(`Created animated door sprite at (${doorX}, ${doorY}) in room ${roomId} with door top`);
}
room.animatedDoors.push(animatedDoorSprite);
room.animatedDoors.push(doorTopSprite);
console.log(`Created animated door sprite at (${doorX}, ${doorY}) in room ${roomId} with door top`);
} catch (error) {
console.warn(`Failed to create animated door sprite:`, error);
@@ -808,16 +840,20 @@ function createAnimatedDoorOnOppositeSide(roomId, fromRoomId, direction, doorWor
graphics.fillStyle(0x00ff00, 1); // Green color for open door
graphics.fillRect(-doorWidth/2, -doorHeight/2, doorWidth, doorHeight);
graphics.setPosition(doorX, doorY);
// Calculate the bottom of the door (where it meets the ground)
const doorBottomY = doorY + (TILE_SIZE * 2) / 2; // doorY is center, so add half height to get bottom
graphics.setDepth(doorBottomY + 0.45); // Bottom Y + door layer offset
// Calculate depth based on door type
if (isSideDoor) {
graphics.setDepth(doorY + 0.45); // World Y + door layer offset
} else {
const doorBottomY = doorY + (TILE_SIZE * 2) / 2; // doorY is center, so add half height to get bottom
graphics.setDepth(doorBottomY + 0.45); // Bottom Y + door layer offset
}
if (!room.animatedDoors) {
room.animatedDoors = [];
}
room.animatedDoors.push(graphics);
console.log(`Created fallback animated door at (${doorX}, ${doorY}) in room ${roomId}`);
}
}