Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 37 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,44 @@ SOPA iOS soll in der **Spiellogik** Android-Verhalten erreichen (UI darf abweich

## Build und Test
- Build:
- `xcodebuild -project SOPA.xcodeproj -scheme SOPA -destination 'platform=iOS Simulator,name=iPhone 16,OS=18.0' build`
- `xcodebuild -project SOPA.xcodeproj -scheme SOPA -destination 'platform=iOS Simulator,name=iPhone 17 Pro' build`
- Voller Testlauf:
- `xcodebuild -project SOPA.xcodeproj -scheme SOPA -destination 'platform=iOS Simulator,name=iPhone 16,OS=18.0' test`
- `xcodebuild -project SOPA.xcodeproj -scheme SOPA -destination 'platform=iOS Simulator,name=iPhone 17 Pro' test`
- Hinweis: Simulator-Namen mit `xcrun simctl list devices available` prüfen (der Name variiert je nach installierter Xcode-Version; aktuell iOS 26.5, iPhone 17 Pro).

## App im Simulator ansehen (visuelle Verifikation mit idb)
Für UI-/Design-Arbeit lässt sich die App im Simulator fernsteuern (Taps/Swipes), um Screens
gegen das Android-Design abzugleichen. Setup ist installiert (siehe unten bei Problemen).

Ablauf (Beispiel iPhone 17 Pro):
```bash
export PATH="$HOME/.local/bin:$PATH" # idb-CLI liegt in ~/.local/bin (pipx)
UDID=$(xcrun simctl list devices booted | grep -oE '[0-9A-F-]{36}' | head -1)
BUNDLE=de.davidschilling.SOPA

xcrun simctl boot "iPhone 17 Pro" 2>/dev/null # falls nicht gebootet
xcrun simctl install "$UDID" "$(find ~/Library/Developer/Xcode/DerivedData/SOPA-*/Build/Products/Debug-iphonesimulator -maxdepth 1 -name SOPA.app | head -1)"
xcrun simctl launch "$UDID" "$BUNDLE"

idb connect "$UDID"
idb ui tap --udid "$UDID" <x> <y> # Koordinaten in POINTS (iPhone 17 Pro = 402x874)
idb ui swipe --udid "$UDID" <x1> <y1> <x2> <y2> # z.B. Reihe/Spalte im Spielfeld schieben
xcrun simctl io "$UDID" screenshot out.png # Screenshot zum Vergleich
```
Menü-Tap-Punkte (Points, iPhone 17 Pro): LEVEL MODE ≈ (201,345), JUST PLAY ≈ (201,439),
TUTORIAL ≈ (201,535), CREDITS ≈ (201,629).

Grenzen: Screens hinter Gameplay (Level Complete, JustPlay-Score) erscheinen erst nach
gelöstem Puzzle und lassen sich per Blind-Swipe kaum reproduzierbar erreichen – dafür
Quellcode heranziehen. JustPlay-Game-Over erreicht man einfach, indem man den Timer
ablaufen lässt (~12 s ohne Lösung).

### idb-Setup (falls nicht vorhanden)
- `brew install facebook/fb/idb-companion`
- `pipx install --python /opt/homebrew/bin/python3.12 fb-idb`
(**muss Python 3.12 sein**, nicht 3.14 – fb-idb 1.1.7 crasht auf 3.14 wegen entferntem
`asyncio.get_event_loop()`).
- Die Meldung `objc[...] Class FBProcess is implemented in both ...` bei jedem Aufruf ist harmlos.

## Wichtige Dateien
- Produktplan: `IOS_PRODUCT_COMPLETION_PLAN.md`
Expand Down
160 changes: 160 additions & 0 deletions ANDROID_DESIGN_PARITY_PLAN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
# iOS ↔ Android Design-Parität – Aufgabenplan

Ziel: Das aktuelle **Android-Design** (siehe `sopa-android/pr/dev-screenshots/`) auf iOS
übernehmen. Grundlage dieses Plans ist ein Vergleich der 7 Android-Referenz-Screens mit
dem aktuellen iOS-Zustand (Branch `backup/ios-ui-level-overview-2026-02-25`).

Die iOS-Screens wurden **live im Simulator** (iPhone 17 Pro, iOS 26.5) per idb erfasst und
mit den Android-Vorlagen verglichen. Ausnahmen: „Level Complete" und der JustPlay-Zwischen-
Score erscheinen nur nach gelöstem Puzzle und wurden über den Quellcode abgeglichen.

## Statusüberblick pro Screen

| Screen | iOS-Datei | Status | Kernabweichung zu Android |
|---|---|---|---|
| Hauptmenü | `StartMenuScene.swift` | 🟢 fast fertig | Menüpunkt-Label + Social-Icons; kein Settings-Screen |
| Level-Auswahl | `LevelChoiceScene` + `LevelButtonArea` + `LevelSelectButton` | 🟢 (live bestätigt) | fehlender Tutorial-Einstieg |
| Level-Mode Spiel | `LevelModeGameScene.swift` | 🟢 (live bestätigt) | Back-Button (Android hat keinen) |
| Level Complete | `LevelModeScoreScene.swift` | 🟢 (P2 erledigt) | Wording + Play-Icon angepasst |
| Just-Play Spiel | `JustPlayGameScene.swift` (+ Basis `GameScene`) | 🟢 (P1 erledigt) | – (schwarz + Android-HUD) |
| Just-Play Highscore | `JustPlayLostScene` (in `JustPlayGameScene.swift`) | 🟢 (P2 erledigt) | Farbbalken + „Share Score" ergänzt |
| Tutorial | `TutorialScene.swift` / `TutorialGameScene.swift` | 🟢 (P2 erledigt) | visuelle Android-Screens; Einstiegspunkt offen (P3) |
| Credits | `CreditsScene.swift` | 🟢 (kein Referenz-Screenshot) | – |

Grundursache vieler roter Punkte: Die Basis-Klasse `GameScene` (`SOPA/view/GameScene.swift:33`)
setzt weiterhin den **warmen braunen** Hintergrund und ein altes Inline-HUD
(„Optimum: N", „Moves:", „N. Level"). `LevelModeGameScene` überschreibt beides bereits
Android-konform – `JustPlayGameScene` und die Score-Szenen tun das noch nicht.

---

## P1 – Hintergrund & Theme vereinheitlichen (schnelle, hochwirksame Fixes)

Android nutzt durchgängig **Schwarz** als Hintergrund. Auf iOS sind noch braun:
`LevelModeScoreScene`, `JustPlayScoreScene`, `JustPlayLostScene`, `TutorialScene` sowie die
Basis `GameScene` (→ trifft `JustPlayGameScene` und `TutorialGameScene`).

- [x] `GameScene` Default-Hintergrund auf schwarz umgestellt (`GameScene.swift`)
- [x] `LevelModeScoreScene` Hintergrund schwarz
- [x] `JustPlayScoreScene` + `JustPlayLostScene` Hintergrund schwarz
- [x] `TutorialScene` Hintergrund schwarz
- [ ] Toten braunen `warmBackground`-Pfad in `SopaTheme` später entfernen

## P1 – Just-Play Spiel-HUD an Android angleichen

Android zeigt oben „Min. Moves"/„Current Moves" (Label + große Zahl darunter) und unten
„Left Time" (große Zahl). iOS `JustPlayGameScene` erbt aktuell das alte Basis-HUD und
addiert nur „Left Time" → doppelte/inkonsistente Beschriftung.

- [x] In `JustPlayGameScene` `addStaticLabels()`/`addDynamicLabels()` überschrieben, analog
zu `LevelModeGameScene` (Impact-Font, Label + große Zahl)
- [x] „Left Time" ins gleiche Layout gebracht (Label oben, große Zahl darunter, unten links)
- [ ] Prüfen, ob das rote Warn-Overlay bei ≤5 s dem Android-Verhalten entspricht

Live bestätigt (idb): JustPlay zeigt jetzt schwarz „Min. Moves / Current Moves" oben und
„Left Time" unten links, Restart unten rechts – wie Android.

## P1 – Safe-Area / Notch (weitgehend erledigt)

Live-Befund war: im JustPlay ragte der „1. Level"-Titel (altes Basis-HUD) in die
**Dynamic Island**, und die Spiel-Buttons überlappten die Labels.

- [x] Ursache behoben durch den JustPlay-HUD-Umbau (kein Level-Titel oben mehr) und die
manuelle Button-Positionierung (Restart unten rechts, minimaler Back oben links)
- [ ] Optional: Top-Labels zusätzlich an Safe-Area-Insets ausrichten (statt `size.height`),
auf mehreren iPhone-Größen gegenprüfen

Hinweis: Der große Leerraum **unter** dem Spielfeld ist **kein** Parität-Fehler –
Android platziert das Feld ebenfalls im oberen Bereich (`FIELD_SART_FROM_TOP = 0.2`,
`GameFieldNode.swift:18`), der untere Bereich trägt das HUD. `GameFieldNode` bleibt
daher unverändert; eine Zentrierung würde von Android *wegführen*.

Zusatzbefund: `IPadProportionSet` ist nur eine leere Unterklasse von `IPhone6Proportionset`
(`IPadProportionSet.swift`), also faktisch identisch – die frühere „iPad-hardcoded"-Sorge
ist gegenstandslos. Positionswerte für das Spiel-HUD kommen aus `ProportionSet`, werden aber
in Level-Mode/JustPlay inzwischen durch absolute Layouts überschrieben.

## P2 – Level Complete an Android angleichen

Android: **schwarzer** Hintergrund, Titel „N. Level Complete", „Your moves: X",
„Moves for 3 Stars: Y", 3 goldene Sterne, unten 3 weiße Kreis-Buttons (Grid / Restart / Play).

- [x] Hintergrund schwarz (P1)
- [x] Titel-Wording auf „N. Level Complete"
- [x] Untertitel „Moves for 3 Stars: N"
- [x] „Next"-Button: gefülltes Play-Dreieck (`play.fill`)
- [ ] Optional: Titel-Font/Größe/links-Ausrichtung noch näher an Android (aktuell zentriert, Optima)
- [ ] Sterne-Optik gegen Android prüfen (`star_score`/`starSW_score`)

## P2 – Just-Play Highscore an Android angleichen

Android: schwarzer Hintergrund, Titel „New Highscore", **blauer Balken** „Score: N",
**gelber Balken** „Level: N", unten 3 Kreis-Buttons: Zurück-Pfeil, Restart, **„SHARE SCORE"**.

- [x] Hintergrund schwarz (P1)
- [x] Score/Level als farbige Balken (blau/gelb) statt reinem Text
- [x] **„SHARE SCORE"-Button ergänzt** (neuer `makeCircleTextButtonTexture`)
- [x] Button-Set an Android angeglichen (Zurück-Pfeil / Restart / Share)
- [x] „Reached Level"/„Highscore"-Klartextzeilen für Parität entfernt (Konfetti bleibt als iOS-Extra bei neuem Highscore)

## P2 – Tutorial neu aufbauen (anderes Konzept)

Android-Tutorial = **visueller** 2-Screen-Ablauf: Titel „Tutorial" + „Click to see next info",
ein Spielfeld-Grid mit grünem/rotem Gate und blauen Röhren, unten farbig hervorgehobener
Erklärtext („Connect the **GREEN** and the **RED** gate, using the **BLUE** tubes. Use all tubes.").
Wird in Android **aus der Level-Auswahl** gestartet (`loadTutorialSceneFromLevelChoiceScene`)
bzw. beim Erststart, nicht aus dem Menü.

- [x] Tutorial als visuelle Screens umgebaut – Android-Artwork nach
`Assets.xcassets/tutorial` importiert (first/second Screen A+B, Let's Go)
- [x] Farbige Keywords (GREEN/RED/BLUE) – über die importierten Screens abgedeckt
- [x] 2-Screen-Ablauf + „Lets GO" → interaktives Tutorial-Level (analog Android)
- [ ] Einstiegspunkt: Android startet aus der Level-Auswahl / beim Erststart; iOS startet
aktuell aus dem Menü (hängt an der SETTINGS/TUTORIAL-Entscheidung, siehe P3)

## P3 – Menü: Settings vs. Tutorial klären + Social-Icons

Android-Menü: **LEVEL MODE / JUST PLAY / SETTINGS / CREDITS** (kein Tutorial-Eintrag).
Der Settings-Screen in Android ist ein **Musik-Mute-Toggle** (`SettingsService`: `MUTE`,
`MY_FIRST_TIME`). Tutorial läuft über Level-Auswahl/Erststart.

iOS aktuell: der 3. Menüpunkt wurde von „SETTINGS" auf **„TUTORIAL"** umbenannt und öffnet
das (Text-)Tutorial. Es gibt auf iOS **keinerlei Audio/Musik** und keinen Settings-Screen.

- [x] Social-Icons an Android angeglichen: Android-`ShareThis` + Twitter-Vogel importiert und
im `StartMenuScene` statt der SF-Symbol-Texturen verwendet
- [~] **Entscheidung getroffen (Nutzer):** iOS weicht bewusst ab – Menüpunkt bleibt „TUTORIAL",
**kein** SETTINGS-Eintrag. Settings/Audio werden vorerst **nicht** gebaut.

## P3 – Audio/Musik + Settings (zurückgestellt)

Android hat Menü-Musik und einen Mute-Toggle; iOS hat aktuell **kein Audio**.
**Auf Nutzerwunsch vorerst zurückgestellt** – wird derzeit nicht umgesetzt.

- [ ] (später) Musik-Playback (z. B. `AVAudioPlayer`) + Mute-Persistenz
- [ ] (später) Settings-Szene mit Mute/Unmute-Button
- [ ] (später) Erststart-Logik (`isFirstTime`) für automatischen Tutorial-Aufruf

## Tutorial-Einstiegspunkt (zurückgestellt)

Android startet das Tutorial aus der Level-Auswahl / beim Erststart. iOS behält auf
Nutzerwunsch den **Menü-Eintrag „TUTORIAL"**; eine Verlegung des Einstiegs wird nicht gemacht.

---

## Offene Punkte / zu verifizieren

- Android-Credits-Screen liegt nicht als Screenshot vor → Parität nicht abgleichbar.
- Ob Android im Just-Play einen Zwischen-Score-Screen pro Level hat (iOS `JustPlayScoreScene`),
ist aus den Screenshots nicht ersichtlich – gegen die Android-App verifizieren.

## Empfohlene Reihenfolge

1. ~~**P1** – Hintergründe schwarz + Just-Play-HUD~~ ✅ erledigt
2. ~~**P2** – Level Complete, Just-Play Highscore, Tutorial-Neuaufbau~~ ✅ erledigt
3. ~~**P3** – Social-Icons~~ ✅ erledigt; Settings/Audio + Tutorial-Einstieg auf
Nutzerwunsch zurückgestellt

Damit ist die sichtbare Design-Parität für alle vorhandenen Screens erreicht.
Offen bleiben nur die bewusst zurückgestellten Punkte (Audio/Settings) sowie kleinere
Feinschliff-Optionen (Level-Complete-Titelstil, Sterne-Optik).
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
See [AGENTS.md](./AGENTS.md) for project instructions and conventions.
Loading
Loading