Files
Cozypaw-Hospital/docs/game-design.md
T

18 KiB
Raw Blame History

Cozypaw Hospital — Game Design Document (GDD)

Dieses Dokument ist die einzige Quelle der Wahrheit für das Spiel-Design. Sprint-Specs und Implementierungspläne werden daraus abgeleitet. Änderungen hier zuerst besprechen, dann in Sprint-Specs übernehmen.

Zuletzt aktualisiert: 2026-05-07


Kapitel 1 — Vision & Prinzipien

Kern-Idee

Genre: Digitales Puppenhaus / Pretend Play. Sandbox — kein Ziel, kein Scheitern, kein Scoring.

Zielgruppe: Kinder ab 3 Jahren. Primär auf Tablet (Android zuerst, iOS später).

Kern-Fantasie: Ich bin Arzt oder Schwester in einem Tier-Krankenhaus. Ich entscheide, wer wo liegt, wer behandelt wird, wer ein Baby bekommt. Ich erzähle mir meine eigene Geschichte.

Nicht-Verhandelbare Prinzipien

Diese Punkte werden in keinem Sprint, keiner Spec und keinem PR geändert:

  1. Keine Werbung — keine Ad-SDKs, kein AdMob, keine Rewarded Ads
  2. Keine Datensammlung — keine Analytics, kein Tracking, keine Telemetrie
  3. Offline-first — vollständig ohne Internetverbindung spielbar
  4. Keine In-App-Käufe — kein Premium-Content, keine Währungen
  5. Keine Achievements / Scoring — kein Sterne-System, kein Freischalten durch Sammeln
  6. Garten von Anfang an offen — kein Unlock-Gate
  7. Keine Gift-Mechaniken — alle Medikamente sind positiv/neutral
  8. COPPA/DSGVO-konform — Play Store Data Safety: "Keine Daten erhoben"
  9. Kein Text in der Spielwelt — Icons, Symbole, Farben statt Beschriftungen
  10. Minimum Touch-Target 64dp — für Kinder-Finger

Was wir besser machen als das Original (Yasa Pets Hospital)

Original Cozypaw
Werbung zwischen Räumen Keine Werbung
Firebase Analytics Kein Tracking
Grüne Giftflaschen machen krank Alle Medikamente positiv
Garten erst nach Sternen freischaltbar Von Anfang an offen
Kleine Touch-Targets Mind. 64dp
Generische Figuren Figuren basieren auf Haustieren der Kinder

Kapitel 2 — Welt & Räume

Struktur

3 Etagen + Gartenbereich. Navigation:

  • Innerhalb einer Etage: Camera-Pan per NavigationArrow
  • Zwischen Etagen: Aufzug-Button + RoomNavigator (Camera-Tween)
  • Garten: HomeButton — wechselt Hospital ↔ Garten

Raum-Übersicht

Etage Raum Scene Room-Chest Inhalt Besondere Interaktion
EG Empfang Reception.tscn Blumensträuße, Nummerntickets Wartenummer-Automat: Tap → Ticket spawnt
EG Geschenke-Shop GiftShop.tscn Geschenkkörbe, Kuscheltiere, Grußkarten
EG Restaurant Restaurant.tscn Mahlzeit-Tabletts × 3, Getränke Tablett auf Tisch stellen
EG Notaufnahme EmergencyRoom.tscn Trage, Verbandsmaterial Ambulanz-Türen öffnen → Trage herausziehen
1.OG Röntgen XRay.tscn Gips-Set, Röntgenfotos Figur auf Tisch → Röntgenbild → Gips per Drag anlegen
1.OG Apotheke Pharmacy.tscn Medikamentenflaschen × 3, Tüten Flasche auf Figur → Figur wird gesünder
1.OG Labor Lab.tscn Reagenzgläser × 2, Mikroskop-Slides Slide in Mikroskop → Bild wechselt
1.OG Patientenzimmer PatientRoom.tscn Kissen, Infusionsbeutel, TV-Fernbedienung IV-Bag an Haken + Figur im Bett → SLEEPING
2.OG Ultraschall Ultrasound.tscn Gel-Tube, Ultraschall-Sonde Sonde an PREGNANT → Bildschirm zeigt Fötus
2.OG Kreißsaal DeliveryRoom.tscn Baby-Decke, Windeln DeliveryBed: PREGNANT rein → BABY spawnt
2.OG Säuglingsstation Nursery.tscn Fläschchen, Rassel, Schnuller Wiege schaukeln; Fläschchen an BABY → trinkt
Garten Gartenparty GardenParty.tscn Tassen, Kuchen, Luftballons GiftBox: Tap → öffnet; TeaPot: Tap → gießt

