Skip to content

KozielGPC/piano-hero

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

92 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

Piano Hero

About

Piano Hero is a Guitar Hero-inspired rhythm game built for piano. Players must hit falling notes at the correct timing to score points and build combos. The game features a built-in song editor for creating custom songs and supports audio synchronization.

Play

๐ŸŽฎ Play Online

Gameplay Video

Piano.Hero.-.Google.Chrome.2025-08-03.22-09-05.mp4

Piano Editor Video

WhatsApp.Video.2025-08-03.at.22.31.45.mp4
WhatsApp.Video.2025-08-03.at.22.32.36.mp4

๐Ÿ—๏ธ Architecture & Technology Stack

Core Technologies

  • Frontend: React 18 with TypeScript
  • Build Tool: Vite (fast HMR and optimized builds)
  • UI Framework: Material-UI (MUI) v5 - Complete component library
  • Audio Processing: WaveSurfer.js v7 - Advanced audio waveform visualization and playback
  • Graphics: Native HTML5 Canvas - Custom implementation for high-performance rendering

State Management

The application uses React Context API with three specialized contexts:

  • GameContext (src/context/GameContext.tsx) - Manages game state, scoring, and lifecycle
  • SongEditorContext (src/context/SongEditorContext.tsx) - Handles song creation and editing
  • SongFileHandlerContext (src/context/SongFileHandlerContext.tsx) - Manages file operations

๐ŸŽฎ Game Features & Implementation

๐ŸŽน Piano Rendering & Interaction

Component: src/components/PianoCanvas/index.tsx

  • Custom Canvas Engine: Built from scratch using HTML5 Canvas API
  • Visual Piano: Renders white and black keys with proper proportions
  • Real-time Interaction: Mouse clicks and keyboard inputs trigger notes
  • Visual Feedback: Keys light up when pressed with timing-based colors

Key Functions:

  • drawCanvas() - Main rendering loop in src/components/PianoCanvas/utils.ts
  • findNearestKeyAndMinDistance() - Click-to-key mapping
  • playNoteAudio() - Audio playback with caching

๐ŸŽต Falling Notes System

Implementation: src/components/PianoCanvas/index.tsx + src/components/PianoCanvas/utils.ts

  • Smooth Animation: RequestAnimationFrame-based note movement
  • Collision Detection: Custom algorithm for note-key intersection
  • Visual Design: Notes fall towards piano keys with proper scaling
  • Multi-note Support: Handles chords and complex patterns

Core Constants (src/components/PianoCanvas/constants.ts):

  • CANVAS_HEIGHT_DEFAULT: 600px canvas height
  • PIANO_HEIGHT: 150px piano section
  • LOOKAHEAD_TIME: 3 seconds of visible notes
  • WHITE_KEY_WIDTH: Key sizing calculations

๐ŸŽฏ Rhythm Engine & Scoring

Component: src/engine/RhythmEngine.ts

Advanced timing-based scoring system with multiple judgment levels:

  • Perfect: ยฑ0.2s (highest points)
  • Great: ยฑ0.3s
  • Good: ยฑ0.4s
  • Hit: Within timing windows
  • Miss: Outside timing windows

Features:

  • Combo System: Tracks consecutive hits with multipliers
  • Progress Tracking: Real-time completion percentage
  • Timing Windows: Configurable early/late tolerances
  • Key Indexing: Optimized note lookup per piano key

๐ŸŽผ Song Editor

Component: src/components/SongEditor/index.tsx

Full-featured song creation tool with multiple sub-components:

  • SongInformation - Set song metadata (name, artist, duration)
  • AudioUpload - Import background audio files
  • InteractiveGamePreview - Real-time preview with playback
  • NoteSelection - Choose which notes to place
  • NotesList - View and edit all song notes
  • ExportControls - Export songs as JSON
  • EditNoteDialog - Fine-tune note timing and duration

Editing Features:

  • Drag & Drop: Move notes by dragging on canvas
  • Duration Control: Resize notes by dragging bottom edge
  • Click Placement: Click piano keys to add notes
  • Audio Sync: Synchronize with background music

๐ŸŽต Audio System

Components: Multiple files handling different aspects

