Skip to content

Tsabo/SQLitePong

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

1 Commit
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

SQLitePong - Pong in SQL using SQLite and C#

A complete implementation of the classic Pong game written entirely in SQL, running on SQLite with a C# host application.

Note: This is a C# port of the original DuckPong by Thomas Zeutschler. The original project demonstrates the power of DuckDB and SQL by implementing Pong purely in SQL. This port adapts the concept to SQLite and C#, maintaining the core philosophy while adding cross-platform support and modern terminal features.

๐ŸŽฎ What is SQLitePong?

SQLitePong is an educational project that showcases the capabilities of SQL by implementing a fully playable Pong game where:

  • All game logic runs in SQL - Physics, collisions, AI, and scoring
  • Rendering is done in SQL - The entire game screen is generated via SQL queries
  • C# provides only I/O - Keyboard input, display output, and timing
  • No game logic in C# - Everything except display and input is pure SQL

This demonstrates that SQL is not just a query language but a complete computational platform capable of complex real-time applications.

๐ŸŽฏ Features

  • โœ… Complete Pong gameplay with classic physics
  • โœ… Advanced AI with distance-based strategy and trick shots
  • โœ… 3ร—5 pixel font rendering for large score display
  • โœ… Dynamic FPS control (15, 30, 60, 120 FPS, and MAX mode)
  • โœ… Sound effects (scoring and paddle hits)
  • โœ… Color terminal output using Spectre.Console
  • โœ… Alternate screen buffer (like vim/less)
  • โœ… Cross-platform (Windows, Linux, macOS)

๐Ÿš€ Quick Start

Prerequisites

  • .NET 10 SDK or later
  • A terminal with ANSI escape sequence support (Windows Terminal, iTerm2, etc.)

Running the Game

This project uses the new .NET 10 dotnet run app feature:

# Clone the repository
git clone https://github.com/tsabo/sqlitepong
cd sqlitepong

# Run the game (no build or project file needed!)
dotnet run app.cs

The required NuGet packages (Microsoft.Data.Sqlite and Spectre.Console) are automatically restored from the #:package directives at the top of the file.

๐ŸŽฎ Controls

Key Action
ESC Exit game
S Toggle sound effects
+ Increase FPS (15 โ†’ 30 โ†’ 60 โ†’ 120 โ†’ MAX)
- Decrease FPS (MAX โ†’ 120 โ†’ 60 โ†’ 30 โ†’ 15)

๐Ÿ—๏ธ How It Works

Architecture

graph TB
    subgraph "C# Host Application (app.cs)"
        KB[Keyboard Input]
        DISP[Display Rendering<br/>Spectre.Console]
        TIME[Frame Timing & Sound]
    end
    
    subgraph "SQLite In-Memory Database"
        STATE[Game State Table<br/>โ€ข Paddle positions<br/>โ€ข Ball position/velocity<br/>โ€ข Scores<br/>โ€ข Tick counter]
        
        subgraph "Game Logic (tickSql - CTE Chain)"
            AI[Step 1: AI Decision<br/>trick shots + tracking]
            MOVE[Step 2: Ball Movement]
            WALL[Step 3: Wall Collision]
            PADDLE[Step 4: Paddle Collision<br/>angle physics]
            SCORE[Step 5: Scoring Detection]
            UPDATE[Step 6: State Update]
            
            AI --> MOVE --> WALL --> PADDLE --> SCORE --> UPDATE
        end
        
        subgraph "Rendering (renderSql - 80ร—25 grid)"
            GRID[Generate Coordinates]
            PIXEL[Pixel-by-Pixel CASE]
            FONT[3ร—5 Font Lookup]
            COLOR[Color Metadata]
            
            GRID --> PIXEL
            PIXEL --> FONT
            PIXEL --> COLOR
        end
    end
    
    KB -->|ESC, S, +/-| TIME
    TIME -->|Execute tickSql| UPDATE
    UPDATE -->|UPDATE state| STATE
    STATE -->|SELECT pixels| GRID
    COLOR -->|Markup| DISP
    DISP -->|Terminal Output| USER((Player))
    TIME -->|Beep| USER
    
    style STATE fill:#e1f5ff
    style UPDATE fill:#ffe1e1
    style DISP fill:#e1ffe1
    style USER fill:#fff4e1
Loading

SQL Techniques Demonstrated

  1. Common Table Expressions (CTEs) - Breaking complex logic into steps
  2. Recursive CTEs - Generating sequences (field coordinates)
  3. Window Functions - Not used here, but could be for advanced scoring
  4. CASE Expressions - Conditional logic (AI decisions, rendering)
  5. JOINs - Font rendering, coordinate mapping
  6. Aggregate Functions - String concatenation for rendering
  7. Random Number Generation - Ball serves, AI imperfection
  8. State Management - Single-row UPDATE pattern

๐Ÿ“Š Game Logic Breakdown

AI Strategy

The AI uses a sophisticated distance-based approach:

When ball is CLOSE (โ‰ค5 pixels):

  • Attempts trick shots by positioning paddle for specific angles
  • 25% chance: Hit top edge (steep up, vy=-2)
  • 25% chance: Hit upper section (diagonal up, vy=-1)
  • 5% chance: Hit center (straight, vy=0) - RARE!
  • 25% chance: Hit lower section (diagonal down, vy=+1)
  • 20% chance: Hit bottom edge (steep down, vy=+2)

