Open the Door
A single room is a demo. A connected world — rooms that lead to other rooms — is a game. This tutorial adds a multi-room system: each room is a map stored in an object, and door tiles trigger transitions between them.
Walk into the yellow door tiles to move between rooms.
Multiple rooms
Each room is an entry in a rooms object keyed by room ID. The map array lives inside each room, alongside any other per-room data you need:
// Our room database - easy to expand!
const rooms = {
1: {
name: "Village Square",
map: [
[1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 2, 1], // Door (tile type 2)
[1, 1, 1, 1, 1, 1, 1, 1]
],
music: "village_theme.ogg",
background: "#2c3e50"
},
2: {
name: "Mysterious Cave",
map: [
[1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 1, 0, 0, 1, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 1],
[3, 0, 0, 0, 0, 0, 0, 1], // Different door (tile type 3)
[1, 1, 1, 1, 1, 1, 1, 1]
],
music: "cave_ambient.ogg",
background: "#1a1a2e"
}
};
// Door destinations - where each door type leads
const doors = {
2: {
toRoom: 2,
playerX: 1,
playerY: 4,
message: "Entering the mysterious cave..."
},
3: {
toRoom: 1,
playerX: 6,
playerY: 4,
message: "Returning to the village..."
}
};
// Game state manager
const gameState = {
currentRoom: 1,
previousRoom: null,
transitionInProgress: false
};
All room data is in one place and each room can carry its own settings — background colour, music track, particle effects — without any other room needing to know about them.
Room transitions
Step 1: Door detection
// Check if player is standing on a door
function checkForDoors(hero, currentRoom) {
const map = rooms[currentRoom].map;
const tileType = map[hero.tileY][hero.tileX];
// Is this tile a door?
if (doors[tileType]) {
return doors[tileType];
}
return null; // No door here
}
Step 2: Transition system
function transitionToRoom(doorData, hero, gameState, app) {
// Prevent multiple rapid transitions
if (gameState.transitionInProgress) return;
gameState.transitionInProgress = true;
// Optional: Show transition effect
showTransitionEffect(doorData.message);
// Update game state
gameState.previousRoom = gameState.currentRoom;
gameState.currentRoom = doorData.toRoom;
// Move hero to new position
hero.tileX = doorData.playerX;
hero.tileY = doorData.playerY;
// Rebuild the room
buildRoom(gameState.currentRoom, app);
// Re-enable transitions after a brief delay
setTimeout(() => {
gameState.transitionInProgress = false;
}, 500);
}
function showTransitionEffect(message) {
// Simple fade effect or message display
console.log(message);
// You could add visual effects here:
// - Screen fade
// - Flash effect
// - Loading animation
// - Sound effects
}
Step 3: Integration with movement
function updateMovement(hero, keys, gameState, app) {
// ... normal movement code ...
// After successful movement, check for doors
const doorData = checkForDoors(hero, gameState.currentRoom);
if (doorData) {
transitionToRoom(doorData, hero, gameState, app);
}
}
Extended door types
The buildRoom function can read per-room properties to set background colour, start music, or trigger effects:
function buildRoom(roomId, app) {
const room = rooms[roomId];
app.stage.removeChildren();
app.renderer.background.color = room.background || 0x2c3e50;
renderMap(room.map, app);
if (room.particles) addParticleEffects(room.particles, app);
if (room.music) playBackgroundMusic(room.music);
displayRoomTitle(room.name, app);
}
// Doors with conditions
const specialDoors = {
LOCKED: {
canUse: (hero) => hero.hasKey,
message: "This door is locked.",
sound: "door_locked.ogg"
},
MAGIC: {
canUse: (hero) => hero.mana >= 10,
cost: { mana: 10 },
effect: "sparkle"
},
TELEPORTER: {
canUse: () => true,
effect: "flash"
}
};
// Smart door system
function tryUseDoor(tileType, hero) {
const doorData = doors[tileType];
if (!doorData) return false;
// Check if door can be used
if (doorData.special) {
const specialType = specialDoors[doorData.special];
if (!specialType.canUse(hero)) {
showMessage(specialType.message);
return false;
}
// Apply costs
if (specialType.cost) {
Object.assign(hero, specialType.cost);
}
// Show special effects
if (specialType.effect) {
playEffect(specialType.effect);
}
}
return true; // Door can be used!
}
What you built:
- A
roomsobject that stores each map alongside per-room settings - A
doorslookup that maps tile values to destination rooms and spawn positions - A
buildRoomfunction that clears the stage and renders the new room - A transition guard (
transitionInProgress) to prevent double-triggers