Lower house and expose rooftop garden terrace
This commit is contained in:
parent
26e847c89e
commit
781a902d5f
121
src/main.js
121
src/main.js
@ -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()
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user