Pocket Planet Wiki

Werbe-SDK

Integration des eigenen Werbemoduls über eine austauschbare AdManager-Schnittstelle.

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]
ZweckEigenwerbung für eigene Spiele und Websites (27 Spiele, 4 Websites im Katalog) – kein Werbenetzwerk, keine Werbeeinnahmen
Aufbaucore/ (TypeScript, framework-frei: Katalog, Konfiguration, Scheduler, Playlist, Messung) + Adapter web/ (Capacitor/HTML) und react-native/ (Expo)
Godotkein Adapter, keine Wrapper, keine Beispiele (Suche über alle Studio-Projekte ergab keinen Treffer in .gd-Dateien)
FormateVollbild-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-KonfigurationJSON pro App unter config/ im Repo patrickuhl1988/Werbung, geladen über raw.githubusercontent.com; lockedConfig > Remote > gespeichert > initialConfig
MessungEreignis 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
OfflineMedien in der App oder per mediaBase (jsDelivr); ohne Netz offlineFallbackId (z. B. joker-studios)

14.2 Technische Hürden in Godot

  1. 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.
  2. 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.
  3. 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.
  4. 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
AdapterInhaltWann
NullAdAdaptertut nichts, can_offer_rewarded = falseTests, Kinder-/Datenschutzmodus, Fehlerfall
HouseAdAdapterGDScript-Port des Werbemodul-Kerns + Godot-OverlayMVP
(künftig) NetworkAdAdapternicht 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-MomentAdEventBemerkung
Epoche abgeschlossen, nach dem Feier-Bildschirmlevel_completenatürliche Pause
Rückkehr-Karte geschlossenapp_resumenur wenn die Abwesenheit ≥ 2 h war
Chronik geschlossenmenu_return
Szenario beendetgame_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), Musik duck(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.
  • Keine Werbe-ID, kein Tracking: Das Werbemodul nutzt keine Geräte-IDs. com.google.android.gms.permission.AD_ID bleibt blockiert (wie in Bridge Royale).
  • Messung joculus_ad_impression nur, wenn die Analytics-Einwilligung erteilt ist (Studio-Muster: Opt-in-Bildschirm, Tiefsee analytics.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ötigtWarum
S1Freigabe für einen offiziellen Godot-Adapter im Werbemodul-Repo (godot/) mit derselben Kernlogik – oder Zustimmung, dass der Port in Pocket Planet lebtVermeidet zwei auseinanderlaufende Kopien
S2Rewarded-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
S3Katalog als JSON-Export (Build-Schritt npm run build → dist/catalog.json)Godot kann TS nicht lesen; eine Quelle der Wahrheit
S4Theora-Fassungen der ausgewählten Videos oder Freigabe, sie selbst zu erzeugen; ggf. eigene mediaBase mit .ogvGodot spielt kein MP4
S5App-ID & Remote-Datei für Pocket Planet: appId = de.bridgeroyale.app, Datei config/pocket-planet-werbe-config.json im Repo WerbungSteuerung ohne Build
S6Katalogeintrag für Pocket Planet (damit andere Spiele es bewerben) – ersetzt den Bridge-Royale-EintragStore-Link bleibt gleich (gleicher Paketname)
S7Bestätigung, ob Bildanzeigen im Hochformat (-hoch.jpg) für alle ausgewählten Creatives vorliegenPocket Planet ist Hochformat

Bis S1–S3 geklärt sind, wird ausschließlich gegen die Schnittstelle in 14.3 und den NullAdAdapter entwickelt.