Lower house and expose rooftop garden terrace

This commit is contained in:
Admin 2026-09-22 00:55:34 +00:00
parent 26e847c89e
commit 781a902d5f
2 changed files with 69 additions and 55 deletions

View File

@ -64,17 +64,17 @@ const SHELL_BEAM_Y = [432, 656, 877, 1094].map((y) => y + HOUSE_Y_OFFSET)
const HOUSE_TOP = FLOOR_SLOTS[0].y const HOUSE_TOP = FLOOR_SLOTS[0].y
const HOUSE_BOTTOM = FLOOR_SLOTS[FLOOR_COUNT - 1].y + FLOOR_SLOTS[FLOOR_COUNT - 1].h const HOUSE_BOTTOM = FLOOR_SLOTS[FLOOR_COUNT - 1].y + FLOOR_SLOTS[FLOOR_COUNT - 1].h
const STATUS_Y = 1540 const STATUS_Y = 1538
// A true rooftop level above the shell, rather than a tiny room inside the gable. // A true rooftop level above the shell, rather than a tiny room inside the gable.
const ROOF_ROOM_BOUNDS = { const ROOF_ROOM_BOUNDS = {
x: 410, x: 155,
y: 18, y: 42,
width: 302, width: 812,
height: 126 height: 168
} }
const ROOF_LIFT_STOP_Y = ROOF_ROOM_BOUNDS.y + Math.round(ROOF_ROOM_BOUNDS.height * 0.84) const ROOF_LIFT_STOP_Y = ROOF_ROOM_BOUNDS.y + ROOF_ROOM_BOUNDS.height - 24
const ELEVATOR_SHAFT_TOP = ROOF_LIFT_STOP_Y - 48 const ELEVATOR_SHAFT_TOP = ROOF_LIFT_STOP_Y - 48
const ELEVATOR_CAR_W = 82 const ELEVATOR_CAR_W = 82
@ -199,7 +199,7 @@ function makeRoofRoom() {
width, width,
height, height,
walkBand: { walkBand: {
minY: y + Math.round(height * 0.72), minY: y + Math.round(height * 0.68),
maxY: y + height - 8, maxY: y + height - 8,
homeY: ROOF_LIFT_STOP_Y homeY: ROOF_LIFT_STOP_Y
} }
@ -229,7 +229,7 @@ function elevatorStopY(room) {
function elevatorEntry(room) { function elevatorEntry(room) {
if (room.side === 'center') { if (room.side === 'center') {
return { return {
x: room.x + Math.round(room.width * 0.68), x: TOWER_CENTER_X + 118,
y: room.walkBand.homeY y: room.walkBand.homeY
} }
} }
@ -605,77 +605,86 @@ class HouseScene extends Phaser.Scene {
const room = ROOM_BY_ID.get('roof-garden') const room = ROOM_BY_ID.get('roof-garden')
const graphics = this.add.graphics().setDepth(30) const graphics = this.add.graphics().setDepth(30)
const inset = 8 const left = room.x
const backInset = 42 const right = room.x + room.width
const wallTop = room.y + 7 const top = room.y
const backTop = room.y + 18 const bottom = room.y + room.height
const backLeft = left + 84
const backRight = right - 84
const horizonY = room.walkBand.minY const horizonY = room.walkBand.minY
const bottomY = room.y + room.height - 6
const left = room.x + inset
const right = room.x + room.width - inset
const backLeft = room.x + backInset
const backRight = room.x + room.width - backInset
// Open-air sky panel and rooftop turf deck. // Open rooftop terrace. The transparent sky lets the pink roof remain
graphics.fillStyle(0xcfefff, 1) // visible behind it while the green deck makes the playable level obvious.
graphics.fillRoundedRect(room.x, room.y, room.width, room.height, 18) graphics.fillStyle(0xffffff, 0.72)
graphics.fillRoundedRect(left, top, room.width, room.height, 24)
graphics.fillStyle(0xbce8ff, 1) graphics.fillStyle(0x94d985, 1)
graphics.fillRect(backLeft, backTop, backRight - backLeft, horizonY - backTop)
graphics.fillStyle(0x8fd47f, 1)
graphics.fillPoints([ graphics.fillPoints([
new Phaser.Geom.Point(backLeft, horizonY), new Phaser.Geom.Point(backLeft, horizonY),
new Phaser.Geom.Point(backRight, horizonY), new Phaser.Geom.Point(backRight, horizonY),
new Phaser.Geom.Point(right, bottomY), new Phaser.Geom.Point(right - 18, bottom - 8),
new Phaser.Geom.Point(left, bottomY) new Phaser.Geom.Point(left + 18, bottom - 8)
], true) ], true)
// Railing so the garden reads as a rooftop terrace. // Pink rooftop railing.
graphics.lineStyle(4, 0xffd1df, 1) graphics.lineStyle(6, 0xf3a7c1, 1)
graphics.lineBetween(left + 8, horizonY - 16, right - 8, horizonY - 16) graphics.lineBetween(left + 24, horizonY - 22, right - 24, horizonY - 22)
graphics.lineBetween(left + 12, horizonY - 16, left + 12, bottomY) graphics.lineBetween(left + 28, horizonY - 22, left + 28, bottom - 10)
graphics.lineBetween(right - 12, horizonY - 16, right - 12, bottomY) graphics.lineBetween(right - 28, horizonY - 22, right - 28, bottom - 10)
// Planters. // Planters along the back edge.
graphics.fillStyle(0xf3c797, 1) graphics.fillStyle(0xf2c08d, 1)
graphics.fillRoundedRect(left + 16, horizonY - 20, 58, 18, 5) graphics.fillRoundedRect(left + 56, horizonY - 27, 104, 22, 6)
graphics.fillRoundedRect(right - 74, horizonY - 20, 58, 18, 5) graphics.fillRoundedRect(right - 160, horizonY - 27, 104, 22, 6)
const flowers = [ const flowers = [
{ x: left + 30, y: horizonY - 27, color: '#ff7fa9' }, { x: left + 78, y: horizonY - 37, color: '#ff7fa9' },
{ x: left + 48, y: horizonY - 34, color: '#ffd86a' }, { x: left + 104, y: horizonY - 43, color: '#ffd86a' },
{ x: right - 48, y: horizonY - 33, color: '#b78cff' }, { x: left + 132, y: horizonY - 36, color: '#b78cff' },
{ x: right - 28, y: horizonY - 27, color: '#ff8f7e' } { x: right - 132, y: horizonY - 36, color: '#ff8f7e' },
{ x: right - 104, y: horizonY - 44, color: '#ffd86a' },
{ x: right - 78, y: horizonY - 38, color: '#b78cff' }
] ]
flowers.forEach((flower) => { flowers.forEach((flower) => {
this.add.text(flower.x, flower.y, '✿', { this.add.text(flower.x, flower.y, '✿', {
fontFamily: 'Arial', fontFamily: 'Arial',
fontSize: '20px', fontSize: '23px',
color: flower.color color: flower.color
}).setOrigin(0.5).setDepth(32) }).setOrigin(0.5).setDepth(32)
}) })
// Bench, offset left so the lift exit on the right remains clear. // Bench on the left, keeping the lift landing clear in the centre/right.
graphics.fillStyle(0xe5b982, 1) graphics.fillStyle(0xe3b47c, 1)
graphics.fillRoundedRect(room.x + 92, horizonY - 9, 74, 9, 4) graphics.fillRoundedRect(left + 218, horizonY - 12, 112, 12, 5)
graphics.fillRect(room.x + 99, horizonY, 6, 16) graphics.fillRect(left + 230, horizonY, 7, 20)
graphics.fillRect(room.x + 153, horizonY, 6, 16) graphics.fillRect(left + 309, horizonY, 7, 20)
graphics.lineStyle(3, 0xd5a4bd, 1) // Lift landing marker aligned with the real sixth elevator stop.
graphics.strokeRoundedRect(room.x, room.y, room.width, room.height, 18) graphics.fillStyle(0xfff2f7, 1)
graphics.lineBetween(left, bottomY, backLeft, horizonY) graphics.fillRoundedRect(TOWER_CENTER_X - 56, horizonY - 38, 112, 44, 10)
graphics.lineBetween(right, bottomY, backRight, horizonY) graphics.lineStyle(4, 0xd99ab6, 1)
graphics.strokeRoundedRect(TOWER_CENTER_X - 56, horizonY - 38, 112, 44, 10)
this.add.text(room.x + 12, room.y + 9, 'Rooftop Garden', { graphics.lineStyle(4, 0xd5a4bd, 1)
graphics.strokeRoundedRect(left, top, room.width, room.height, 24)
this.add.text(left + 20, top + 14, 'Rooftop Garden', {
fontFamily: 'Arial Rounded MT Bold, ui-rounded, sans-serif', fontFamily: 'Arial Rounded MT Bold, ui-rounded, sans-serif',
fontSize: '15px', fontSize: '19px',
color: '#5f7552', color: '#56734e',
fontStyle: 'bold', fontStyle: 'bold',
backgroundColor: 'rgba(255,255,255,0.90)',
padding: { x: 8, y: 4 }
}).setDepth(33)
this.add.text(right - 22, top + 17, 'hold to visit', {
fontFamily: 'Arial Rounded MT Bold, ui-rounded, sans-serif',
fontSize: '14px',
color: '#8b6577',
backgroundColor: 'rgba(255,255,255,0.86)', backgroundColor: 'rgba(255,255,255,0.86)',
padding: { x: 6, y: 3 } padding: { x: 6, y: 3 }
}).setDepth(33) }).setOrigin(1, 0).setDepth(33)
} }
buildHouseShell() { buildHouseShell() {
@ -911,7 +920,9 @@ class HouseScene extends Phaser.Scene {
this.updateStatus(this.currentRoom(), 'Hold for ' + room.name + '…') this.updateStatus(this.currentRoom(), 'Hold for ' + room.name + '…')
this.roomHoldTimer = this.time.delayedCall(ROOM_HOLD_MS, () => { const holdMs = room.isRoof ? 360 : ROOM_HOLD_MS
this.roomHoldTimer = this.time.delayedCall(holdMs, () => {
if ( if (
this.roomHoldRoom?.id !== room.id || this.roomHoldRoom?.id !== room.id ||
this.journeyActive this.journeyActive
@ -1389,7 +1400,7 @@ const game = new Phaser.Game({
}) })
window.__DOLLHOUSE__ = { window.__DOLLHOUSE__ = {
version: '0.10.0', version: '0.10.1',
game, game,
async resetAll() { async resetAll() {
await clearGameState() await clearGameState()

View File

@ -12,6 +12,9 @@ html, body, #app, #game {
margin: 0; margin: 0;
overflow: hidden; overflow: hidden;
} }
#game {
padding-top: clamp(42px, 6vh, 76px);
}
body { body {
min-height: 100dvh; min-height: 100dvh;
overscroll-behavior: none; overscroll-behavior: none;