Konzeptphase. Interne Planungsfassung, Stand 04.11.2026. Pocket Planet ist noch in Entwicklung – Inhalte, Zahlen und Abläufe können sich ändern.
14.1 Was das Werbemodul heute ist (geprüft in D:/Claude/Werbemodul)
| [Fakt] | |
|---|---|
| Zweck | Eigenwerbung für eigene Spiele und Websites (27 Spiele, 4 Websites im Katalog) – kein Werbenetzwerk, keine Werbeeinnahmen |
| Aufbau | core/ (TypeScript, framework-frei: Katalog, Konfiguration, Scheduler, Playlist, Messung) + Adapter web/ (Capacitor/HTML) und react-native/ (Expo) |
| Godot | kein Adapter, keine Wrapper, keine Beispiele (Suche über alle Studio-Projekte ergab keinen Treffer in .gd-Dateien) |
| Formate | Vollbild-Overlay mit Video (MP4, 720p), Bild (JPG/PNG), Platzhalter-Kachel, neu spielbare Anzeige (HTML in iframe/WebView, docs/PLAYABLE.md); „Weiter“ nach N Sekunden (Standard 5), Blöcke mit 1–10 Anzeigen |
Auslöser (AdEvent) | game_start, game_end_offline, game_end_online, good_move, level_complete, menu_return, result_action, app_resume, custom; Modus „nach Spielen“ oder „nach Minuten“ (tick(), setVisible()) |
Schutzregeln (AdConfig) | enabled, frequencyCapMinutes (Standard 2), graceGames (erstes Spiel werbefrei), excludeSelf, canShow()-Rückfrage der App |
Kern-API (WerbemodulCore) | init(), event(ev) → bool, tick(), setVisible(v), beginBlock(force, orientation) → PlaylistItem[], endBlock(), setConfig(), resetConfig(), loadRemote(url), snapshot(), resetState(), flushSave() |
| Remote-Konfiguration | JSON pro App unter config/ im Repo patrickuhl1988/Werbung, geladen über raw.githubusercontent.com; lockedConfig > Remote > gespeichert > initialConfig |
| Messung | Ereignis joculus_ad_impression mit creative_id, placement, sdk_version (1.1.0) – über die Analytics der App und nur mit deren Einwilligung; das Modul spricht nie selbst mit Firebase |
| Offline | Medien in der App oder per mediaBase (jsDelivr); ohne Netz offlineFallbackId (z. B. joker-studios) |
14.2 Technische Hürden in Godot
- Kein MP4: [Fakt] Godot spielt Video nur als Ogg Theora (
VideoStreamTheora). Die Werbevideos (H.264-MP4) müssen per ffmpeg konvertiert werden (ffmpeg -i x.mp4 -c:v libtheora -q:v 6 -c:a libvorbis x.ogv). Theora ist bei gleicher Qualität größer und braucht mehr CPU → [Vorschlag] im MVP nur Bild-Anzeigen und Platzhalter; Video ab Phase 3, nach Messung auf dem A13. - Keine WebView: Spielbare Anzeigen (HTML) brauchen eine WebView. Godot hat keine eingebaute → nicht im MVP. Möglich wäre später ein Android-WebView-Plugin.
- Kein Rewarded-Modus im Kern: Es gibt kein Konzept „Anzeige auf Wunsch des Spielers, Rückmeldung bei Abschluss“.
beginBlock(force=true)ist laut Doku ausdrücklich eine Testvorschau, die Zähler und Mindestabstand ignoriert – sie darf nicht als Rewarded-Ersatz missbraucht werden. - Kern ist TypeScript: Er muss in GDScript portiert werden (Logikanteil ≈ 900 Zeilen; der Katalog mit ≈ 1 300 Zeilen ist Daten und wird als JSON exportiert statt portiert).
14.3 AdManager – zentrale, austauschbare Schnittstelle
scripts/autoload/ads.gd ist das einzige, was das Spiel kennt. Dahinter steckt ein austauschbarer Adapter.
# ads.gd (Autoload) – öffentliche Schnittstelle
signal ad_started(placement: String) # Spiel pausiert Simulation/Audio
signal ad_finished(placement: String, completed: bool)
func event(name: String) -> void # meldet Spielereignisse an den Adapter (Auslöser-Logik)
func can_offer_rewarded(placement: String) -> bool
func show_rewarded(placement: String, on_done: Callable) -> void # on_done.call(completed: bool)
func is_showing() -> bool
func set_consent(analytics_allowed: bool) -> void
# Adapter-Vertrag (scripts/services/ads/*.gd)
class_name AdAdapter extends RefCounted
func init(config: Dictionary) -> void
func on_event(name: String) -> bool # true = Block wird jetzt gezeigt
func begin_rewarded(placement: String) -> bool
func end_block(completed: bool) -> void
| Adapter | Inhalt | Wann |
|---|---|---|
NullAdAdapter | tut nichts, can_offer_rewarded = false | Tests, Kinder-/Datenschutzmodus, Fehlerfall |
HouseAdAdapter | GDScript-Port des Werbemodul-Kerns + Godot-Overlay | MVP |
(künftig) NetworkAdAdapter | nicht geplant – nur nach ausdrücklicher Entscheidung (Auftrag: keine fremden SDKs als Ersatz, solange unser SDK geeignet ist) | – |
14.4 Einbindung in Pocket Planet
Ereignis-Abbildung (Pocket Planet hat keine „Spiele“ mit Ende – wir bilden auf vorhandene AdEvent-Werte ab, statt neue zu erfinden):
| Pocket-Planet-Moment | AdEvent | Bemerkung |
|---|---|---|
| Epoche abgeschlossen, nach dem Feier-Bildschirm | level_complete | natürliche Pause |
| Rückkehr-Karte geschlossen | app_resume | nur wenn die Abwesenheit ≥ 2 h war |
| Chronik geschlossen | menu_return | |
| Szenario beendet | game_end_offline |
Empfohlene Konfiguration (lockedConfig) [Vorschlag]: Modus „nach Spielen“, Zähler 2, Werbung erst beim Verlassen des Endbildschirms, frequencyCapMinutes 20 (statt 2: Pocket-Planet-Sitzungen sind kurz), graceGames so gesetzt, dass die ersten 3 Tage werbefrei sind, sequenceLength 1, excludeSelf true.
Interaktion mit der Simulation:
ad_started→ Simulation pausiert (keine Zyklen, Zeitraffer aus), Musikduck(true), Spiel speichert vorher.ad_finished→ alles läuft weiter. Die Zeit während der Anzeige zählt nicht als Offline-Zeit.- Eine Anzeige wird nie gezeigt, während der Spieler pinselt, eine Evolutionskarte offen ist oder ein Ereignis entschieden werden muss (
canShow-Rückfrage).
Fehler & offline:
- Remote-Konfiguration nicht ladbar → letzte gespeicherte gilt, sonst
lockedConfig. - Medium fehlt/ladefehler → Platzhalter-Kachel (wie im Kern vorgesehen); bei belohnter Anzeige zählt die Platzhalter-Kachel als vollständig (Spieler darf nicht bestraft werden).
- Jede Ausnahme im Adapter wird abgefangen, protokolliert und schaltet für die Sitzung auf
NullAdAdapter.
14.5 Consent, Datenschutz, Store-Richtlinien
- Keine Werbe-ID, kein Tracking: Das Werbemodul nutzt keine Geräte-IDs.
com.google.android.gms.permission.AD_IDbleibt blockiert (wie in Bridge Royale). - Messung
joculus_ad_impressionnur, wenn die Analytics-Einwilligung erteilt ist (Studio-Muster: Opt-in-Bildschirm, Tiefseeanalytics.gd). - Kein ATT-Dialog auf iOS nötig, solange nicht getrackt wird.
- Play-Formular: „Enthält Werbung: Ja“ (Eigenwerbung zählt als Werbung). Data-Safety: Analytics-Daten wie bisher bei Bridge Royale (Nutzungsdaten, App-Instanz-ID), nur mit Einwilligung.
- Familienrichtlinie: Pocket Planet ist nicht für Kinder unter 13 als Zielgruppe ausgewiesen [Annahme] – sonst gelten strengere Werbe- und Datenregeln. Entscheidung F7 in 17.
14.6 Was wir vom SDK-Verantwortlichen brauchen (präzise)
| # | Benötigt | Warum |
|---|---|---|
| S1 | Freigabe für einen offiziellen Godot-Adapter im Werbemodul-Repo (godot/) mit derselben Kernlogik – oder Zustimmung, dass der Port in Pocket Planet lebt | Vermeidet zwei auseinanderlaufende Kopien |
| S2 | Rewarded-Modus im Kern: z. B. Option „auf Anforderung, ohne Zähler, mit Abschlussmeldung“, inkl. eigener Regeln (max. N pro Tag, Mindestabstand) und eigener Messung (placement = rewarded_<ort>) | Existiert nicht; force ist nur für Tests |
| S3 | Katalog als JSON-Export (Build-Schritt npm run build → dist/catalog.json) | Godot kann TS nicht lesen; eine Quelle der Wahrheit |
| S4 | Theora-Fassungen der ausgewählten Videos oder Freigabe, sie selbst zu erzeugen; ggf. eigene mediaBase mit .ogv | Godot spielt kein MP4 |
| S5 | App-ID & Remote-Datei für Pocket Planet: appId = de.bridgeroyale.app, Datei config/pocket-planet-werbe-config.json im Repo Werbung | Steuerung ohne Build |
| S6 | Katalogeintrag für Pocket Planet (damit andere Spiele es bewerben) – ersetzt den Bridge-Royale-Eintrag | Store-Link bleibt gleich (gleicher Paketname) |
| S7 | Bestätigung, ob Bildanzeigen im Hochformat (-hoch.jpg) für alle ausgewählten Creatives vorliegen | Pocket Planet ist Hochformat |
Bis S1–S3 geklärt sind, wird ausschließlich gegen die Schnittstelle in 14.3 und den NullAdAdapter entwickelt.