Kapitel 3 — Figurensystem

Roster MVP (8 Figuren)

ID Spezies Rolle Start-State
bunny_f Häschen Patientin / Mutter HEALTHY
bunny_m Häschen Patient / Besucher HEALTHY
kitten_f Kätzchen Patientin HEALTHY
kitten_m Kätzchen Patient HEALTHY
bunny_baby Häschen Baby BABY
kitten_baby Kätzchen Baby BABY
fox_doctor Fuchs Arzt HEALTHY
owl_nurse Eule Krankenschwester HEALTHY

Zustände

Bereits in CharacterData.State implementiert:

HEALTHY → SICK → HEALTHY  (durch Medikament)
HEALTHY → PREGNANT → (DeliveryBed) → HEALTHY + BABY spawnt
HEALTHY / SICK → SLEEPING  (durch IV-Bag oder Bett)
SLEEPING → HEALTHY  (nach Interaktion)
HEALTHY → TIRED  (kann in Bett gelegt werden)

Animations-States (AnimatedSprite2D)

State Trigger Frames
idle Default, kein Snap, nicht gehalten 4 — atmet, blinzelt (loop)
held DragDropComponent aktiv 2 — Arme leicht seitlich
sitting Snap auf Stuhl / Hocker / Theke 2 — aufrecht sitzend
lying Snap auf Bett / Tisch / Trage 2 — flach liegend
happy Interaktion erfolgreich abgeschlossen 4 — hüpft/jubelt (einmalig, dann idle)
sleeping State = SLEEPING 4 — Augen zu, langsamer Atem (loop)

Node-Struktur

Character (Node2D)               class_name Character
├── DragDropComponent             ← Drag & Drop (bestehend)
├── SnapReceiver (Node2D)         ← NEU: scannt SnapPoints beim Loslassen
├── AnimatedSprite2D              ← NEU: ersetzt ColorRect-Placeholder
├── OutfitLayer1 (Sprite2D)       ← NEU: Kleidung (Kittel, Patientenhemd)
├── OutfitLayer2 (Sprite2D)       ← NEU: Medizinisch (Gips, Verband)
├── OutfitLayer3 (Sprite2D)       ← NEU: Accessoire (Stethoskop, Mütze)
├── HandLeft (Node2D)             ← NEU: Attachment-Point links
│   └── HeldItem (Node2D)         ←   aktuell gehaltenes Item (oder leer)
├── HandRight (Node2D)            ← NEU: Attachment-Point rechts
│   └── HeldItem (Node2D)
└── CollisionArea (Area2D)        ← bestehend

Outfit-Regeln

Ein OutfitItem hat layer: int (13). Per Drag auf eine Figur gezogen → Layer-Sprite wechselt auf das Item-Bild, Item verschwindet aus der Welt. Tap auf aktiven OutfitLayer → Item fällt neben Figur zurück in die Welt. Outfit wird in CharacterData als outfit: Array[String] (3 Einträge, leer = kein Outfit) gespeichert.


Kapitel 4 — Objekt-Katalog

Kategorien

Typ Beschreibung
Möbel / Snap-Host Statisch, hat einen oder mehrere SnapPoints für Figuren
Holdable Item Kann aufgehoben und in einen Hand-Slot gelegt werden
Outfit Item Holdable + per Drag auf Figur anwendbar (belegt Outfit-Layer)
Maschine Nimmt Figur oder Item auf → produziert Ausgabe
Spawner Tap → neues Item-Exemplar erscheint in der Welt
Applier Auf Figur gezogen → ändert State oder spielt Animation

Vollständige Liste (~55 Objekte)

EG — Empfang (6)

  • queue_machine — Spawner: Tap → number_ticket spawnt
  • number_ticket — Holdable
  • reception_desk — Snap-Host (Pose: sitting)
  • waiting_chair × 3 — Snap-Host (Pose: sitting)

EG — Geschenke-Shop (4)

  • gift_basket — Holdable
  • plush_toy — Holdable
  • greeting_card — Holdable
  • shop_counter — Snap-Host (Pose: sitting)

