Inspiration

Most short-session strategy games sell speed or luck. Tiny Broadcast sells a plan. You run a small-town radio station for one season, and the station's character comes from the choices you made.

What it does

  • Seasons: each season is seven in-game days. Each day has three slots (morning, afternoon, evening) and a pool of programs: open lines, local sessions, town bulletins, late-night shows and more. Every day brings a town event and a listener focus.
  • Visible trade-offs: each program shows how it will change Budget, Trust and Reach before you commit. The simulation is deterministic, so the same seed and the same choices always give the same result.
  • Your funding: each broadcast is funded one of two ways. A clearly labelled sponsor route and a community route apply the same program effects. Turning down a sponsor never locks anything and never slows you down.
  • Season end: the game names your station's character (Community Radio, Hit Machine, Night Owl or Trusted Voice), gives you a share card, and lets you replay with a different plan.

Left out on purpose: loot boxes, pay-to-win, streak pressure, fake countdowns and absence penalties. The game works offline, and no account is needed.

Free and Ad Free:

  • Free: the full game, with one declinable sponsor break at a season boundary.
  • Ad Free: a one-time lifetime unlock (tinybroadcast_ad_free_lifetime) that removes it.

How we built it

The game logic is plain TypeScript in React Native / Expo. Ads run through our own Kotlin module (tinybroadcast-ads), which wraps the Google Mobile Ads SDK and Google's UMP consent SDK.

RevenueCat, in two roles:

  1. Purchases. Buying the lifetime "Ad Free" product grants the entitlement tinybroadcast_ad_free. The offering is tinybroadcast_default, requested by id, with the package $rc_lifetime.
  2. Ad tracking. The single interstitial is loaded through Purchases.sharedInstance.adTracker.loadAndTrackInterstitialAd, so RevenueCat records ad revenue next to purchase revenue.

Checks before an ad is shown. The Kotlin module does three things:

  • It re-fetches CustomerInfo with CacheFetchPolicy.FETCH_CURRENT and skips the ad if tinybroadcast_ad_free is active.
  • It re-checks UMP canRequestAds().
  • It builds the request as non-personalized.

Live build. The Play build is versionCode 3. It contains the Google Mobile Ads SDK and the AdMob application id.

Challenges we ran into

  • Honest sponsorship in a game. The sponsor route had to be clearly labelled, have the same effect as the community route, and cost nothing to decline. The deterministic simulation makes that verifiable.
  • A purchase just before an ad. Re-reading the entitlement from the network, not the cache, right before the ad means a player who just bought Ad Free never sees one.

Accomplishments that we're proud of

  • A strategy game with no loot boxes and no pay-to-win, where ad revenue and purchase revenue sit side by side in RevenueCat.
  • One ad placement, declinable, at a natural pause.

What's next for Tiny Broadcast

More town events and listener focuses per season.

Judges' access

  • Promo code: Judges: promo code provided in the private judging field. The code unlocks the one-time Ad Free product (tinybroadcast_ad_free, lifetime).
  • Without a code: the full game is free and has one declinable sponsor break.

Built With

Share this project:

Updates

Submission history