- buildClassicalNotes() had an unreachable return after the note-building chain, so simplifyNotes() (the Full/Simple note-density toggle) was never applied to any isClassical piece — fixed by assigning to a variable first. - Jingle Bells' note durations used an eighth-note-heavy pattern that compressed the tune to roughly half its correct length instead of the familiar quarter/half-note "Jingle bells, jingle bells" cadence — replaced with a standard, measure-verified rhythm. - Drunken Sailor inserted a stray extra beat between each of its 3 passes (t+=q, one full quarter note tied to the beat grid) which broke the 4/4 pulse; changed to an off-grid pause. Also extended its chord backing to cover the chorus (mm9-16), which previously had none on repeat passes. - Removed O Fortuna (Orff, 1936) and Sabre Dance (Khachaturian, 1942) from Classical, and Rudolph the Red-Nosed Reindeer (1949), Frosty the Snowman (1950), and Winter Wonderland (1934) from Christmas — none of these are actually public domain (all still under active copyright), despite being filed under a "public domain compositions" list. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PbwKCCj1vwAoqgRYDoqgeL
300 lines
12 KiB
Markdown
300 lines
12 KiB
Markdown
# 🥁 Drum Rhythm Game — Claude Handoff Document
|
||
|
||
This file tells Claude exactly what this project is, what has been built, what needs to be built next, and how everything works. Read this entire file before making any changes.
|
||
|
||
---
|
||
|
||
## What This Is
|
||
|
||
A browser-based drum rhythm game built as a single HTML file. It works like Rock Band — notes scroll down the screen and the player hits the matching drum pad in time. It runs entirely in the browser with no server, no dependencies, no npm. Just open `index.html`.
|
||
|
||
The game was originally built to work with a **Wii Rock Band drum kit connected via USB** on Windows, Mac, and Linux. It also works with keyboard keys.
|
||
|
||
---
|
||
|
||
## Current File Structure
|
||
|
||
Right now everything is in one file: `index.html`. As this project grows, split it as follows:
|
||
|
||
```
|
||
drum-rhythm-game/
|
||
├── index.html ← main shell, links all JS/CSS
|
||
├── css/
|
||
│ └── style.css ← extract all <style> here
|
||
├── js/
|
||
│ ├── audio.js ← AudioContext, drum sounds, synthesizer
|
||
│ ├── rhythms.js ← all genre drum patterns
|
||
│ ├── classical.js ← classical pieces, note sequences, synth orchestra
|
||
│ ├── game.js ← game loop, scoring, hit detection, players
|
||
│ ├── canvas.js ← all canvas drawing
|
||
│ ├── input.js ← keyboard + gamepad input
|
||
│ └── menu.js ← UI screens, genre tabs, pad toggles
|
||
└── CLAUDE.md ← this file
|
||
```
|
||
|
||
---
|
||
|
||
## Hardware Setup
|
||
|
||
- **Drum kit**: Wii Rock Band drums connected via USB dongle
|
||
- **Pads**: Red, Yellow, Blue, Green (4 pads) + Kick pedal
|
||
- **OS**: Must work on Windows 11, Linux, and Mac
|
||
- **Browser**: Chrome or Edge recommended for gamepad API support
|
||
|
||
### Gamepad Button Mapping (Wii Rock Band via USB)
|
||
```
|
||
Button 0 → Blue (lane 2)
|
||
Button 1 → Green (lane 3)
|
||
Button 2 → Red (lane 0)
|
||
Button 3 → Yellow(lane 1)
|
||
Button 4 → Kick (lane 4)
|
||
Button 8 → Kick (lane 4) — alternate
|
||
```
|
||
|
||
### Lane Definitions
|
||
```
|
||
Lane 0 = Red — Tom high — keyboard: F
|
||
Lane 1 = Yellow — Snare — keyboard: G
|
||
Lane 2 = Blue — Hi-hat — keyboard: H
|
||
Lane 3 = Green — Tom low — keyboard: J
|
||
Lane 4 = Kick — Bass drum — keyboard: Space
|
||
```
|
||
|
||
---
|
||
|
||
## What Has Been Built
|
||
|
||
### Screens
|
||
1. **Menu screen** — mode select, rhythm picker, pad toggles, players, leaderboard
|
||
2. **Game screen** — canvas highway, HUD (score/streak/acc/player), countdown
|
||
3. **Leaderboard screen** — all saved scores sorted by score
|
||
|
||
### Modes
|
||
1. **Rhythm Mode** — select a genre + rhythm, notes scroll, drum pattern plays as audio background, score your hits
|
||
2. **MP3 Jam Mode** — load your own MP3, it plays in background, drum freely (no chart, no scoring)
|
||
|
||
### Genres & Rhythms (8 genres × 15 patterns = 120 rhythms)
|
||
- Rock, Metal, Jazz, Hip Hop, Funk, Latin, Electronic, Country
|
||
- Each rhythm has: name, BPM, bars, pattern array
|
||
- Pattern format: `{t: beat_offset, l: lane}` where t is within a 4-beat bar
|
||
|
||
### Rhythm Pattern System
|
||
```javascript
|
||
// Example pattern entry
|
||
{n:"Basic Rock", bpm:90, bars:8, p:[
|
||
{t:0, l:4}, // kick on beat 1
|
||
{t:0, l:2}, // hihat on beat 1
|
||
{t:1, l:1}, // snare on beat 2
|
||
// etc.
|
||
]}
|
||
```
|
||
- `bars` controls how many times the 4-beat pattern repeats
|
||
- Notes are built by looping the pattern for the full bar count
|
||
- Only notes on **active pads** appear on screen (user can toggle pads)
|
||
|
||
### Pad Toggle System
|
||
- Menu has colored buttons for each pad/kick
|
||
- Toggle off = pad makes sound when hit but shows no notes and doesn't score
|
||
- Designed for beginners — start with kick+snare, add more pads as you improve
|
||
|
||
### Scoring
|
||
- Hit within 0.17 seconds of note time = counts as hit
|
||
- Within 0.05s = "PERFECT" (green), otherwise "GOOD" (yellow)
|
||
- Miss = streak resets
|
||
- Score = 100 × min(streak, 10) per hit
|
||
- Scores saved to localStorage key `"drgame5"`
|
||
|
||
### Multiplayer (Take Turns)
|
||
- Add players in menu (up to N players)
|
||
- Each player takes a turn on the same rhythm
|
||
- After all turns, results shown sorted by score
|
||
- All scores saved to leaderboard
|
||
|
||
### Audio System
|
||
- Uses Web Audio API — no external files needed
|
||
- **Critical**: AudioContext must be unlocked on user gesture — especially important on Linux/Chrome
|
||
- Unlock happens on any click, keydown, touchstart, mousedown
|
||
- Two separate AudioContexts: `previewAc` (menu preview) and `gameAc` (in-game)
|
||
- Both must call `.resume()` aggressively
|
||
|
||
### Drum Sounds (Synthesized)
|
||
```
|
||
Kick → sine oscillator, 180Hz → 40Hz sweep, ~0.3s
|
||
Snare → highpass noise burst + 180Hz tone body
|
||
Hi-hat→ highpass noise burst, very short ~0.05s
|
||
Tom → sine oscillator, 160Hz → 64Hz sweep
|
||
Tom2 → sine oscillator, 120Hz → 48Hz sweep
|
||
```
|
||
|
||
### Canvas Layout
|
||
- Top 78% = 4 pad lanes side by side
|
||
- Bottom 22% = kick zone (full width, centered)
|
||
- Hit line at 76% down the pad zone
|
||
- Notes fall from top, future notes above hit line
|
||
- Note Y position: `noteY = HIT_Y - (noteTime - currentSongTime) * SPEED`
|
||
- SPEED = 260px/second
|
||
- Notes outside screen bounds are skipped (culled)
|
||
- Missed notes (past hit line by HIT_WIN) fade to 20% opacity
|
||
|
||
### Preview System
|
||
- In menu, click Preview to hear any rhythm before playing
|
||
- Auto-loops the pattern using scheduled Web Audio nodes
|
||
- Plays all drum hits as audio so user can hear the beat
|
||
- Stops cleanly when switching rhythms or starting game
|
||
|
||
---
|
||
|
||
## What Needs To Be Built Next
|
||
|
||
### 1. Classical Music Genre Tab (PRIORITY)
|
||
|
||
Add a new genre called **"Classical"** with the following pieces. Each piece needs:
|
||
- A synthesized melody/orchestral background that plays automatically
|
||
- A separate set of "hittable" notes (melody notes only) that scroll on screen
|
||
- The player hits the melody rhythm, background fills in the rest
|
||
|
||
#### Pieces to implement (all public domain compositions):
|
||
|
||
| Piece | Composer | Notes |
|
||
|-------|----------|-------|
|
||
| Beethoven's 5th (Opening) | Beethoven | DA DA DA DUM — 3 same pad + 1 different |
|
||
| Hall of the Mountain King | Grieg | Starts slow, accelerates — great difficulty curve |
|
||
| Ride of the Valkyries | Wagner | Galloping rhythm pattern |
|
||
| Mars, Bringer of War | Holst | Heavy 5/4 march |
|
||
| Toccata & Fugue in D Minor | Bach | Famous DUN DUN DUN opener |
|
||
| William Tell Overture (Gallop) | Rossini | Fast galloping rhythm |
|
||
| Bolero | Ravel | Literally a drum pattern that builds — perfect |
|
||
| Also Sprach Zarathustra | Strauss | DA DAAAA DA DUM (2001 theme) |
|
||
| Barber of Seville Overture | Rossini | Bugs Bunny classic |
|
||
| The Blue Danube | Strauss Jr. | Waltz rhythm |
|
||
| Night on Bald Mountain | Mussorgsky | Fantasia — dark and dramatic |
|
||
| Sorcerer's Apprentice | Dukas | Fantasia — Mickey Mouse |
|
||
| Swan Lake (Theme) | Tchaikovsky | Elegant waltz |
|
||
| Morning Mood | Grieg | Peer Gynt — gentle build |
|
||
| In the Hall of the Mountain King | Grieg | (same as above, confirm not duplicate) |
|
||
|
||
> **Not actually public domain — do not re-add:** O Fortuna (Orff, 1936; composer d. 1982 — still under copyright until 2032 in the US / 2052 in the EU) and Sabre Dance (Khachaturian, 1942; composer d. 1978 — still under copyright until 2048 in the EU) were removed from the repo on this basis. The rest of this table is genuinely public domain (composers who died before ~1955, or works published before 1930).
|
||
|
||
#### How Classical Mode Should Work
|
||
1. Player selects a classical piece
|
||
2. Game starts with countdown
|
||
3. **Background**: Full synthesized orchestral arrangement plays automatically (Web Audio oscillators, multiple voices, proper frequencies)
|
||
4. **Foreground**: Only the main melody notes scroll down as hittable notes
|
||
5. Player hits the melody rhythm — satisfying because they're "playing" the famous part
|
||
6. Scoring same as rhythm mode
|
||
|
||
#### Synthesizer Architecture for Classical
|
||
Use multiple oscillator types for different instruments:
|
||
```javascript
|
||
// Strings — sawtooth oscillator + lowpass filter
|
||
// Brass — square oscillator + envelope
|
||
// Woodwind— triangle oscillator
|
||
// Bass — sine oscillator, low frequency
|
||
// Timpani — sine sweep, like kick but lower
|
||
// Choir — multiple detuned sine oscillators
|
||
```
|
||
|
||
Use a note-scheduling system:
|
||
```javascript
|
||
// Notes stored as: {time, freq, duration, instrument, volume}
|
||
// Schedule all notes at game start using AudioContext time
|
||
// This ensures perfect sync regardless of JS timing
|
||
```
|
||
|
||
#### Note Frequencies Reference
|
||
```javascript
|
||
const NOTES = {
|
||
C3:130.81, D3:146.83, E3:164.81, F3:174.61, G3:196.00,
|
||
A3:220.00, Bb3:233.08, B3:246.94,
|
||
C4:261.63, D4:293.66, E4:329.63, F4:349.23, G4:392.00,
|
||
A4:440.00, Bb4:466.16, B4:493.88,
|
||
C5:523.25, D5:587.33, E5:659.25, F5:698.46, G5:783.99,
|
||
A5:880.00, C6:1046.50
|
||
};
|
||
```
|
||
|
||
#### Beethoven's 5th — Starter Implementation
|
||
```
|
||
Opening motif (G minor):
|
||
- G4 (short) → G4 (short) → G4 (short) → Eb4 (long)
|
||
- F4 (short) → F4 (short) → F4 (short) → D4 (long)
|
||
|
||
Drum mapping:
|
||
- Short notes → Red pad (lane 0)
|
||
- Long notes → Green pad (lane 3)
|
||
- Background: strings + brass arrangement
|
||
```
|
||
|
||
---
|
||
|
||
### 2. Audio Improvements
|
||
- Make drum sounds punchier with a slight distortion/clipping on kick
|
||
- Add reverb to classical orchestral sounds (ConvolverNode or simple delay feedback)
|
||
- Consider a master volume slider in the game HUD (not just menu)
|
||
|
||
### 3. Visual Improvements
|
||
- Scrolling speed lines in lane backgrounds for motion feel
|
||
- Note "explosion" particle effect on perfect hit
|
||
- Combo multiplier display (currently capped at 10x but not shown prominently)
|
||
- BPM display during game
|
||
|
||
### 4. Gameplay Features
|
||
- **Practice mode**: slow down to 50/75% speed
|
||
- **Difficulty**: Easy (fewer notes), Medium (all notes), Hard (+ extra fills)
|
||
- **Endless mode**: rhythm loops until you quit, cumulative score
|
||
- **Song length selector**: 1 min / 2 min / full length
|
||
|
||
### 5. Quality of Life
|
||
- Remap button in-game HUD (not just standalone soundboard)
|
||
- Volume control per sound type (kick louder than hihat etc.)
|
||
- "How to play" screen
|
||
- GitHub Pages deployment so it runs at a URL without downloading
|
||
|
||
---
|
||
|
||
## Known Issues & Bugs
|
||
|
||
1. **Linux audio** — AudioContext needs aggressive `.resume()` on every user interaction. Already fixed in current code but watch for regressions.
|
||
2. **Pad toggle visual** — toggling a pad on/off used to flicker (toggle on click). Fixed to be one-directional but confirm behavior.
|
||
3. **High BPM rhythms** — at 200+ BPM notes can stack visually. May need note size scaling by BPM.
|
||
4. **MP3 Jam scoring** — currently no chart in MP3 mode, just free play. Future: beat detection to generate a chart from the MP3.
|
||
|
||
---
|
||
|
||
## Tech Constraints
|
||
|
||
- **No external libraries** — pure vanilla JS, Web Audio API, Canvas 2D
|
||
- **No build step** — must work by opening index.html directly
|
||
- **No server required** — localStorage for scores, no backend
|
||
- **Single HTML file** initially, refactor to multi-file as needed
|
||
- **Cross-platform** — Windows 11, Linux (Ubuntu/Fedora), Mac, any modern browser
|
||
|
||
---
|
||
|
||
## Style Guide
|
||
|
||
- Dark theme: background `#0a0a0f`, cards `#13131f`, borders `#222`
|
||
- Lane colors: Red `#e53e3e`, Yellow `#d69e2e`, Blue `#3182ce`, Green `#38a169`, Kick `#805ad5`
|
||
- Accent: Purple `#805ad5` for buttons/highlights
|
||
- Font: system sans-serif, no imports needed
|
||
- Minimal UI — game canvas should dominate the screen
|
||
|
||
---
|
||
|
||
## How To Test
|
||
|
||
1. Open `index.html` in Chrome or Edge
|
||
2. Click any genre tab → select a rhythm → click Preview to hear it
|
||
3. Click Start → watch countdown → notes should fall → hit F/G/H/J/Space
|
||
4. For drum kit: plug in USB, hit any pad to wake gamepad API, should show "🎮 Connected"
|
||
5. Test on Linux: click something first before hitting Preview — audio needs a gesture
|
||
|
||
---
|
||
|
||
## Questions / Decisions Needed
|
||
|
||
- [ ] Should classical pieces loop or play once through?
|
||
- [ ] Should the synthesized orchestra volume be adjustable separately from drum hit volume?
|
||
- [ ] For Bolero specifically — should difficulty increase as the piece builds (more notes appearing)?
|
||
- [ ] Should we add a GitHub Pages deploy so it runs at a public URL?
|