EG — Restaurant (5)

  • meal_tray_1/2/3 — Holdable (3 Mahlzeit-Varianten)
  • drink_cup — Holdable
  • dining_table — Snap-Host (Pose: sitting)

EG — Notaufnahme (4)

  • ambulance — Maschine: Türen öffnen → Trage sichtbar (bereits impl.)
  • stretcher — Holdable + Snap-Host (Pose: lying)
  • bandage_roll — Outfit Item (Layer 2: Verband)
  • er_table — Snap-Host (Pose: lying)

1.OG — Röntgen (5)

  • xray_machine — Maschine: Figur auf Tisch → Röntgenbild (bereits impl.)
  • xray_photo — Holdable (result item, spawnt nach Röntgen)
  • cast_machine — Maschine: Figur rein → legt Gips-Outfit an
  • cast_arm — Outfit Item (Layer 2: Gips)
  • xray_table — Snap-Host (Pose: lying)

1.OG — Apotheke (4)

  • medicine_bottle_red/blue/yellow — Applier: auf Figur → State = HEALTHY + happy
  • medicine_bag — Holdable
  • pharmacy_counter — Snap-Host (Pose: sitting)

1.OG — Labor (4)

  • microscope — Maschine: Slide in Slot → Bild wechselt
  • test_tube × 2 — Holdable
  • microscope_slide — Holdable → passt in microscope-Slot
  • lab_stool — Snap-Host (Pose: sitting)

1.OG — Patientenzimmer (6)

  • patient_bed × 2 — Snap-Host (Pose: lying) (bereits impl.)
  • iv_bag — Holdable + Applier: in IV-Hook gehängt + Figur im Bett → State = SLEEPING
  • iv_hook — Slot an patient_bed, nimmt iv_bag auf
  • tv_remote — Holdable
  • pillow — Holdable
  • bedside_table — Snap-Host (Pose: sitting)

2.OG — Ultraschall (5)

  • ultrasound_machine — Maschine (bereits impl.)
  • ultrasound_probe — Holdable + Applier: auf PREGNANT-Figur auf Tisch → Bildschirm zeigt Fötus
  • gel_tube — Holdable
  • exam_table — Snap-Host (Pose: lying)
  • ultrasound_screen — reagiert auf Probe-Nähe (Kind des ultrasound_machine)

2.OG — Kreißsaal (4)

  • delivery_bed — Maschine: PREGNANT eingerastet → BABY spawnt (bereits impl.)
  • baby_blanket — Holdable
  • diaper — Outfit Item für BABY (Layer 1)
  • baby_scale — Snap-Host (Pose: lying, nur BABY-Figuren)

2.OG — Säuglingsstation (5)

  • cradle × 2 — Snap-Host (Pose: lying) (bereits impl.)
  • baby_bottle — Holdable + Applier: auf BABY → happy-Animation + Trink-SFX
  • rattle — Holdable
  • pacifier — Outfit Item für BABY (Layer 3)
  • incubator — Snap-Host (Pose: lying, nur BABY-Figuren)

Garten (7)

  • gift_box × 3 — Tap → öffnet sich (bereits impl.)
  • tea_pot — Tap → gießt (bereits impl.)
  • tea_cup × 2 — Holdable
  • cake — Holdable
  • balloon × 2 — Holdable
  • garden_table — Snap-Host (Pose: sitting)
  • garden_chair × 2 — Snap-Host (Pose: sitting)

Kapitel 5 — Core Systems

5.1 Snap-Point System

SnapPoint ist ein Node2D an Möbeln:

class_name SnapPoint extends Node2D
@export var pose: String = "sitting"   # "sitting" | "lying"
@export var species_filter: Array[String] = []  # leer = alle; ["BABY"] = nur Babys
var occupant: Character = null

SnapReceiver sitzt auf jeder Figur. Bei drag_released scannt er alle SnapPoint-Nodes im Radius 80px. Nächster freier Snap (unter Berücksichtigung species_filter) gewinnt: Figur teleportiert auf SnapPoint-Position, Animation wechselt zu pose. Beim erneuten Aufnehmen (drag_picked_up) gibt SnapPoint occupant frei → Animation zurück zu held.

5.2 Hand-Slot System