Audio Sources:

  • Individual Notes: public/sounds/ - All piano notes (C1-C8, including sharps/flats)
  • Background Music: User-uploaded files via src/components/SongEditor/components/AudioUpload/
  • Audio Caching: Optimized loading in src/components/PianoCanvas/index.tsx

WaveSurfer Integration:

  • Visual waveform display in song editor
  • Precise audio synchronization
  • Real-time playback control

๐ŸŽฎ Game Controller & States

Component: src/components/GameController/index.tsx

Manages game flow through five distinct states:

  1. MENU (src/components/GameController/components/Stages/Menu/) - Song selection
  2. LOADING (src/components/GameController/components/Stages/Loading/) - Asset loading
  3. PLAYING (src/components/GameController/components/Stages/Play/) - Active gameplay
  4. PAUSED (src/components/GameController/components/Stages/Pause/) - Game paused
  5. ENDED (src/components/GameController/components/Stages/EndGame/) - Results screen
  6. SONG_EDITOR - Song creation mode

๐Ÿ“Š Progress & Performance Tracking

Implementation: Throughout src/context/GameContext.tsx

  • Real-time Accuracy: Calculated as (correct notes / total notes) ร— 100
  • Combo Counter: Tracks consecutive hits, resets on miss
  • Score System: Points awarded based on timing accuracy
  • Progress Bar: Visual completion indicator

๐Ÿ”ง How The Game Engine Works

๐ŸŽฎ Core Game Loop & Timing System

The game operates on a precise timing system using performance.now() for millisecond accuracy:

Time Management (src/components/GameController/index.tsx):

const start = performance.now() - currentTime * 1000;
const step = (ts: number) => {
    actions.setCurrentTime((ts - start) / 1000);
    animationRef.current = requestAnimationFrame(step);
};

๐ŸŽต Note Falling Algorithm

Core Physics (src/components/PianoCanvas/utils.ts):

The falling notes use a sophisticated position calculation:

const timeUntilNote = noteStartTime - currentTime;
const fallProgress = (LOOKAHEAD_TIME - timeUntilNote) / LOOKAHEAD_TIME;
const fallAreaHeight = noteAreaHeight - NOTE_AREA_BOTTOM_PADDING;
const noteCenterY = fallProgress * fallAreaHeight + NOTE_AREA_TOP_PADDING;

How it works:

  1. LOOKAHEAD_TIME = 4 seconds - notes become visible 4 seconds before they should be hit
  2. fallProgress ranges from 0 (note appears) to 1 (note reaches piano)
  3. Position mapping: Linear interpolation between top of canvas and piano keys
  4. Real-time updates: 60fps via requestAnimationFrame

๐ŸŽฏ Timing Windows & Collision Detection

Rhythm Engine (src/engine/RhythmEngine.ts):

The game uses a sophisticated multi-tier timing system:

// Timing judgments (in seconds):
if (delta >= 0 && delta <= 0.2) judgement = "perfect";      // 300 points
else if (absDelta <= 0.3) judgement = "great";              // 200 points  
else if (absDelta <= 0.4) judgement = "good";               // 100 points
else if (delta >= -early && delta <= late) judgement = "hit"; // 50 points
else judgement = "miss";                                      // 0 points

Per-Key Indexing: The engine maintains separate note queues for each piano key for optimal performance:

  • Map<string, number[]> - Maps each key to its note indices
  • Map<string, number> - Tracks next unprocessed note per key
  • Prevents double-hits and optimizes lookup time

๐ŸŽจ Canvas Rendering Pipeline

Multi-Layer Rendering (src/components/PianoCanvas/utils.ts):

  1. Background Layer: Canvas background + piano strip
  2. Note Layer: Falling notes with collision shapes
  3. Piano Layer: Interactive keys with hit feedback
  4. UI Layer: Score feedback and labels

Optimized Rendering:

  • Viewport Culling: Only renders visible notes
  • Partial Redraws: Piano keys redraw separately via redrawPianoStrip()
  • Color-Coded Feedback: Instant visual feedback based on timing accuracy
// Note visibility optimization
const noteIsVisible = currentTime >= noteStartTime - LOOKAHEAD_TIME && 
                     currentTime <= noteEndTime + 1;
const noteIsInViewport = noteCenterY >= -NOTE_AREA_BOTTOM_PADDING && 
                        noteCenterY <= height;

๐ŸŽน Piano Key Mapping & Audio System

