TipTap Games

Game lifecycle

Your game is one panel in a feed the player is swiping through, so it starts, pauses, loses focus and resumes without ever being unloaded. These are the hooks for each of those moments.

Loading screen

The platform can only see when your documentfinished parsing, which for a game that then decodes audio or builds levels is far too early — the player stares at a live but empty panel. Report progress and the platform shows a proper loading screen with your title, and holds the game paused until you say it's ready.

TipTap.setLoadProgress(progress: number)

Call with a value from 0 to 1 while your game is preparing assets. This opts your game into the platform loading screen: the player sees your title and a progress bar instead of a blank panel, and your game stays paused until it's ready.

TipTap.ready()

Loading is finished — the platform drops the loading screen and starts the game. Required if you called setLoadProgress. Games that are instantly playable should call neither; the platform starts them as soon as the document loads.

Audio & focus

Players swipe between games constantly, and two games playing music at once is the fastest way to get closed. The platform pauses off-screen games, but it cannot reach inside your audio graph — you have to stop your own sound on tiptap:blur. The platform also has a global mute toggle, and canPlayAudio() folds both conditions into one check.

TipTap.canPlayAudio(): boolean

True only when your game is on screen AND the player has not muted all games. This is the single check you want before starting music or a sound effect.

TipTap.isFocused(): boolean

True when your game is the one the player is actually looking at. False when it has scrolled out of view, when the results overlay is up, or when the browser tab is in the background. This is visibility, for audio — it is NOT DOM focus and says nothing about whether keydown will fire. That one is takeKeyboardFocus(), and the platform handles it for you.

TipTap.isMuted(): boolean

True when the player has muted all games with the platform's global sound toggle. Respect it — your game's own mute button should stay in sync with this.

TipTap.isPaused(): boolean

True while the platform has your game paused.

TipTap.onFocusChange(cb) / onMuteChange(cb) / onPauseChange(cb)

Callback forms of the window events below, if you prefer callbacks to listeners. Each receives the new boolean value.

Window events

The platform fires these on window as the player moves through the feed. Use whichever style fits — every one has a callback equivalent above.

tiptap:focus

Your game is on screen and the player is looking at it. Safe to start audio (check canPlayAudio() first).

tiptap:blur

Your game is no longer the one being looked at — scrolled away, overlay up, or the browser tab went to the background. Stop ALL audio here.

tiptap:mutechange

The player toggled the global sound control. event.detail.muted is the new value.

tiptap:pause

Stop game loop timers and animations. Fired whenever the platform pauses your game.

tiptap:resume

Restart timers and unpause animations.

tiptap:leaderboardclose

The player dismissed the leaderboard with Continue. Your state is intact — resume play.

tiptap:achievement

A first-time achievement unlock was confirmed. event.detail carries the achievement.

Arcade view

TipTap.setArcade(on: boolean)

Request that the platform enter or leave arcade view, where your game fills the whole viewport with no feed chrome. Players can also toggle it themselves from the action rail.

TipTap.isArcade() / TipTap.onArcadeChange(cb)

Read or subscribe to arcade state — useful if your layout should change when it has the full screen. Also fires as 'tiptap:arcadechange'.

Sharing

Offer a share at the moments that earn it — a personal best, a first clear, a run worth showing — from a button on your own end screen. Firing it automatically at every game over throws UI over the player and teaches them to dismiss your end screen without reading it. If you pass no picture the platform generates a branded score card with the score, the game and the player on it.

TipTap.share({ score?, text?, imageDataUrl? })

Opens the platform's share sheet. Every field is optional. There is no callback and no result — you are never told whether the player went through with it, so never gate a reward on it.

imageDataUrl — your own picture, instead of the generated card

A data: URL of type png, jpeg or webp, at most 2 MB decoded. Anything else is dropped with a console warning and the sheet still opens with the platform's generated score card, so a bad snapshot degrades rather than failing. Build it on a separate offscreen canvas around 1080px on the long edge — your live canvas is sized for a phone and rarely reads well shared.