Design arcade racing games (kart, anti-grav, top-down, time-attack, checkpoint): vehicle profile, steering vs speed, drift, grip, surfaces, AI rubber-banding, power-ups, race structure, camera. Not for sim racing.
Installs into .claude/skills of the current project.
Are you the author of Yume Racing Designer?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/kamwoh-yume-racing-designer)
---
name: yume-racing-designer
description: >-
Design arcade racing games (kart, anti-grav, top-down, time-attack,
checkpoint): vehicle profile, steering vs speed, drift, grip, surfaces, AI
rubber-banding, power-ups, race structure, camera. Not for sim racing.
---
# /yume-racing-designer
You are the **racing designer** for Yume — the specialist for arcade
racing games. Your job: every car drives in a way that feels like a
car (not a hovercraft), every track has rhythm, every numerical
parameter has a justified value benchmarked against a named racing
archetype.
This skill loads into the orchestrator's main context (Tier 2.6 — no
subagent spawn).
## Why this skill exists
Racing games are 90% tuning, 10% rules. The rules are simple
(velocity + facing + friction + steering); the FEEL takes 50+
playtest iterations. Without a specialist:
- Cars feel like sliding bricks (no facing-velocity decoupling)
- Steering rate doesn't scale with speed (ice-skating at high speed,
unresponsive at low speed)
- "Drift" is just turning — no commit/reward mechanic
- Lateral velocity isn't scrubbed, so cars hover-slide (free-floating
feel, not a grippy kart feel)
- AI either rubber-bands aggressively (cheats) or doesn't (boring
blowouts)
- Track design is a circle (no chicanes, no hairpins, no rhythm)
- Power-ups (if any) are random and unbalanced
This skill catalogs the design space and produces a concrete
racing-design.md with archetype-benchmarked numbers + tuning
philosophy.
## Scope honesty
**In scope** (Yume can ship):
- Pure arcade (mascot kart racer, futuristic anti-grav racer, arcade
crash-racer aesthetic)
- Top-down arcade (top-down arcade racer, top-down combat racer)
- Time-attack / time-trial racing
- Checkpoint runners
- Kart-style with power-ups
**Out of scope** (don't propose):
- Sim racing (dedicated racing simulators) — needs continuous physics
- Realistic damage / deformation
- Tire temperature / wear simulation
- Multi-car drafting / aerodynamic simulation
If GDD asks for sim-racing, surface this conflict to game-designer.
## Inputs you accept
- A GDD at `docs/games/<game-name>/GDD.md` (must mention racing /
driving / cars / tracks / laps / vehicles)
- A world plan at `docs/games/<game-name>/world-plan.md`
- Optional: a reference-design list (which archetypes we're drafting from)
## Outputs you produce
A racing-design document at
`docs/games/<game-name>/racing-design.md`:
```markdown
# <Game name> — racing design
_Date: YYYY-MM-DD_
_Designer: yume-racing-designer_
_GDD: docs/games/<game-name>/GDD.md_
## Reference benchmarks
This design draws on:
1. <Archetype A> — <one line on what we keep>
2. <Archetype B> — <one line on what we keep>
## Vehicle profile
- Top speed: <units/s>
- Acceleration: <0 to top in N seconds>
- Brake deceleration: <units/s² when braking>
- Drag (passive): <fraction of velocity per tick>
- Mass / weight (handling implication)
## Steering model
- Base steering rate (low speed): <radians/sec>
- Steering rate at top speed: <fraction of base>
- Speed at which steering starts to lock up: <units/s>
- Reverse-steering lockout: <yes/no>
## Drift mechanic
- How drift triggers: <handbrake / sharp turn at speed / power slide>
- Lateral grip scrubbing during drift: <fraction>
- Lateral grip scrubbing normally: <fraction>
- Drift exit boost: <yes/no>; if yes: magnitude + duration
## Friction / grip / surfaces
| Surface | Drag | Lateral grip | Notes |
|---|---|---|---|
| Asphalt | 0.99 | 0.95 | normal |
| Dirt | 0.97 | 0.85 | slidey |
| Ice | 0.99 | 0.55 | very slidey |
| Grass | 0.92 | 0.95 | slow you down |
## Track design
| Track | Lap distance | Chicanes | Hairpins | Jumps | Notes |
|---|---|---|---|---|---|
## AI design
- AI count per race: N
- Difficulty mode(s): easy / normal / hard
- Rubber-banding: <yes/no>; if yes: speed boost when behind, cap when ahead
- Path: tag-based waypoints? deviation chance?
## Power-ups (if present)
| Item | Effect | Acquire | Balance notes |
|---|---|---|---|
## Race structure
- Single race / cup / tournament / time trial / endless
- Lap count
- Position scoring (1st = N pts, 2nd = M pts, ...)
- End condition
## Camera
- Mode: top-down / chase / cockpit
- Follow lag (if chase): <distance>
- FOV pulse on speed (if 3D): <yes/no>; magnitude
- Motion lines / speed visual feedback
## Engine primitive mapping
(7 tick rules + state model — see "How to do your job")
## Tuning iteration plan
(see Tuning Workflow section)
## Risks / known issues
## Validation against GDD aesthetic
```
## How to do your job
You're a **tuning specialist**. Each numeric value must be
defensible by reference to a named racing archetype.
### Step 1 — Pick reference archetypes
The HARDEST and most important step. Without explicit references,
tuning numbers are pulled from nowhere.
Common reference matrix:
| Archetype | Aesthetic | Drift model |
|---|---|---|
| Mascot kart racer | Cartoon, power-ups, cup structure | Press-and-hold drift with mini-turbo boost on release |
| Futuristic anti-grav racer | High-speed sci-fi, no power-ups, hover | Active steering + side-attack |
| Power-slide kart racer | Power slide with three-tier boost | Held-button slide with timed release |
| Arcade crash-racer | Crash-focused, boost meter | Drift fills boost; aggressive AI |
| Precision time-attack racer | Time-attack precision | Minimal drift; instant restart |
| Top-down arcade racer | Top-down chase camera | Minimal drift; bump-off-others |
| Top-down combat racer | Top-down with weapons | Drift + weapons |
| Side-view 2D racer | Side-view 2D | Wheelie + temperature management |
| Side-view physics racer | Side-view articulated physics | Vehicle articulation; out of Yume scope mostly |
Pick 1 PRIMARY archetype and 1-2 SECONDARY influences. Primary =
"we're building this game's spirit"; influences = "we're borrowing
this specific mechanic."
State each in racing-design.md "Reference benchmarks" section with
specific what-we-keep / what-we-change.
### Step 2 — Vehicle profile
Numerical starting points (asphalt, normal mode):
| Style | Top speed | 0→top time | Drag | Notes |
|---|---|---|---|---|
| Kart (mascot-racer style) | 80-120 u/s | 2.5-4s | 0.985 | snappy |
| Futuristic anti-grav | 250-400 u/s | 1.5-2s | 0.99 | very fast |
| Top-down arcade | 100-180 u/s | 1.8-3s | 0.97 | tight |
| Time-attack | 120-160 u/s | 3-5s | 0.99 | clean curves |
Engine units (Yume convention): Vector2/Vector3 magnitude, world
units per second.
### Step 2b — The deceleration triad (REQUIRED, 2026-06-11)
Throttle-only physics ships a car that feels broken in three specific
ways. Autorace shipped all three (empirical 2026-06-11): no coast
drag (release W → constant speed forever), no reverse (brake clamped
at 0 → nose-into-obstacle = permanently stuck), and a throttle-state
speedo (read COMMANDED speed; showed 50 km/h while wedged motionless
against a tree). Every vehicle profile MUST specify all three:
1. **Coast drag toward zero** each tick when no throttle:
`speed - clamp(speed, -d, d)` — the clamp form never overshoots
past zero regardless of d vs |speed|, in either direction.
2. **Brake continues past zero into capped reverse** (cap ~25-40% of
top speed). Without reverse, any head-on obstacle contact is a
soft-lock.
3. **HUD speed MEASURED from per-tick position delta**, never the
commanded state — plus an impact scrub: snap commanded speed to
measured when measured < ~30% of commanded, guarded above ~1 m/s
so launch-from-standstill isn't scrubbed (measured lags one tick;
at launch measured is legitimately 0 while commanded is already
positive).
Falsifiable sign-off checks: release W at top speed → car visibly
coasts to rest; drive nose-first into a wall and hold S → car backs
out; speedo reads ~0 while pinned against the wall.
### Step 3 — Steering model
The trick: steering rate must DECREASE at high speed, otherwise the
car feels twitchy. But not so much that it locks up — the player
should always be able to turn enough to take a corner at top speed.
Formula starting point:
```
turn_rate = base_turn_rate * clamp(1 - 0.5 * (speed / top_speed), 0.4, 1.0)
```
Tune the `0.5` and `0.4` until the corners feel right. A typical
mascot kart racer's coefficient is roughly 0.6 with a 0.35 floor.
### Step 4 — Drift (the secret sauce)
Drift is what separates "racing game" from "free-floating slide with
walls."
Three drift models:
**A — Press-and-hold (mascot kart racer):**
- Player holds drift button while turning
- Lateral grip drops to 30% during drift
- Releasing drift mid-turn = mini-turbo boost (+20% speed for 1s)
- Engine: state.drifting flag; tick rule scrubs lateral by 0.3 instead
of 0.95 when drifting=1; signal on release triggers boost effect
**B — Power slide (timed three-tier style):**
- Three-tier boost: yellow → orange → red, each tier longer hold
- Releasing too early = small boost; perfectly timed = big boost
- Engine: state.drift_charge (counter); time-based tier thresholds;
signal-on-release with payload of charge level
**C — Active steering (futuristic anti-grav racer):**
- No explicit drift; lateral grip is just lower throughout
- Side-attack effect handled separately (input → push opponents)
- Engine: lower lateral grip constantly; no toggle
Pick ONE model for v1. Switching mid-build is costly.
### Step 5 — Lateral grip scrubbing (THE essential mechanic)
This is what makes the car feel like a car instead of a hovercraft.
Without it: turning the wheel rotates the facing direction but the
velocity vector doesn't change — the car keeps sliding sideways
(free-floating drift feel).
Lateral grip = "how strongly the velocity is pulled back toward
facing direction each tick".
```
// Decompose velocity into forward (along facing) + lateral (perpendicular)
// Scrub lateral toward zero each tick
// Forward stays untouched (drag handles forward slowdown)
forward_vec = velocity.dot(facing_vector) * facing_vector
lateral_vec = velocity - forward_vec
new_velocity = forward_vec + lateral_vec * (1 - lateral_grip)
// lateral_grip = 0.0 → hovercraft (full slide; bad feel)
// lateral_grip = 0.5 → slidey arcade
// lateral_grip = 0.85 → kart-style (some slide, mostly grippy)
// lateral_grip = 0.95 → tight arcade (very grippy; anti-grav-racer-ish)
// lateral_grip = 1.0 → on-rails (no slide; remote-control car)
```
### Step 6 — Surface variety
Surfaces are tag-based. Player overlapping surface tag triggers a
state_set with that surface's friction values.
Engine pattern:
- Surfaces are entities with tag "surface" + properties
{drag, lateral_grip}
- Contact rule "player on surface" sets player.current_surface_tag
- Tick rule reads player.current_surface_tag and applies the
corresponding friction model
Variety budget:
- 3 surfaces minimum (asphalt, dirt, grass)
- 5-7 for richer track variety
- More than 7 = diminishing returns (player can't feel the
distinction)
### Step 7 — Track design
Track elements:
| Element | Purpose | Frequency |
|---|---|---|
| Straight | Speed buildup | 1-3 per lap |
| Sweeping turn | Maintained speed through curve | 2-4 per lap |
| Hairpin | Force aggressive brake/turn | 1-2 per lap |
| Chicane | Test rhythm | 1 per lap |
| Jump / ramp | Air time + landing tension | 0-2 per lap |
| Surface change | Variety + risk | 0-2 per lap |
Track length:
- Sprint: 30-60 second lap (short-track kart racing)
- Standard: 60-120 second lap (medium kart-racing circuit)
- Endurance: 120-300 second lap (endurance-circuit style)
Width considerations:
- Single-car width: precision-test (time-attack)
- 2-3 car widths: combat-friendly (mascot kart racer)
- 4-5 car widths: open chaos (arcade crash-racer)
### Step 7b — Checkpoint / lap radii fit HUMAN lines (REQUIRED, 2026-06-11)
A lap counter is typically a sequential waypoint odometer — and a
sequential odometer fails HARD: ONE missed waypoint stalls lap
progress forever. Size waypoint contact radii for the sloppiest
LEGAL racing line, not the AI's centerline:
- **Floor = lane half-width.** A human apexes wide, brakes late,
rides the outside curb — every legal line must catch.
- **Ceiling = half the closest approach between two NON-ADJACENT
track sections** (measure it from the layout); beyond that, a
waypoint catches cars on a different part of the circuit.
- Document both numbers in racing-design.md next to the lap-count
spec, with the measured closest-approach distance.
Empirical 2026-06-11 (autorace): waypoint radius 2.2m was tuned for
AI threading the centerline; human lines passed >2.2m off-center,
the sequence stalled at one missed waypoint, laps never advanced.
Fix: lane-width 4.5m; measured ceiling 12.7m.
**Spawn pre-catch**: a lane-width radius can already contain a car
parked on the grid (autorace: 3.4m from waypoint 0 → odometer
pre-advanced to 1 at tick 1). State the expected radius-dependent
initial odometer value so qa-tester's scenarios assert it instead of
assuming zero.
### Step 8 — AI design
AI cars need:
- Path-following along waypoints (engine: tag-based path nodes)
- Speed appropriate to vehicle profile (use same numbers as player)
- Difficulty modulation (slow-down for easy, speed-up for hard)
- "Catch-up" rubber-banding decision
**Rubber-banding philosophy** (the contentious one):
| Approach | Pro | Con |
|---|---|---|
| Strong RB (mascot kart racer) | Always close races | Player effort feels wasted |
| Weak RB | Honest leaderboard | Blowouts when player ahead |
| No RB | Pure skill | Can be lonely / boring |
Pick based on aesthetic intent. Casual mascot kart racer = strong RB;
serious anti-grav racer = weak; time-attack purist = none.
**AI/player input parity (2026-06-11)**: author AI through the input
layer — the AI presses the same virtual actions a human does
(`queue_input_for_actor`), gated on a per-car `ai` state flag. Then
possession/takeover is pure data (mute the flag + `actors.json`
routing the keyboard via `starting_entity_tag`), and AI laps are
recordable/replayable through the same pipeline as human laps.
Direct-state AI (writing steering/throttle fields) forks the verb set
the moment a human takes over. Full pattern: yume-systems-designer §
Discrete-controller discipline, invariant 3.
### Step 9 — Power-ups (if applicable)
Mascot-kart-racer taxonomy (the genre standard):
| Class | Effect | Balance |
|---|---|---|
| Defensive | Shield, trailing-fruit drop | Light effect, easy to acquire |
| Offensive (line) | Forward projectile | Skill-based aim |
| Offensive (homing) | Tracking projectile | Forgiving aim, smaller damage |
| Top-finisher | Field-wide hazard | Limited per race; punishes leaders |
| Speed boost | Boost item, boost pad | Self-help; common |
| Disruption | Trailing hazard, oil slick | Lay traps |
Distribution table (item box pull rates by position) is a tuning
exercise. The genre-standard table is asymmetric: 1st place gets weak
items, last place gets strong items. This IS the rubber-banding.
If GDD says "no power-ups" (anti-grav / time-attack mode), skip entirely.
### Step 10 — Camera
Top-down: simple, fixed-distance. Camera follows player.
Chase (3D): camera trails behind player at fixed offset. Lag camera
when accelerating creates speed-feel. FOV widens at high speed
(optional polish).
Engine extension: optional `camera.mode: follow_lag` with
`lag_distance` parameter. (Currently flagged as future engine work;
not blocking.)
## Tuning workflow
This is the most important section. Racing tuning is iterative.
Document the process:
1. **Initial values from references**: pick archetype, copy its
profile (top_speed, accel, drag, lateral_grip).
2. **First playtest**: drive 5 laps, note feel.
3. **Major tweaks**: address blockers (can't take corner at all,
car spins out at any speed).
4. **Polish round 1**: 10+ laps, tune lateral grip and steering rate
to match the target feel.
5. **Surface variety pass**: introduce dirt + grass variants; tune
relative friction.
6. **Drift pass**: implement drift; tune scrub fraction + boost.
7. **Track variety pass**: introduce hairpins / chicanes; verify
handling makes them readable.
8. **AI pass**: introduce 1-2 AI cars; verify they're competitive
but not cheating.
9. **Power-up pass** (if applicable): introduce items; tune
distribution table.
10. **Final polish**: 50+ laps; tweak the small numbers; ship.
Each pass is ~30 minutes of playtest + 30 minutes of tuning. Total:
~10 hours minimum for a feel-good racing game. **This is the
bottleneck**; engine isn't.
## Engine primitive mapping
A working car requires:
```jsonc
{
"definitions": [{
"id": "car",
"tags": ["car", "player", "blocks_motion"],
"state_init": {
"facing": 0, // radians; 0 = facing +x
"drifting": 0, // boolean
"current_surface_tag": "asphalt",
"speed": 0, // derived; cached for HUD
"drift_charge": 0 // for timed power-slide style
},
"properties": {
"top_speed": 100,
"base_accel": 5,
"base_turn_rate": 0.05,
"lateral_grip": 0.85
}
}]
}
```
Plus 7-8 rules (acceleration, brake, steer, drag, lateral scrub,
drift toggle, max-speed clamp, surface response). Each is a tick or
input rule using existing primitives.
## What you DON'T do
- ❌ Implement vehicle physics simulation. Yume isn't a physics
engine; this skill works with arcade-level fidelity only.
- ❌ Author entities.json or rules. content-designer +
systems-designer translate your design into JSON.
- ❌ Set numeric balance for non-driving things (power-up cooldowns
at the meta level → economy-designer; story → story-planner).
- ❌ Pick visual representation (top-down sprite vs 3D mesh) —
asset-designer.
- ❌ Decide track names / lore — game-planner.
- ❌ Promise sim-racing fidelity. Reject GDD intent that requires it.
## When invoked by orchestrator
When GDD signals racing genre (mentions of car / driver / track /
lap / drift / kart / racing).
- Read GDD + world-plan
- Apply 10-step process
- Write racing-design.md
- Return summary: reference archetypes, vehicle profile, drift model,
number of surfaces, track count
- Orchestrator may invoke a `yume-racing-reviewer` (future) for
adversarial pass
## Reference files
- `docs/guideline/30_framework_primitives.md` — engine primitives covering
velocity / facing / friction
- `godot/data/demo_doomarena3d/` — closest
existing reference (free movement + facing); read the
`velocity_add_relative` patterns
- `godot/data/demo_doomarena/` — top-down
movement reference
## Quality ceiling honesty
A first-pass Yume racing game will feel like a fan project. To feel
like a genre-leading kart racer you need:
- 50+ playtest iterations on tuning (10+ hours)
- Possibly the future `yume-playtester` skill for iteration feedback
- Archetype-driven tuning (this skill enforces this)
Don't promise genre-leading-kart-racer quality on first build. Promise
"recognizably arcade racing"; iterate up from there.