HandLeft und HandRight sind Node2D-Nodes an der Figur. Bei drag_released eines Holdable Items prüft das Item ob es sich in Reichweite (~60px) eines leeren Hand-Slots befindet. Wenn ja: Item wird Kind des Hand-Slots, global_position relativ zum Slot, reist mit Figur mit. Zweiter Drag vom Hand-Slot löst das Item. Maximum 1 Item pro Hand.

5.3 Outfit Layer System

Drei Sprite2D-Nodes über dem Basis-Sprite der Figur. OutfitItem hat:

@export var outfit_layer: int = 1   # 1 | 2 | 3
@export var outfit_sprite: Texture2D

Per Drag auf Figur → Layer-Sprite zeigt outfit_sprite, Item verschwindet aus Welt. Tap auf aktiven Layer → Item fällt neben Figur, Layer-Sprite wird leer. Gespeichert in CharacterData.outfit: Array[String] (3 Item-IDs).

5.4 Room Chest System

Jeder Raum hat einen RoomChest-Node:

class_name RoomChest extends Node2D
@export var item_ids: Array[String] = []

Tap auf Chest → öffnet sich, zeigt Items als Icon-Reihe (tappbar). Tap auf Icon → Item-Instanz spawnt neben Chest. Items die in die Chest-Zone (~100px) zurückgezogen werden despawnen. Gehaltene oder eingerastete Items werden nie automatisch entfernt. Chest-State (welche Items spawnt, wo) wird per SaveManager persistiert.

5.5 Applier-Logik

Items mit apply_on_drop: bool = true triggern apply_to(character: Character) wenn auf eine Figur gedroppt. Mapping:

Item Effekt
medicine_bottle_* set_state(HEALTHY) + happy-Animation + sfx_medicine
iv_bag (in IV-Hook, Figur im Bett) set_state(SLEEPING)
baby_bottle auf BABY happy-Animation + sfx_baby_coo
bandage_roll Outfit Layer 2: Verband-Sprite
cast_arm Outfit Layer 2: Gips-Sprite
diaper Outfit Layer 1 für BABY
pacifier Outfit Layer 3 für BABY

5.6 Maschinen-Interaktion

Maschinen haben einen receive_slot: SnapPoint. Zusätzliche Bedingungen lösen Ausgaben aus:

Maschine Bedingung Ausgabe
xray_machine Figur auf xray_table Röntgenbild-Animation → xray_photo spawnt
ultrasound_machine PREGNANT auf exam_table + ultrasound_probe in HandSlot Fötus-Bild auf ultrasound_screen
microscope microscope_slide in Slot Bild-Wechsel auf Screen
queue_machine Tap number_ticket spawnt
iv_hook iv_bag eingehängt + Figur in patient_bed set_state(SLEEPING)
delivery_bed PREGNANT eingerastet + 2s BABY spawnt, Mutter → HEALTHY (bereits impl.)
cast_machine Figur eingerastet cast_arm-Outfit (Layer 2) auf Figur, Figur → HEALTHY
baby_scale BABY-Figur eingerastet happy-Animation + sfx_happy
ultrasound_machine PREGNANT auf exam_table + ultrasound_probe in HandSlot Fötus-Bild auf ultrasound_screen

Kapitel 6 — UI & Navigation

HUD (immer sichtbar)

  • Aufzug-Button — Etagen-Wechsel, 64dp, links oder rechts je nach Raum
  • HomeButton — Hospital ↔ Garten, 64dp (bereits impl.)
  • Settings-Button — oben rechts, 48dp
  • Kein Score, kein Timer, keine Sterne, kein Text

Navigation

System Status
Camera-Pan innerhalb Etage NavigationArrow (bereits impl.)
Etagen-Wechsel ElevatorButton + RoomNavigator (bereits impl.)
Hospital ↔ Garten HomeButton (bereits impl.)

Room Chest UI

Tap auf Chest → Icon-Reihe erscheint direkt in der Spielwelt über/neben der Chest (kein separater Screen). Tap außerhalb → Chest schließt. Icons haben 64dp Mindestgröße.

Settings-Menü

  • Lautstärke Musik (Slider)
  • Lautstärke SFX (Slider)
  • Savegame zurücksetzen (mit Bestätigung)
  • Später: Sprache

Kapitel 7 — Audio Design

Musik

Bereich Stil Loop-Länge
EG Fröhlich, Empfangs-Feeling ~2 min
1.OG Ruhig, Glockenspiel-Elemente ~2 min
2.OG Sanft, Schlaflied-Atmosphäre ~2 min
Garten Beschwingt, Party-Feeling ~2 min

