Created detailed implementation plan for redesigning the room layout system to support variable room sizes and four-direction connections. Core Concepts: - Grid unit system (5×4 tiles base, excluding 2-tile visual top) - Valid room heights: 6, 10, 14, 18, 22, 26... (formula: 2 + 4N) - Breadth-first room positioning from starting room - Deterministic door placement with alignment for asymmetric connections - Comprehensive scenario validation Documents Created: - OVERVIEW.md: High-level goals and changes - TERMINOLOGY.md: Definitions and concepts - GRID_SYSTEM.md: Grid unit system specification - POSITIONING_ALGORITHM.md: Room positioning logic - DOOR_PLACEMENT.md: Door placement rules and algorithms - WALL_SYSTEM.md: Wall collision system updates - VALIDATION.md: Scenario validation system - IMPLEMENTATION_STEPS.md: Step-by-step implementation guide - TODO_LIST.md: Detailed task checklist - README.md: Quick start and overview Review & Critical Fixes: - review1/CRITICAL_REVIEW.md: Identified 4 critical issues - review1/RECOMMENDATIONS.md: Solutions for all issues - UPDATED_FILES_SUMMARY.md: Integration of review feedback Critical Issues Identified & Resolved: 1. Grid height calculation (now: 6, 10, 14, 18...) 2. Door alignment for asymmetric connections (solution documented) 3. Code duplication (shared module approach specified) 4. Disconnected rooms (validation added) Implementation Strategy: - Incremental approach with feature flag - Phase 1: Constants and helpers - Phase 2a: North/South positioning - Phase 2b: East/West support - Phase 3: Door placement with critical fixes - Phase 4: Validation - Phase 5-6: Testing and documentation Estimated time: 18-26 hours Confidence: 9/10 (all critical issues addressed) Ready for implementation.
8.2 KiB
Wall and Collision System
Overview
The wall system creates invisible collision boxes at room boundaries to prevent the player from walking through walls. Doors remove these collision boxes to create passages between rooms.
Current Implementation
Located in js/systems/collision.js:
createWallCollisionBoxes()- Creates collision rectangles for wall tilesremoveTilesUnderDoor()- Removes wall tiles where doors are placed
Wall Placement
Wall Edges
Rooms have walls on all four sides:
WWWWWWWWWW <- North wall (top 2 rows, visual only)
WWWWWWWWWW
WFFFFFFFFW <- West/East walls (1 tile each side)
WFFFFFFFFW North wall collision starts here
WFFFFFFFFW
WFFFFFFFFW
WFFFFFFFFW
WFFFFFFFFW <- South wall (bottom row)
Collision Box Placement
Collision boxes are thin rectangles placed at the boundary between wall and floor:
// North wall: Top 2 rows (visual wall)
// Collision box at bottom edge of row 2
if (tileY < 2) {
createCollisionBox(
worldX + TILE_SIZE / 2, // Center of tile
worldY + TILE_SIZE - 4, // 4px from bottom
TILE_SIZE, // Full tile width
8 // 8px thick
);
}
// South wall: Bottom row
// Collision box at bottom edge
if (tileY === mapHeight - 1) {
createCollisionBox(
worldX + TILE_SIZE / 2,
worldY + TILE_SIZE - 4,
TILE_SIZE,
8
);
}
// West wall: Left column
// Collision box at right edge
if (tileX === 0) {
createCollisionBox(
worldX + TILE_SIZE - 4, // 4px from right edge
worldY + TILE_SIZE / 2, // Center of tile
8, // 8px thick
TILE_SIZE // Full tile height
);
}
// East wall: Right column
// Collision box at left edge
if (tileX === mapWidth - 1) {
createCollisionBox(
worldX + 4, // 4px from left edge
worldY + TILE_SIZE / 2,
8,
TILE_SIZE
);
}
Changes Needed for Variable Room Sizes
Current Issue
The current implementation assumes all rooms are 10×10 tiles. Wall detection uses hardcoded checks:
// Current code
if (tileY < 2) { /* north wall */ }
if (tileY === map.height - 1) { /* south wall */ }
if (tileX === 0) { /* west wall */ }
if (tileX === map.width - 1) { /* east wall */ }
This works correctly and should continue to work for variable room sizes!
No Changes Needed
The wall collision system is already compatible with variable room sizes:
- Uses
map.widthandmap.heightfrom Tiled JSON - Dynamically detects edges based on actual room dimensions
- Creates collision boxes for each wall tile
The current implementation in js/systems/collision.js lines 22-151 should work without modification.
Door Integration
Removing Wall Tiles
When doors are created, wall tiles must be removed:
function removeTilesUnderDoor(wallLayer, doorX, doorY, doorWidth, doorHeight) {
// Convert world coordinates to layer tile coordinates
const layerTileX = Math.floor((doorX - wallLayer.x) / TILE_SIZE);
const layerTileY = Math.floor((doorY - wallLayer.y) / TILE_SIZE);
// Calculate how many tiles the door spans
const tilesWide = Math.ceil(doorWidth / TILE_SIZE);
const tilesTall = Math.ceil(doorHeight / TILE_SIZE);
// Remove tiles in door area
for (let x = 0; x < tilesWide; x++) {
for (let y = 0; y < tilesTall; y++) {
const tileX = layerTileX + x;
const tileY = layerTileY + y;
const tile = wallLayer.getTileAt(tileX, tileY);
if (tile) {
wallLayer.removeTileAt(tileX, tileY);
console.log(`Removed wall tile at (${tileX}, ${tileY}) for door`);
}
}
}
}
Current Implementation
The current removeTilesUnderDoor() function in js/systems/collision.js (lines 154-335):
- Calculates door positions using same logic as door sprites
- Converts door world coordinates to tile coordinates
- Removes tiles in door area
This should continue to work with the new positioning system, as long as door positions are calculated correctly.
Updates Needed
The door positioning logic in removeTilesUnderDoor() must match the new door placement algorithm:
- Update door position calculation to use new algorithm (from DOOR_PLACEMENT.md)
- Remove hardcoded positioning logic (lines 195-283 currently duplicate door placement)
- Use shared door calculation function instead
Collision Box Management
Creation During Room Load
export function createRoom(roomId, roomData, position) {
// ... create room layers ...
// Create wall collision boxes
wallsLayers.forEach(wallLayer => {
createWallCollisionBoxes(wallLayer, roomId, position);
});
// Create door sprites (which remove wall tiles/collisions)
const doorSprites = createDoorSpritesForRoom(roomId, position);
// ... rest of room creation ...
}
Door-Specific Removal
When a door is opened, wall collisions in that area are already removed (tiles removed). When door sprite has collision physics, closing the door is done by the door sprite's collision box.
Room-Specific Collision
Each room maintains its own collision boxes:
rooms[roomId] = {
map,
layers,
wallsLayers,
wallCollisionBoxes: [], // All collision boxes for this room
doorSprites: [],
objects: {},
position
};
Testing Wall Collisions
Visual Debug Mode
Add ability to visualize collision boxes:
window.showWallCollisions = function() {
Object.values(rooms).forEach(room => {
if (room.wallCollisionBoxes) {
room.wallCollisionBoxes.forEach(box => {
box.setVisible(true);
box.setAlpha(0.3);
box.setFillStyle(0xff0000); // Red
});
}
});
};
window.hideWallCollisions = function() {
Object.values(rooms).forEach(room => {
if (room.wallCollisionBoxes) {
room.wallCollisionBoxes.forEach(box => {
box.setVisible(false);
});
}
});
};
Test Cases
- Player vs Wall: Walk into walls, should not pass through
- Player vs Door: Walk through open door, should pass
- Player vs Closed Door: Walk into closed door, should not pass
- Different Room Sizes: Test walls work for small, standard, and large rooms
- Room Boundaries: Test at edges where rooms connect
Implementation Notes
Order of Operations
Critical: Wall collision boxes must be created before door tiles are removed:
// Correct order:
1. Create room layers
2. Create wall collision boxes (for all wall tiles)
3. Create door sprites
4. Remove tiles under doors (removes some collision boxes)
// If done wrong:
1. Create room layers
2. Create door sprites
3. Remove tiles under doors
4. Create wall collision boxes <- Would create boxes where doors are!
The current implementation does this correctly.
Edge Cases
Rooms with Shared Walls
When two rooms are adjacent (east-west connection):
[Room1][Room2]
^^
Shared edge
- Room1 has east wall collision
- Room2 has west wall collision
- These are at the same location
- Both are removed when door is created
- Works correctly (two collision boxes at same spot is fine)
Overlapping Visual Walls
When rooms stack north-south:
[Room2] <- Bottom 2 rows visible
[Room1] <- Top 2 rows visible
- Room1's north wall (visual) overlaps Room2's south area
- Collision is only on Room1's floor edge (row 2 bottom)
- Room2's south wall collision is at its bottom edge
- No conflict, works correctly
Summary
What Works Already
- Dynamic wall detection based on room size
- Collision box creation at wall edges
- Player collision with walls
- Door removal of wall tiles
What Needs Updates
- Door position calculation in
removeTilesUnderDoor()must use new algorithm - Remove duplicate door positioning logic
- Ensure door positions match between
createDoorSpritesForRoom()andremoveTilesUnderDoor()
What Stays the Same
- Collision box placement logic
- Wall edge detection
- Collision thickness (8px)
- Order of operations