A carnival-style ring toss game designed for school field day environments. Players toss rings onto pegs using a skill-based power meter, with bonus incentives for stacking on their own rings. Supports 1–2 players with turn-based multiplayer.
- 1–2 Players: Solo mode or turn-based multiplayer.
- Skill-Based Toss: 5-section power meter — stop it in the center to land your ring.
- 3 Pegs: Left, Center, Right — each holds up to 3 rings.
- 6 Rings Per Player: Alternate turns until all rings are used.
- 20-Second Turn Timer: Auto-miss if the player doesn't act in time.
- Scoring: +2 per landed ring, +1 stacking bonus for landing on your own color (2-player only).
- Peg Images: Pre-rendered images update on canvas showing the ring stack (e.g.,
peg_rb.png= red then blue). - Missed Rings: Dropped as assets near the target peg with positional scatter.
- Player Teleportation: Players are teleported to their mat positions on game start.
- Reset Cleanup: Ring assets are removed and pegs reset to empty on game reset.
| Badge | Condition |
|---|---|
| Sharp Shooter | Land 3 successful throws in a row |
| On Fire | Hit all your throws in a single game |
| Stack Master | Fill a peg entirely with your color |
| Piggyback Pro | Stack on top of an opponent's ring (2-player) |
| Comeback Kid | Win after being behind in score with your final toss (2-player) |
| All Miss, No Hit | Miss every throw in a game |
| Ring Toss Regular | Play 10 games |
| Ring Rockstar | Win 5 games (2-player) |
| Field Day Champion | Win 15 games (2-player) |
- Admins can reset the game at any time via the Reset button.
- During an active game, only players or admins can reset.
The app uses the following unique name patterns for managing dropped assets in the world:
| Unique Name | Description |
|---|---|
RingToss_keyAsset |
Ring Toss sign that when clicked opens the app in an iframe |
RingToss_mat_red |
Red player's mat — teleport destination on game start |
RingToss_mat_blue |
Blue player's mat — teleport destination on game start |
RingToss_peg_left |
Left peg — layer1 image updated to show ring stack |
RingToss_peg_center |
Center peg — layer1 image updated to show ring stack |
RingToss_peg_right |
Right peg — layer1 image updated to show ring stack |
RingToss_ring_{timestamp}_{id} |
Dropped ring assets (created on miss, deleted on reset) |
Peg images are hosted at https://sdk-ring-toss.s3.us-east-1.amazonaws.com/ and named by ring stack order:
peg_empty.png— no ringspeg_r.png— one red ringpeg_rb.png— red then bluepeg_rrb.png— red, red, blue- All permutations up to 3 rings with
r(red) andb(blue)
Ring assets: ring_r.png, ring_b.png
The data object attached to the key asset (Ring Toss sign) stores the full game state:
{
gameStatus: "waiting" | "in-progress" | "game-over";
playerRed: { profileId, visitorId, displayName, interactiveNonce } | null;
playerBlue: { profileId, visitorId, displayName, interactiveNonce } | null;
currentTurn: "red" | "blue";
pegs: { left: string[]; center: string[]; right: string[] }; // e.g. ["r", "b"]
scores: { red: number; blue: number };
ringsRemaining: { red: number; blue: number };
consecutiveHits: { red: number; blue: number };
totalHits: { red: number; blue: number };
totalMisses: { red: number; blue: number };
isSoloGame: boolean;
winner: "red" | "blue" | "tie" | null;
}Visitor data is scoped by ${urlSlug}-${sceneDropId} and tracks per-player stats for badge eligibility:
{
gamesPlayed: number;
gamesWon: number;
}| Event | Unique Key |
|---|---|
joins |
profileId |
starts1player |
profileId |
starts2player |
profileId (each player) |
completions |
profileId (each player) |
resets |
— |
| Method | Path | Purpose |
|---|---|---|
| GET | /api/game-state |
Load game state, badges, admin check, track joins |
| PUT | /api/join |
Join as Red or Blue player |
| PUT | /api/start |
Start game, teleport players to mats |
| PUT | /api/toss |
Execute toss (body: { peg, hit }), awards badges on game end |
| PUT | /api/end-game |
End game early, calculate winner, award badges |
| PUT | /api/reset |
Clear board, reset peg images, remove ring assets |
Create a .env file in the root directory. See .env-example for a template.
| Variable | Description | Required |
|---|---|---|
INSTANCE_DOMAIN |
Topia API domain (api.topia.io for production) |
Yes |
INSTANCE_PROTOCOL |
Protocol (https) |
Yes |
INTERACTIVE_KEY |
Topia interactive app key | Yes |
INTERACTIVE_SECRET |
Topia interactive app secret | Yes |
- Clone the repository and install dependencies
npm install-
Configure environment variables
See Environment Variables above.
-
Run in development
npm run dev