Cross-Fade bei Etagen-Wechsel (AudioManager bereits impl.). Default-Lautstärke: 60%.

SFX-Katalog

ID Trigger
sfx_pickup Figur oder Item aufheben
sfx_place Figur oder Item ablegen (kein Snap)
sfx_snap Figur rastet in SnapPoint ein
sfx_happy happy-Animation startet
sfx_chest_open RoomChest öffnet
sfx_item_spawn Item spawnt aus Chest
sfx_medicine Medikament auf Figur angewendet
sfx_pour TeaPot gießt
sfx_gift_open GiftBox öffnet
sfx_cradle_rock Wiege schaukelt
sfx_xray_scan Röntgengerät aktiv
sfx_ambulance Ambulanz-Türen öffnen
sfx_baby_coo Baby-Interaktion (Fläschchen, Schaukeln)
sfx_bunny_sniff Häschen-Figur aufgehoben
sfx_kitten_meow Kätzchen-Figur aufgehoben
sfx_fox_yip Fuchs-Figur aufgehoben
sfx_owl_hoot Eulen-Figur aufgehoben

Quellen: freesound.org, opengameart.org (Creative Commons)


Kapitel 8 — Save/Load

Format v2

Erweiterung des bestehenden SaveManager + GameState. Migration: v1-Saves werden beim Laden auf v2 hochkonvertiert (fehlende Felder → Defaults).

{
  "version": 2,
  "current_floor": 0,
  "characters": {
    "bunny_f": {
      "position": [640, 360],
      "state": "HEALTHY",
      "outfit": ["white_coat", "", "stethoscope"],
      "held_left": "medicine_bottle_blue",
      "held_right": "",
      "snap_point": "floor1/xray/xray_table/snap_0"
    }
  },
  "room_chests": {
    "floor0/reception/chest": {
      "spawned_items": [
        {"id": "number_ticket", "pos": [200, 300]}
      ]
    }
  }
}

Auto-Save: nach jeder Interaktion (Pick-up, Place, Snap, Outfit-Wechsel, State-Änderung).


Kapitel 9 — Sprint-Plan (Gesamt)

Sprint Titel Kern-Deliverable
0 Setup Git, Godot, Android-Export
12 Proof of Concept Ein Raum, eine Figur, Drag & Drop
34 Core Systems RoomNavigator, SaveManager, Settings
57 Erdgeschoss Reception, GiftShop, Restaurant, EmergencyRoom
810 1. Obergeschoss XRay, Pharmacy, Lab, PatientRoom
1113 2. Obergeschoss Ultrasound, DeliveryRoom, Nursery
14 Zuhause & Garten GardenParty, HomeButton, GiftBox, TeaPot
15 Character System v2 AnimatedSprite2D (6 States), SnapReceiver, HandSlots, OutfitLayers
16 Snap-Point System SnapPoint an allen Möbeln in allen 12 Räumen
17 Hand-Slots + Outfits Item-Holding, OutfitItem-Typ, Apply-Logik, Save-Extension
18 Room Chests + Items RoomChest-Node, alle ~55 Objekte verteilt
19 Maschinen & Applier XRay-Foto, Ultraschall-Fötus, Mikroskop, Wartenummer, IV-Bag, Medizin
20 Sound & Musik Kompletter SFX-Katalog, Musik-Loops
21 Polish Tutorial-Hint, Animations-Feinschliff, Settings-Erweiterung
22 Release Icon, Splash, Play Store, Familien-Testing

Sprints 014 abgeschlossen. Sprints 1522 stehen aus.


Appendix — Asset-Strategie

Empfehlung: Hybrid

  • Kinder malen Helden-Figuren (Häschen, Kätzchen) auf Papier → einscannen → digitalisieren
  • Freelancer für Hintergründe und generische Objekte
  • Tier-Geräusche: freesound.org (Creative Commons)

Asset-Formate:

  • Sprites: PNG mit Transparenz, 2× (für Retina-Displays)
  • Animationen: SpriteSheet oder einzelne Frames in AnimatedSprite2D
  • Audio: OGG für Loops, WAV für kurze SFX

Dieses Dokument wird nur bei Produkt-Entscheidungen aktualisiert, nie bei rein technischen Implementierungsdetails.