When ball is FAR:

  • 85% accuracy defensive tracking
  • 15% chance: Don't move (creates scoring opportunities)

Physics Engine

Ball Movement:

  • Horizontal velocity: ยฑ1
  • Vertical velocity: -2, -1, 0, 1, 2

Collision Detection:

  • Top/bottom walls: Flip vertical velocity
  • Paddles: Reverse horizontal + calculate angle based on hit zone

Paddle Zones (7 zones on a 7-pixel paddle):

Position 0 (top):    vy = -2 (steep up)
Positions 1-2:       vy = -1 (diagonal up)
Positions 3-4:       vy =  0 (straight)
Position 5:          vy =  1 (diagonal down)
Position 6 (bottom): vy =  2 (steep down)

๐ŸŽจ Rendering System

The game uses a pixel-by-pixel rendering approach:

  1. Generate an 80ร—25 grid of coordinates
  2. For each (x, y) position, determine:
    • Is it a border, paddle, ball, center line, or score digit?
    • What character to display?
    • What color (grey/dim or white/bold)?
  3. Assemble into lines with Spectre.Console markup
  4. Output to alternate screen buffer

๐Ÿ”Š Sound System

  • Score Sound: 440 Hz beep + 500ms game pause
  • Paddle Hit: 880 Hz beep (throttled to max 120 Hz)
  • Cross-platform: Windows uses Console.Beep(), others use bell character (\a)

๐Ÿ†š Comparison to Original DuckPong

Feature DuckPong (Python/DuckDB) SQLitePong (C#/SQLite)
SQL Engine DuckDB SQLite
Host Language Python C# (.NET 10)
Terminal Library curses Spectre.Console
Color Support โœ… 4 color pairs โœ… Grey + White Bold + Yellow
Alternate Screen โœ… curses automatic โœ… ANSI escape codes
Cross-platform โœ… Linux/macOS/Windows โœ… Linux/macOS/Windows
Package Management pip NuGet (inline directives)
AI Complexity Advanced (trick shots) Advanced (trick shots)
Font Rendering 3ร—5 digits 3ร—5 digits
Sound Effects โœ… curses.beep() โœ… Console.Beep() + \a

Both implementations share the same core philosophy and ~95% of the SQL logic!

๐Ÿง  Educational Value

This project demonstrates:

  • SQL is Turing-complete - Can implement complex algorithms
  • CTEs for procedural logic - Breaking down problems step-by-step
  • SQL for game engines - Real-time state management
  • Recursive queries - Generating series and coordinates
  • Advanced CASE logic - Multi-level conditional branching
  • Cross-platform .NET - Modern C# features (raw strings, top-level statements)
  • Terminal UI techniques - Alternate screens, ANSI colors, cursor control

๐Ÿ“ Code Structure

app.cs (single file - 600+ lines)
โ”œโ”€โ”€ Header Comment (Attribution)
โ”œโ”€โ”€ Package Directives (#:package)
โ”œโ”€โ”€ Using Statements
โ”œโ”€โ”€ Main()
โ”‚   โ”œโ”€โ”€ Terminal Setup (alternate screen)
โ”‚   โ”œโ”€โ”€ Database Setup (in-memory SQLite)
โ”‚   โ”œโ”€โ”€ setupSql (CREATE tables, INSERT font data)
โ”‚   โ”œโ”€โ”€ tickSql (Game logic - 6-step CTE chain)
โ”‚   โ”œโ”€โ”€ renderSql (Rendering - pixel-by-pixel)
โ”‚   โ””โ”€โ”€ Game Loop
โ”‚       โ”œโ”€โ”€ Input handling
โ”‚       โ”œโ”€โ”€ Tick execution (UPDATE state)
โ”‚       โ”œโ”€โ”€ Render execution (SELECT pixels)
โ”‚       โ”œโ”€โ”€ Display output (Spectre.Console)
โ”‚       โ”œโ”€โ”€ Sound effects
โ”‚       โ””โ”€โ”€ Frame rate limiting
โ””โ”€โ”€ Helper Functions
    โ”œโ”€โ”€ PlayBeep() - Cross-platform sound
    โ”œโ”€โ”€ ExecuteNonQuery() - SQL execution
    โ”œโ”€โ”€ GetABVx() - State retrieval
    โ””โ”€โ”€ ExecuteRenderQuery() - Pixel fetching

๐Ÿ™ Credits

Original DuckPong

SQLitePong (This Port)

  • Author: Jeremy Brown (Tsabo)
  • Adaptation: SQLite + C# + Spectre.Console
  • License: MIT (same as original)
  • Key Changes:
    • Ported from DuckDB to SQLite
    • Ported from Python/curses to C#/Spectre.Console
    • Added alternate screen buffer support
    • Adapted to .NET 10's dotnet run app feature
    • Cross-platform sound handling

๐Ÿ”— Links

๐ŸŽฏ Try It Now!

dotnet run app.cs

Press + to speed up the game, - to slow down, S to enable sound, and ESC to exit.

Enjoy watching SQL play against itself! ๐ŸŽฎโœจ


Built with โค๏ธ for SQL enthusiasts and retro gaming fans

About

Pong in SQL using SQLite and C#

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published