Keyboard Layout (src/utils/constants.ts):

  • 88 Piano Keys mapped to computer keyboard
  • White Keys: Letters (Q,W,E,R,T,Y,U,I,O,P, etc.)
  • Black Keys: Numbers (2,3,5,6,7, etc.)
  • Offset System: Each key has a precise visual offset for proper spacing

Audio Architecture:

  • Individual Note Sounds: 88 separate MP3 files in /public/sounds/
  • Audio Caching: Map<string, HTMLAudioElement> prevents reload delays
  • Background Audio Sync: WaveSurfer.js provides precision audio timing
  • Smart Audio Mixing: Piano sounds only play for wrong notes when background audio is active

๐ŸŽฎ Game State Machine

State Transitions (src/context/GameContext.tsx):

MENU โ†’ LOADING โ†’ PLAYING โ‡„ PAUSED โ†’ ENDED
  โ†“                                    โ†‘
SONG_EDITOR โ†โ†’ โ†โ†’ โ†โ†’ โ†โ†’ โ†โ†’ โ†โ†’ โ†โ†’ โ†โ†’ โ†โ†’ โ†โ†’

State Management: Each state has specific logic:

  • PLAYING: Active game loop, timing engine, collision detection
  • PAUSED: Suspends timing, preserves state
  • ENDED: Score calculation, progress tracking

๐Ÿ† Scoring & Combo System

Real-time Score Calculation:

// Accuracy: (correct / total) * 100
const accuracy = totalNotes > 0 ? (correctNotes / totalNotes) * 100 : 0;

// Combo Logic: Resets on wrong/miss, increments on correct
if (score.wrongNotes > prevScore.wrongNotes) setCombo(0);
else if (score.correctNotes > prevScore.correctNotes) {
    setCombo(prevCombo => {
        const newCombo = prevCombo + 1;
        setMaxCombo(prevMax => Math.max(prevMax, newCombo));
        return newCombo;
    });
}

๐ŸŽผ Song Editor Implementation

Interactive Note Editing:

  1. Drag & Drop: Converts mouse Y-position to time using getTimeFromY()
  2. Duration Editing: Bottom-edge dragging adjusts note length
  3. Real-time Preview: Instant visual feedback during editing
  4. Audio Synchronization: WaveSurfer provides waveform visualization

Data Flow:

User Input โ†’ Canvas Coordinates โ†’ Time Conversion โ†’ Note Update โ†’ Re-render

๐Ÿ”ง Performance Optimizations

Rendering Optimizations:

  • Selective Redraws: Only piano strip updates for key presses
  • Object Pooling: Reuses canvas contexts and audio elements
  • Viewport Culling: Skips off-screen note calculations
  • Efficient Hit Detection: Spatial partitioning for note lookups

Memory Management:

  • Audio Caching: Prevents repeated file loads
  • Context Cleanup: Proper cleanup of timers and event listeners
  • Component Memoization: Reduces unnecessary React re-renders

๐Ÿงฎ Mathematical Models

Note Position Formula:

Y = fallProgress ร— (canvasHeight - pianoHeight - padding) + topPadding
fallProgress = (lookaheadTime - timeUntilNote) / lookaheadTime
timeUntilNote = noteStartTime - currentGameTime

Timing Accuracy:

delta = userInputTime - noteStartTime
judgement = f(|delta|, timingWindows)
points = judgementMap[judgement].points

๐Ÿ“ Project Structure

src/
โ”œโ”€โ”€ components/
โ”‚   โ”œโ”€โ”€ GameArea/           # Main game container
โ”‚   โ”œโ”€โ”€ GameController/     # Game state management & stages  
โ”‚   โ”œโ”€โ”€ Header/            # Application header
โ”‚   โ”œโ”€โ”€ PianoCanvas/       # Core piano rendering & interaction
โ”‚   โ””โ”€โ”€ SongEditor/        # Song creation tools
โ”œโ”€โ”€ context/               # React Context providers
โ”‚   โ”œโ”€โ”€ GameContext.tsx    # Game state & scoring
โ”‚   โ”œโ”€โ”€ SongEditorContext.tsx # Song editing state
โ”‚   โ””โ”€โ”€ SongFileHandlerContext.tsx # File operations
โ”œโ”€โ”€ engine/
โ”‚   โ”œโ”€โ”€ RhythmEngine.ts    # Core game logic & timing
โ”‚   โ”œโ”€โ”€ types.ts           # Game engine types
โ”‚   โ””โ”€โ”€ constants.ts       # Timing configurations
โ”œโ”€โ”€ utils/
โ”‚   โ”œโ”€โ”€ constants.ts       # Piano notes & mappings
โ”‚   โ”œโ”€โ”€ interfaces.ts      # Type definitions
โ”‚   โ”œโ”€โ”€ songLibrary.ts     # Song management
โ”‚   โ””โ”€โ”€ time.ts            # Time utilities
โ””โ”€โ”€ songs/                 # Predefined songs

