Files
Cozypaw-Hospital/docs/superpowers/plans/2026-04-17-sprint-5-7-erdgeschoss.md
2026-04-17 21:15:07 +02:00

975 lines
30 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Sprint 5-7: Erdgeschoss — Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Four fully interactive ground-floor rooms (Reception, Gift Shop, Restaurant, Emergency Room) with horizontal room-to-room navigation and an ambulance drive-in animation.
**Architecture:** Floor 0 rooms are laid out side-by-side at 1280 px intervals along the X axis. `RoomNavigator` is extended to tween the camera both horizontally (room index) and vertically (floor index). `NavigationArrow` objects placed at room boundaries handle left/right navigation. When `go_to_floor()` is called, the room resets to index 0. The ambulance in Emergency Room drives in automatically the first time the player navigates there.
**Tech Stack:** Godot 4.6.2, GDScript (static typing), placeholder ColorRect graphics, existing `InteractiveObject` + `DragDropComponent` base classes.
---
## File Map
| Action | File | Responsibility |
|--------|------|----------------|
| Modify | `scripts/systems/room_navigator.gd` | Add horizontal room navigation: `go_to_room(floor, room)` |
| Create | `scripts/objects/navigation_arrow.gd` | Tappable arrow navigating to `(target_floor, target_room)` |
| Create | `scenes/objects/NavigationArrow.tscn` | Visual placeholder (blue button + label) |
| Modify | `scenes/rooms/floor0/Reception.tscn` | Add bench ×2, bell, potted plant |
| Create | `scenes/rooms/floor0/GiftShop.tscn` | Shelf, counter, 4 interactive objects |
| Create | `scenes/rooms/floor0/Restaurant.tscn` | 3 tables, kitchen counter, 4 interactive objects |
| Create | `scripts/objects/ambulance.gd` | Drive-in/out animation, triggered by `RoomNavigator.room_changed` |
| Create | `scenes/objects/Ambulance.tscn` | ColorRect-based ambulance visual |
| Create | `scenes/rooms/floor0/EmergencyRoom.tscn` | Ambulance bay, medical table, IV stand, 2 interactive objects |
| Modify | `scenes/main/Main.tscn` | Add 4 rooms to Floor0, navigation arrows, elevator reposition |
**Room layout in Floor0 (local X positions):**
- Reception: x=0 (room index 0), camera center world (640, 360)
- GiftShop: x=1280 (room index 1), camera center world (1920, 360)
- Restaurant: x=2560 (room index 2), camera center world (3200, 360)
- EmergencyRoom: x=3840 (room index 3), camera center world (4480, 360)
---
## Task 1: Extend RoomNavigator for horizontal room navigation
**Files:**
- Modify: `scripts/systems/room_navigator.gd`
- [ ] **Step 1: Replace room_navigator.gd**
Full file replacement:
```gdscript
## RoomNavigator — autoload that moves the Camera2D smoothly between hospital floors and rooms.
extends Node
signal room_changed(floor_index: int, room_index: int)
const FLOOR_HEIGHT: float = 720.0
const ROOM_WIDTH: float = 1280.0
const CAMERA_TWEEN_DURATION: float = 0.6
var _current_floor: int = 0
var _current_room: int = 0
var _camera: Camera2D
func initialize(camera: Camera2D) -> void:
_camera = camera
func go_to_floor(floor_index: int) -> void:
go_to_room(floor_index, 0)
func go_to_room(floor_index: int, room_index: int) -> void:
if _camera == null:
return
if floor_index == _current_floor and room_index == _current_room:
return
_current_floor = floor_index
_current_room = room_index
var target_x: float = room_index * ROOM_WIDTH + ROOM_WIDTH * 0.5
var target_y: float = floor_index * -FLOOR_HEIGHT + FLOOR_HEIGHT * 0.5
var tween: Tween = create_tween()
tween.set_ease(Tween.EASE_IN_OUT)
tween.set_trans(Tween.TRANS_SINE)
tween.tween_property(_camera, "position", Vector2(target_x, target_y), CAMERA_TWEEN_DURATION)
tween.finished.connect(func() -> void: room_changed.emit(floor_index, room_index))
func get_current_floor() -> int:
return _current_floor
func get_current_room() -> int:
return _current_room
```
- [ ] **Step 2: Commit**
```bash
cd "F:/Development/_gameDev/Cozypaw-Hospital"
git add scripts/systems/room_navigator.gd
git commit -m "feat(navigation): extend RoomNavigator for horizontal room-within-floor navigation"
```
---
## Task 2: NavigationArrow component
**Files:**
- Create: `scripts/objects/navigation_arrow.gd`
- Create: `scenes/objects/NavigationArrow.tscn`
- [ ] **Step 1: Create navigation_arrow.gd**
```gdscript
## NavigationArrow — tappable button that navigates camera to a specific floor and room.
class_name NavigationArrow extends Node2D
const BUTTON_HALF_SIZE: float = 48.0
@export var target_floor: int = 0
@export var target_room: int = 0
@export var label_text: String = ""
func _ready() -> void:
var label: Label = get_node_or_null("Label") as Label
if label != null:
label.text = label_text
func _input(event: InputEvent) -> void:
var screen_pos: Vector2
if event is InputEventScreenTouch and event.pressed:
screen_pos = event.position
elif event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
screen_pos = event.position
else:
return
var canvas_transform: Transform2D = get_viewport().get_canvas_transform()
var world_pos: Vector2 = canvas_transform.affine_inverse() * screen_pos
var local_pos: Vector2 = to_local(world_pos)
if abs(local_pos.x) <= BUTTON_HALF_SIZE and abs(local_pos.y) <= BUTTON_HALF_SIZE:
_on_pressed()
func _on_pressed() -> void:
RoomNavigator.go_to_room(target_floor, target_room)
_play_bounce()
func _play_bounce() -> void:
var tween: Tween = create_tween()
tween.tween_property(self, "scale", Vector2(1.15, 1.15), 0.08)
tween.tween_property(self, "scale", Vector2(1.0, 1.0), 0.08)
```
- [ ] **Step 2: Create NavigationArrow.tscn**
```
[gd_scene load_steps=2 format=3 uid="uid://cozypaw_navarrow"]
[ext_resource type="Script" path="res://scripts/objects/navigation_arrow.gd" id="1_navarrow"]
[node name="NavigationArrow" type="Node2D"]
script = ExtResource("1_navarrow")
[node name="Body" type="ColorRect" parent="."]
color = Color(0.30, 0.60, 1.0, 0.85)
size = Vector2(96, 96)
position = Vector2(-48, -48)
[node name="Label" type="Label" parent="."]
offset_left = -24.0
offset_top = -18.0
offset_right = 24.0
offset_bottom = 18.0
text = "→"
theme_override_font_sizes/font_size = 36
horizontal_alignment = 1
vertical_alignment = 1
```
> Note: The "→" / "←" label is a placeholder. It will be replaced with a sprite icon in Sprint 15 (Polish).
- [ ] **Step 3: Commit**
```bash
git add scripts/objects/navigation_arrow.gd scenes/objects/NavigationArrow.tscn
git commit -m "feat(navigation): add NavigationArrow component for within-floor room navigation"
```
---
## Task 3: Complete Reception scene
**Files:**
- Modify: `scenes/rooms/floor0/Reception.tscn`
Current state: background, counter, floor, walls, one flower.
Add: waiting bench ×2 (with legs), bell on counter, potted plant in corner.
- [ ] **Step 1: Replace Reception.tscn**
```
[gd_scene load_steps=2 format=3 uid="uid://cozypaw_reception"]
[ext_resource type="PackedScene" path="res://scenes/objects/InteractiveObject.tscn" id="1_iobj"]
[node name="Reception" type="Node2D"]
[node name="Background" type="ColorRect" parent="."]
color = Color(0.78, 0.94, 0.80, 1)
size = Vector2(1280, 720)
position = Vector2(0, 0)
[node name="Floor" type="ColorRect" parent="."]
color = Color(0.88, 0.80, 0.68, 1)
size = Vector2(1280, 100)
position = Vector2(0, 620)
[node name="WallLeft" type="ColorRect" parent="."]
color = Color(0.92, 0.88, 0.82, 1)
size = Vector2(40, 620)
position = Vector2(0, 0)
[node name="WallRight" type="ColorRect" parent="."]
color = Color(0.92, 0.88, 0.82, 1)
size = Vector2(40, 620)
position = Vector2(1240, 0)
[node name="Counter" type="ColorRect" parent="."]
color = Color(0.55, 0.35, 0.18, 1)
size = Vector2(340, 80)
position = Vector2(460, 540)
[node name="CounterTop" type="ColorRect" parent="."]
color = Color(0.70, 0.50, 0.28, 1)
size = Vector2(340, 12)
position = Vector2(460, 528)
[node name="NumberDisplayFrame" type="ColorRect" parent="."]
color = Color(0.20, 0.20, 0.20, 1)
size = Vector2(120, 80)
position = Vector2(570, 445)
[node name="NumberDisplayScreen" type="ColorRect" parent="."]
color = Color(0.10, 0.80, 0.20, 1)
size = Vector2(100, 60)
position = Vector2(580, 455)
[node name="BenchLeft" type="ColorRect" parent="."]
color = Color(0.60, 0.40, 0.20, 1)
size = Vector2(180, 40)
position = Vector2(100, 578)
[node name="BenchLeftLeg1" type="ColorRect" parent="."]
color = Color(0.45, 0.28, 0.12, 1)
size = Vector2(16, 32)
position = Vector2(112, 618)
[node name="BenchLeftLeg2" type="ColorRect" parent="."]
color = Color(0.45, 0.28, 0.12, 1)
size = Vector2(16, 32)
position = Vector2(252, 618)
[node name="BenchRight" type="ColorRect" parent="."]
color = Color(0.60, 0.40, 0.20, 1)
size = Vector2(180, 40)
position = Vector2(940, 578)
[node name="BenchRightLeg1" type="ColorRect" parent="."]
color = Color(0.45, 0.28, 0.12, 1)
size = Vector2(16, 32)
position = Vector2(952, 618)
[node name="BenchRightLeg2" type="ColorRect" parent="."]
color = Color(0.45, 0.28, 0.12, 1)
size = Vector2(16, 32)
position = Vector2(1092, 618)
[node name="CharacterSpawn" type="Marker2D" parent="."]
position = Vector2(300, 520)
[node name="Flower" parent="." instance=ExtResource("1_iobj")]
position = Vector2(200, 560)
[node name="Bell" parent="." instance=ExtResource("1_iobj")]
position = Vector2(530, 510)
[node name="PottedPlant" parent="." instance=ExtResource("1_iobj")]
position = Vector2(1180, 560)
```
- [ ] **Step 2: Commit**
```bash
git add scenes/rooms/floor0/Reception.tscn
git commit -m "feat(reception): complete Reception with waiting benches, bell, and potted plant"
```
---
## Task 4: Gift Shop scene
**Files:**
- Create: `scenes/rooms/floor0/GiftShop.tscn`
- [ ] **Step 1: Create GiftShop.tscn**
```
[gd_scene load_steps=2 format=3 uid="uid://cozypaw_giftshop"]
[ext_resource type="PackedScene" path="res://scenes/objects/InteractiveObject.tscn" id="1_iobj"]
[node name="GiftShop" type="Node2D"]
[node name="Background" type="ColorRect" parent="."]
color = Color(1.0, 0.88, 0.92, 1)
size = Vector2(1280, 720)
position = Vector2(0, 0)
[node name="Floor" type="ColorRect" parent="."]
color = Color(0.88, 0.80, 0.68, 1)
size = Vector2(1280, 100)
position = Vector2(0, 620)
[node name="WallLeft" type="ColorRect" parent="."]
color = Color(0.96, 0.90, 0.90, 1)
size = Vector2(40, 620)
position = Vector2(0, 0)
[node name="WallRight" type="ColorRect" parent="."]
color = Color(0.96, 0.90, 0.90, 1)
size = Vector2(40, 620)
position = Vector2(1240, 0)
[node name="ShelfBoard" type="ColorRect" parent="."]
color = Color(0.75, 0.50, 0.25, 1)
size = Vector2(800, 20)
position = Vector2(240, 360)
[node name="ShelfLegLeft" type="ColorRect" parent="."]
color = Color(0.60, 0.38, 0.18, 1)
size = Vector2(16, 240)
position = Vector2(240, 380)
[node name="ShelfLegRight" type="ColorRect" parent="."]
color = Color(0.60, 0.38, 0.18, 1)
size = Vector2(16, 240)
position = Vector2(1024, 380)
[node name="Counter" type="ColorRect" parent="."]
color = Color(0.60, 0.38, 0.18, 1)
size = Vector2(240, 80)
position = Vector2(520, 540)
[node name="CounterTop" type="ColorRect" parent="."]
color = Color(0.75, 0.50, 0.25, 1)
size = Vector2(240, 12)
position = Vector2(520, 528)
[node name="CharacterSpawn" type="Marker2D" parent="."]
position = Vector2(300, 520)
[node name="FlowerBouquet" parent="." instance=ExtResource("1_iobj")]
position = Vector2(380, 330)
[node name="PlushToy" parent="." instance=ExtResource("1_iobj")]
position = Vector2(640, 330)
[node name="GiftCard" parent="." instance=ExtResource("1_iobj")]
position = Vector2(900, 330)
[node name="GiftBox" parent="." instance=ExtResource("1_iobj")]
position = Vector2(640, 510)
```
- [ ] **Step 2: Commit**
```bash
git add scenes/rooms/floor0/GiftShop.tscn
git commit -m "feat(giftshop): add Gift Shop room with shelf, counter, and interactive gift objects"
```
---
## Task 5: Restaurant scene
**Files:**
- Create: `scenes/rooms/floor0/Restaurant.tscn`
- [ ] **Step 1: Create Restaurant.tscn**
```
[gd_scene load_steps=2 format=3 uid="uid://cozypaw_restaurant"]
[ext_resource type="PackedScene" path="res://scenes/objects/InteractiveObject.tscn" id="1_iobj"]
[node name="Restaurant" type="Node2D"]
[node name="Background" type="ColorRect" parent="."]
color = Color(1.0, 0.95, 0.82, 1)
size = Vector2(1280, 720)
position = Vector2(0, 0)
[node name="Floor" type="ColorRect" parent="."]
color = Color(0.75, 0.65, 0.50, 1)
size = Vector2(1280, 100)
position = Vector2(0, 620)
[node name="WallLeft" type="ColorRect" parent="."]
color = Color(0.96, 0.92, 0.80, 1)
size = Vector2(40, 620)
position = Vector2(0, 0)
[node name="WallRight" type="ColorRect" parent="."]
color = Color(0.96, 0.92, 0.80, 1)
size = Vector2(40, 620)
position = Vector2(1240, 0)
[node name="KitchenCounter" type="ColorRect" parent="."]
color = Color(0.55, 0.35, 0.18, 1)
size = Vector2(360, 80)
position = Vector2(460, 240)
[node name="KitchenCounterTop" type="ColorRect" parent="."]
color = Color(0.70, 0.50, 0.28, 1)
size = Vector2(360, 12)
position = Vector2(460, 228)
[node name="Table1" type="ColorRect" parent="."]
color = Color(0.65, 0.42, 0.20, 1)
size = Vector2(200, 20)
position = Vector2(120, 520)
[node name="Table1Leg1" type="ColorRect" parent="."]
color = Color(0.50, 0.32, 0.15, 1)
size = Vector2(16, 100)
position = Vector2(140, 540)
[node name="Table1Leg2" type="ColorRect" parent="."]
color = Color(0.50, 0.32, 0.15, 1)
size = Vector2(16, 100)
position = Vector2(304, 540)
[node name="Table2" type="ColorRect" parent="."]
color = Color(0.65, 0.42, 0.20, 1)
size = Vector2(200, 20)
position = Vector2(540, 520)
[node name="Table2Leg1" type="ColorRect" parent="."]
color = Color(0.50, 0.32, 0.15, 1)
size = Vector2(16, 100)
position = Vector2(560, 540)
[node name="Table2Leg2" type="ColorRect" parent="."]
color = Color(0.50, 0.32, 0.15, 1)
size = Vector2(16, 100)
position = Vector2(724, 540)
[node name="Table3" type="ColorRect" parent="."]
color = Color(0.65, 0.42, 0.20, 1)
size = Vector2(200, 20)
position = Vector2(960, 520)
[node name="Table3Leg1" type="ColorRect" parent="."]
color = Color(0.50, 0.32, 0.15, 1)
size = Vector2(16, 100)
position = Vector2(980, 540)
[node name="Table3Leg2" type="ColorRect" parent="."]
color = Color(0.50, 0.32, 0.15, 1)
size = Vector2(16, 100)
position = Vector2(1144, 540)
[node name="CharacterSpawn" type="Marker2D" parent="."]
position = Vector2(300, 490)
[node name="SoupBowl" parent="." instance=ExtResource("1_iobj")]
position = Vector2(220, 490)
[node name="Sandwich" parent="." instance=ExtResource("1_iobj")]
position = Vector2(640, 490)
[node name="JuiceGlass" parent="." instance=ExtResource("1_iobj")]
position = Vector2(1060, 490)
[node name="CashRegister" parent="." instance=ExtResource("1_iobj")]
position = Vector2(640, 210)
```
- [ ] **Step 2: Commit**
```bash
git add scenes/rooms/floor0/Restaurant.tscn
git commit -m "feat(restaurant): add Restaurant room with three tables and interactive food objects"
```
---
## Task 6: Ambulance component
**Files:**
- Create: `scripts/objects/ambulance.gd`
- Create: `scenes/objects/Ambulance.tscn`
The ambulance starts off-screen to the right. When `RoomNavigator` emits `room_changed(0, 3)` (Emergency Room), it drives in. Tapping the ambulance drives it back out; tapping again drives it back in.
- [ ] **Step 1: Create ambulance.gd**
```gdscript
## Ambulance — drives in from off-screen right when the Emergency Room is entered; tap to toggle.
class_name Ambulance extends Node2D
const OFFSCREEN_OFFSET: float = 1200.0
const BUTTON_HALF_WIDTH: float = 90.0
const BUTTON_HALF_HEIGHT: float = 50.0
const DRIVE_DURATION: float = 1.2
@export var trigger_floor: int = 0
@export var trigger_room: int = 3
var _parked_x: float = 0.0
var _is_parked: bool = false
var _is_animating: bool = false
func _ready() -> void:
_parked_x = position.x
position.x = _parked_x + OFFSCREEN_OFFSET
RoomNavigator.room_changed.connect(_on_room_changed)
func _exit_tree() -> void:
if RoomNavigator.room_changed.is_connected(_on_room_changed):
RoomNavigator.room_changed.disconnect(_on_room_changed)
func _on_room_changed(floor_index: int, room_index: int) -> void:
if floor_index == trigger_floor and room_index == trigger_room:
if not _is_parked and not _is_animating:
_drive_in()
func _input(event: InputEvent) -> void:
if _is_animating:
return
var screen_pos: Vector2
if event is InputEventScreenTouch and event.pressed:
screen_pos = event.position
elif event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
screen_pos = event.position
else:
return
var canvas_transform: Transform2D = get_viewport().get_canvas_transform()
var world_pos: Vector2 = canvas_transform.affine_inverse() * screen_pos
var local_pos: Vector2 = to_local(world_pos)
if abs(local_pos.x) <= BUTTON_HALF_WIDTH and abs(local_pos.y) <= BUTTON_HALF_HEIGHT:
if _is_parked:
_drive_out()
else:
_drive_in()
func _drive_in() -> void:
_is_animating = true
_is_parked = false
var tween: Tween = create_tween()
tween.set_ease(Tween.EASE_OUT)
tween.set_trans(Tween.TRANS_QUAD)
tween.tween_property(self, "position:x", _parked_x, DRIVE_DURATION)
tween.finished.connect(func() -> void:
_is_parked = true
_is_animating = false
_play_stop_bounce()
)
func _drive_out() -> void:
_is_animating = true
_is_parked = false
var tween: Tween = create_tween()
tween.set_ease(Tween.EASE_IN)
tween.set_trans(Tween.TRANS_QUAD)
tween.tween_property(self, "position:x", _parked_x + OFFSCREEN_OFFSET, DRIVE_DURATION)
tween.finished.connect(func() -> void:
_is_animating = false
)
func _play_stop_bounce() -> void:
var tween: Tween = create_tween()
tween.tween_property(self, "scale", Vector2(1.08, 0.94), 0.08)
tween.tween_property(self, "scale", Vector2(0.96, 1.06), 0.08)
tween.tween_property(self, "scale", Vector2(1.0, 1.0), 0.08)
```
- [ ] **Step 2: Create Ambulance.tscn**
```
[gd_scene load_steps=2 format=3 uid="uid://cozypaw_ambulance"]
[ext_resource type="Script" path="res://scripts/objects/ambulance.gd" id="1_ambulance"]
[node name="Ambulance" type="Node2D"]
script = ExtResource("1_ambulance")
[node name="Body" type="ColorRect" parent="."]
color = Color(1.0, 1.0, 1.0, 1)
size = Vector2(180, 100)
position = Vector2(-90, -50)
[node name="RedStripe" type="ColorRect" parent="."]
color = Color(0.90, 0.15, 0.15, 1)
size = Vector2(180, 20)
position = Vector2(-90, -15)
[node name="Cabin" type="ColorRect" parent="."]
color = Color(0.82, 0.85, 0.90, 1)
size = Vector2(70, 60)
position = Vector2(-90, -50)
[node name="WindowFront" type="ColorRect" parent="."]
color = Color(0.60, 0.85, 1.0, 1)
size = Vector2(50, 38)
position = Vector2(-82, -46)
[node name="WheelFront" type="ColorRect" parent="."]
color = Color(0.15, 0.15, 0.15, 1)
size = Vector2(30, 30)
position = Vector2(-75, 48)
[node name="WheelBack" type="ColorRect" parent="."]
color = Color(0.15, 0.15, 0.15, 1)
size = Vector2(30, 30)
position = Vector2(50, 48)
[node name="Siren" type="ColorRect" parent="."]
color = Color(0.10, 0.40, 1.0, 1)
size = Vector2(40, 18)
position = Vector2(-20, -68)
```
- [ ] **Step 3: Commit**
```bash
git add scripts/objects/ambulance.gd scenes/objects/Ambulance.tscn
git commit -m "feat(ambulance): add Ambulance component with drive-in/out animation triggered by room navigation"
```
---
## Task 7: Emergency Room scene
**Files:**
- Create: `scenes/rooms/floor0/EmergencyRoom.tscn`
The Ambulance node is placed at position (500, 570) within the room. Its `_ready()` stores `_parked_x = 500` and shifts it to x = 500 + 1200 = 1700 (off-screen right). It drives in when `room_changed(0, 3)` fires.
- [ ] **Step 1: Create EmergencyRoom.tscn**
```
[gd_scene load_steps=3 format=3 uid="uid://cozypaw_emergency"]
[ext_resource type="PackedScene" path="res://scenes/objects/InteractiveObject.tscn" id="1_iobj"]
[ext_resource type="PackedScene" path="res://scenes/objects/Ambulance.tscn" id="2_ambulance"]
[node name="EmergencyRoom" type="Node2D"]
[node name="Background" type="ColorRect" parent="."]
color = Color(0.88, 0.94, 1.0, 1)
size = Vector2(1280, 720)
position = Vector2(0, 0)
[node name="Floor" type="ColorRect" parent="."]
color = Color(0.72, 0.74, 0.80, 1)
size = Vector2(1280, 100)
position = Vector2(0, 620)
[node name="WallLeft" type="ColorRect" parent="."]
color = Color(0.90, 0.92, 0.96, 1)
size = Vector2(40, 620)
position = Vector2(0, 0)
[node name="WallRight" type="ColorRect" parent="."]
color = Color(0.90, 0.92, 0.96, 1)
size = Vector2(40, 620)
position = Vector2(1240, 0)
[node name="AmbulanceBay" type="ColorRect" parent="."]
color = Color(0.58, 0.60, 0.68, 1)
size = Vector2(380, 120)
position = Vector2(860, 500)
[node name="AmbulanceBayLine" type="ColorRect" parent="."]
color = Color(0.90, 0.80, 0.10, 1)
size = Vector2(380, 6)
position = Vector2(860, 500)
[node name="MedicalTable" type="ColorRect" parent="."]
color = Color(0.85, 0.85, 0.92, 1)
size = Vector2(260, 30)
position = Vector2(180, 490)
[node name="MedicalTableLeg1" type="ColorRect" parent="."]
color = Color(0.68, 0.68, 0.76, 1)
size = Vector2(16, 130)
position = Vector2(200, 520)
[node name="MedicalTableLeg2" type="ColorRect" parent="."]
color = Color(0.68, 0.68, 0.76, 1)
size = Vector2(16, 130)
position = Vector2(408, 520)
[node name="IVPole" type="ColorRect" parent="."]
color = Color(0.78, 0.78, 0.84, 1)
size = Vector2(10, 220)
position = Vector2(545, 350)
[node name="IVBag" type="ColorRect" parent="."]
color = Color(0.55, 0.85, 0.95, 1)
size = Vector2(50, 70)
position = Vector2(525, 280)
[node name="CharacterSpawn" type="Marker2D" parent="."]
position = Vector2(310, 490)
[node name="Stretcher" parent="." instance=ExtResource("1_iobj")]
position = Vector2(680, 490)
[node name="IVStand" parent="." instance=ExtResource("1_iobj")]
position = Vector2(550, 440)
[node name="Ambulance" parent="." instance=ExtResource("2_ambulance")]
position = Vector2(500, 570)
```
- [ ] **Step 2: Commit**
```bash
git add scenes/rooms/floor0/EmergencyRoom.tscn
git commit -m "feat(emergency): add Emergency Room scene with ambulance bay, medical table, and interactive objects"
```
---
## Task 8: Wire up Floor 0 in Main.tscn
**Files:**
- Modify: `scenes/main/Main.tscn`
**Changes:**
- Add GiftShop, Restaurant, EmergencyRoom as instances at x offsets 1280, 2560, 3840 in Floor0
- Move ElevatorUp0 to position (1100, 160) to avoid overlap with navigation arrows
- Add 6 NavigationArrow instances at room boundaries (3 pairs)
- `load_steps` changes from 9 → 13 (add 4 new ExtResources)
**NavigationArrow positions in Floor0 local space:**
| Node name | X | Y | target_floor | target_room | label |
|-----------|---|---|---|---|---|
| NavRight0to1 | 1200 | 480 | 0 | 1 | → |
| NavLeft1to0 | 1340 | 480 | 0 | 0 | ← |
| NavRight1to2 | 2480 | 480 | 0 | 2 | → |
| NavLeft2to1 | 2600 | 480 | 0 | 1 | ← |
| NavRight2to3 | 3760 | 480 | 0 | 3 | → |
| NavLeft3to2 | 3920 | 480 | 0 | 2 | ← |
**Visibility verification (camera center ± 640 horizontal):**
- Room 0 (cam x=640): screen x 01280 → NavRight0to1 at 1200 ✓, elevator at 1100 ✓
- Room 1 (cam x=1920): screen x 12802560 → NavLeft1to0 at 1340 ✓, NavRight1to2 at 2480 ✓
- Room 2 (cam x=3200): screen x 25603840 → NavLeft2to1 at 2600 ✓, NavRight2to3 at 3760 ✓
- Room 3 (cam x=4480): screen x 38405120 → NavLeft3to2 at 3920 ✓
- [ ] **Step 1: Replace Main.tscn**
```
[gd_scene load_steps=13 format=3 uid="uid://cozypaw_main"]
[ext_resource type="Script" path="res://scripts/main/main.gd" id="1_main"]
[ext_resource type="PackedScene" path="res://scenes/rooms/floor0/Reception.tscn" id="2_reception"]
[ext_resource type="PackedScene" path="res://scenes/characters/Character.tscn" id="3_char"]
[ext_resource type="PackedScene" path="res://scenes/ui/HUD.tscn" id="4_hud"]
[ext_resource type="PackedScene" path="res://scenes/ui/SettingsMenu.tscn" id="5_settings"]
[ext_resource type="PackedScene" path="res://scenes/objects/ElevatorButton.tscn" id="6_elevbtn"]
[ext_resource type="Script" path="res://scripts/characters/character_data.gd" id="7_chardata"]
[ext_resource type="PackedScene" path="res://scenes/rooms/floor0/GiftShop.tscn" id="8_giftshop"]
[ext_resource type="PackedScene" path="res://scenes/rooms/floor0/Restaurant.tscn" id="9_restaurant"]
[ext_resource type="PackedScene" path="res://scenes/rooms/floor0/EmergencyRoom.tscn" id="10_emergency"]
[ext_resource type="PackedScene" path="res://scenes/objects/NavigationArrow.tscn" id="11_navarrow"]
[sub_resource type="Resource" id="CharacterData_bunny1"]
script = ExtResource("7_chardata")
id = "bunny_01"
display_name = "Bunny"
species = 0
state = 0
current_floor = 0
position = Vector2(0, 0)
[node name="Main" type="Node2D"]
script = ExtResource("1_main")
[node name="Camera2D" type="Camera2D" parent="."]
position = Vector2(640, 360)
zoom = Vector2(1, 1)
[node name="Hospital" type="Node2D" parent="."]
[node name="Floor0" type="Node2D" parent="Hospital"]
position = Vector2(0, 0)
[node name="Reception" parent="Hospital/Floor0" instance=ExtResource("2_reception")]
position = Vector2(0, 0)
[node name="GiftShop" parent="Hospital/Floor0" instance=ExtResource("8_giftshop")]
position = Vector2(1280, 0)
[node name="Restaurant" parent="Hospital/Floor0" instance=ExtResource("9_restaurant")]
position = Vector2(2560, 0)
[node name="EmergencyRoom" parent="Hospital/Floor0" instance=ExtResource("10_emergency")]
position = Vector2(3840, 0)
[node name="ElevatorUp0" parent="Hospital/Floor0" instance=ExtResource("6_elevbtn")]
position = Vector2(1100, 160)
target_floor = 1
[node name="NavRight0to1" parent="Hospital/Floor0" instance=ExtResource("11_navarrow")]
position = Vector2(1200, 480)
target_floor = 0
target_room = 1
label_text = "→"
[node name="NavLeft1to0" parent="Hospital/Floor0" instance=ExtResource("11_navarrow")]
position = Vector2(1340, 480)
target_floor = 0
target_room = 0
label_text = "←"
[node name="NavRight1to2" parent="Hospital/Floor0" instance=ExtResource("11_navarrow")]
position = Vector2(2480, 480)
target_floor = 0
target_room = 2
label_text = "→"
[node name="NavLeft2to1" parent="Hospital/Floor0" instance=ExtResource("11_navarrow")]
position = Vector2(2600, 480)
target_floor = 0
target_room = 1
label_text = "←"
[node name="NavRight2to3" parent="Hospital/Floor0" instance=ExtResource("11_navarrow")]
position = Vector2(3760, 480)
target_floor = 0
target_room = 3
label_text = "→"
[node name="NavLeft3to2" parent="Hospital/Floor0" instance=ExtResource("11_navarrow")]
position = Vector2(3920, 480)
target_floor = 0
target_room = 2
label_text = "←"
[node name="Floor1" type="Node2D" parent="Hospital"]
position = Vector2(0, -720)
[node name="Background" type="ColorRect" parent="Hospital/Floor1"]
color = Color(0.78, 0.88, 0.96, 1)
size = Vector2(1280, 720)
position = Vector2(0, 0)
[node name="FloorLabel" type="Label" parent="Hospital/Floor1"]
offset_left = 560.0
offset_top = 300.0
offset_right = 720.0
offset_bottom = 360.0
text = "1. OG"
theme_override_font_sizes/font_size = 32
[node name="FloorRect" type="ColorRect" parent="Hospital/Floor1"]
color = Color(0.88, 0.80, 0.68, 1)
size = Vector2(1280, 100)
position = Vector2(0, 620)
[node name="ElevatorDown1" parent="Hospital/Floor1" instance=ExtResource("6_elevbtn")]
position = Vector2(1200, 540)
target_floor = 0
[node name="ElevatorUp1" parent="Hospital/Floor1" instance=ExtResource("6_elevbtn")]
position = Vector2(1200, 180)
target_floor = 2
[node name="Floor2" type="Node2D" parent="Hospital"]
position = Vector2(0, -1440)
[node name="Background" type="ColorRect" parent="Hospital/Floor2"]
color = Color(0.96, 0.88, 0.96, 1)
size = Vector2(1280, 720)
position = Vector2(0, 0)
[node name="FloorLabel" type="Label" parent="Hospital/Floor2"]
offset_left = 560.0
offset_top = 300.0
offset_right = 720.0
offset_bottom = 360.0
text = "2. OG"
theme_override_font_sizes/font_size = 32
[node name="FloorRect" type="ColorRect" parent="Hospital/Floor2"]
color = Color(0.88, 0.80, 0.68, 1)
size = Vector2(1280, 100)
position = Vector2(0, 620)
[node name="ElevatorDown2" parent="Hospital/Floor2" instance=ExtResource("6_elevbtn")]
position = Vector2(1200, 360)
target_floor = 1
[node name="Characters" type="Node2D" parent="."]
[node name="Bunny1" parent="Characters" instance=ExtResource("3_char")]
position = Vector2(300, 400)
data = SubResource("CharacterData_bunny1")
[node name="UI" type="CanvasLayer" parent="."]
[node name="HUD" parent="UI" instance=ExtResource("4_hud")]
[node name="SettingsMenu" parent="UI" instance=ExtResource("5_settings")]
```
- [ ] **Step 2: Commit**
```bash
git add scenes/main/Main.tscn
git commit -m "feat(floor0): wire up all four ground-floor rooms with horizontal navigation arrows"
```
- [ ] **Step 3: Push to develop**
```bash
git push origin develop
```
---
## Self-Review: Spec Coverage Check
| Sprint 5-7 requirement | Covered by |
|------------------------|-----------|
| Empfang komplett | Task 3: bench ×2, bell, potted plant, number display |
| Geschenke-Shop | Task 4: full scene with shelf, 4 interactive objects |
| Restaurant | Task 5: full scene with 3 tables, 4 interactive objects |
| Notaufnahme | Task 7: full scene with ambulance bay, table, IV stand |
| Krankenwagen-Animation | Task 6: drive-in on room_changed, drive-out on tap |
| Horizontal room navigation | Task 1 + 2: RoomNavigator + NavigationArrow |
| All rooms accessible from game | Task 8: all wired up in Main.tscn |
**Placeholder scan:** All code blocks are complete. No "TBD" or "implement later" present. UIDs are convention-based and may be regenerated by Godot on first open — this is expected behavior.
**Type consistency:** `room_changed(floor_index: int, room_index: int)` signal defined in Task 1 and consumed in Task 6 (`_on_room_changed`). ✓ `go_to_room(floor_index: int, room_index: int)` defined in Task 1 and called in Task 2 (`NavigationArrow._on_pressed()`). ✓
---
## Smoke Test Checklist (manual, on device after completion)
- [ ] Game starts at Reception (camera center visible, green background)
- [ ] "→" arrow in Reception navigates smoothly to Gift Shop
- [ ] "←" arrow in Gift Shop navigates back to Reception
- [ ] Full chain: Reception → Gift Shop → Restaurant → Emergency works both directions
- [ ] Elevator Up from Reception navigates to Floor 1
- [ ] Elevator Down from Floor 1 lands at Reception (room 0), not Emergency Room
- [ ] Tapping flower/bell in Reception plays bounce animation
- [ ] Navigating to Emergency Room for the first time: ambulance drives in from right
- [ ] Tapping ambulance after it's parked: drives back out
- [ ] Tapping ambulance again: drives back in
- [ ] Dragging Bunny character across rooms works correctly
- [ ] Save/load preserves Bunny position after app restart