๐Ÿš€ Getting Started

Prerequisites

  • Node.js โ‰ฅ20
  • Yarn package manager

Installation & Running

# Clone repository
git clone https://github.com/KozielGPC/piano-hero.git

# Enter directory
cd piano-hero

# Install dependencies
yarn install

# Start development server
yarn dev

# Build for production
yarn build

# Preview production build
yarn preview

Available Scripts

  • yarn dev - Start development server with HMR
  • yarn build - TypeScript compilation + production build
  • yarn lint - ESLint code quality check
  • yarn preview - Preview production build locally

๐ŸŽต Available Songs

  • Interstellar Main Theme - Hans Zimmer (simplified)
  • Custom Songs - Import JSON files or create in the song editor

๐ŸŽน Game Controls

Keyboard Controls

Each piano key maps to a computer keyboard key:

  • White Keys: Letters (A, S, D, F, G, H, J, etc.)
  • Black Keys: Numbers and symbols
  • Full mapping: Defined in src/utils/constants.ts

Mouse Controls

  • Click Piano Keys: Play individual notes
  • Click Notes: Select/edit notes in song editor
  • Drag Notes: Move timing or adjust duration
  • Canvas Interaction: Add notes in editor mode

๐Ÿ”ง Technical Implementation Details

Performance Optimizations

  • Canvas Rendering: Optimized redraw cycles, only updates changed regions
  • Audio Caching: Preloads and caches all piano note sounds
  • RequestAnimationFrame: Smooth 60fps animation loops
  • Component Memoization: Prevents unnecessary re-renders

Timing System

  • High Precision: Uses performance.now() for millisecond accuracy
  • Audio Sync: Synchronizes visual elements with audio playback
  • Configurable Windows: Adjustable timing tolerances per difficulty

Song Data Format

Songs are stored as JSON with this structure:

{
  "name": "Song Name",
  "artist": "Artist Name", 
  "duration": 180,
  "notes": [
    {
      "note": "C4",
      "time": 1.5,
      "duration": 0.5,
      "type": "white"
    }
  ]
}

๐ŸŽฏ Current Features Status

  • โœ… Interactive piano with full keyboard
  • โœ… Falling notes with smooth animation
  • โœ… Advanced scoring system (Perfect/Great/Good/Hit/Miss)
  • โœ… Combo system with visual feedback
  • โœ… Song editor with audio synchronization
  • โœ… JSON song import/export
  • โœ… Audio file upload support
  • โœ… Real-time game preview
  • โœ… Drag-and-drop note editing
  • โœ… Multiple game states (Menu/Play/Pause/End)
  • โœ… Progress tracking and accuracy calculation

๐Ÿšง Future Enhancements

  • ๐ŸŽฏ Difficulty levels (Easy/Medium/Hard)
  • ๐Ÿ† Leaderboards and score persistence
  • ๐ŸŽผ Auto-generation from MP3 files
  • ๐ŸŒ Multiplayer gameplay
  • ๐Ÿ“ฑ Mobile device support
  • ๐ŸŽจ Visual themes and customization
  • ๐Ÿ”Š Sound effects and haptic feedback

๐Ÿค Contributing

Contributions are welcome! Feel free to:

  • ๐Ÿ› Report bugs via GitHub Issues
  • ๐Ÿ’ก Suggest features and improvements
  • ๐Ÿ”ง Submit Pull Requests
  • ๐Ÿ“– Improve documentation
  • ๐ŸŽต Create and share songs

๐Ÿ“„ License

This project is open source. Feel free to use, modify, and distribute according to the repository license.

About

Guitar Hero like piano game

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published