diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 9b09888..0000000 Binary files a/.DS_Store and /dev/null differ diff --git a/.gitignore b/.gitignore deleted file mode 100644 index e43b0f9..0000000 --- a/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.DS_Store diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index 074c301..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1,169 +0,0 @@ -# CLAUDE.md - -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - -## Project Overview - -This is a LÖVE2D game development playground using Fennel (a Lisp dialect that compiles to Lua). The repository contains multiple game/project experiments: - -- **hello_world**: Basic LÖVE2D + Fennel template with REPL support -- **hello_world_lua**: Basic LÖVE2D in pure Lua (reference implementation) -- **one_line**: A pixel drawing application demonstrating canvas manipulation -- **two_player_cleaning_game**: Two-player game (primary focus for development) - -## Key Architecture - -### Fennel + LÖVE2D Setup - -Fennel is a Lisp-like language that compiles to Lua at runtime. Each project directory shares common bootstrap files via symlinks: - -- **fennel-1.5.3.lua** (root): The Fennel compiler itself -- **fennel_bootstrap.lua** (root): Sets up Fennel module loading and compiles `.fnl` files on-the-fly - -Each project directory contains: -- **main.fnl**: The Fennel source code (user-editable) -- **main.lua** → symlink to `../fennel_bootstrap.lua`: Entry point that Lua/LÖVE2D loads -- **fennel.lua** → symlink to `../fennel-1.5.3.lua`: Fennel compiler reference - -### How It Works - -1. LÖVE2D loads `main.lua` (the bootstrap file) -2. Bootstrap loads the Fennel compiler and sets up a custom module loader -3. Module loader intercepts `require("main.fnl")` and compiles it via Fennel at runtime -4. Compiled Fennel code executes with full LÖVE2D API access - -### LÖVE2D Lifecycle - -Games define lifecycle callbacks (all optional): -- **love.load()**: Called once at startup -- **love.update()**: Called every frame (~60fps by default) -- **love.draw()**: Called every frame after update, render graphics here -- **love.keypressed(key)**: Keyboard input handler -- **love.handlers.stdin(line)**: REPL input for live evaluation (used in hello_world template) - -## Development Workflow - -### Running a Game - -```bash -love ./two_player_cleaning_game -``` - -LÖVE2D must be installed and in your PATH. See [Getting Started](https://love2d.org/wiki/Getting_Started) for installation. - -### Live Coding / REPL - -The hello_world template includes stdin REPL support. While a game is running: -- Type Fennel code at the terminal -- Code is evaluated via `fennel.eval()` and results printed - -To enable in other projects, add this to `love.load()`: - -```fennel -(: (love.thread.newThread "require('love.event') -while 1 do love.event.push('stdin', io.read('*line')) end") :start) - -(fn love.handlers.stdin [line] - (let [(ok val) (pcall fennel.eval line)] - (print (if ok (fennel.view val) val)))) -``` - -## Fennel Language Basics - -### Syntax Patterns - -```fennel -; Variables -(local name "value") -(var counter 0) - -; Functions -(fn my-func [arg1 arg2] - (+ arg1 arg2)) - -; Tables/Objects -(local person { - :name "Alice" - :age 30 - :greet (fn [self] (print (.. self.name " says hello"))) -}) - -; Common control flow -(when condition - (do-something)) - -(if condition - (then-branch) - (else-branch)) - -(match value - "a" (handle-a) - "b" (handle-b)) - -; Iteration -(each [k v (pairs table)] - (print k v)) - -(for [i 1 10] - (print i)) -``` - -### Interop with Lua - -Call Lua functions naturally: - -```fennel -(love.graphics.setColor 1 0 0) ; red -(love.window.getMode) ; returns width, height, flags table -``` - -Access nested Lua objects with colon `:` syntax: - -```fennel -(: canvas-obj :setFilter "nearest" "nearest") ; equivalent to canvas_obj:setFilter(...) -``` - -## Project-Specific Notes - -### two_player_cleaning_game - -Currently uses the hello_world template structure. Development focus: -- Extend main.fnl with game logic (player movement, cleanup mechanics, etc.) -- Reference one_line/main.fnl for canvas/graphics patterns if needed -- Use LÖVE2D physics (love.physics) or collision detection as needed - -### Symlink Pattern - -Do **not** modify symlinked files (main.lua, fennel.lua) — modify main.fnl instead. If adding new modules, create them as separate .fnl files in the project directory. - -## Common Development Tasks - -### Adding a new module/file - -1. Create `my_module.fnl` in the project directory -2. Require it: `(local my-module (require "my_module"))` -3. The bootstrap module loader will auto-compile it - -### Debugging - -- Use `(print (fennel.view value))` to inspect tables and complex values -- stdin REPL (hello_world template) allows live evaluation for quick tests -- LÖVE2D console output is visible in the terminal where you ran `love` - -### Working with Graphics - -LÖVE2D graphics API examples: - -```fennel -(love.graphics.setColor 1 0 0) ; set color to red -(love.graphics.rectangle "fill" x y w h) ; draw filled rectangle -(love.graphics.circle "line" x y radius) ; draw circle outline -(love.graphics.print text x y) ; draw text -(love.graphics.draw drawable x y) ; draw canvas/image -``` - -## References - -- **LÖVE2D API**: https://love2d.org/wiki/Main_Page -- **Fennel Language**: https://fennel-lang.org/ -- **Fennel Plugin**: The compiler is shipped in this repo; no external install needed beyond LÖVE2D diff --git a/two_player_cleaning_game/.DS_Store b/two_player_cleaning_game/.DS_Store deleted file mode 100644 index ee089d4..0000000 Binary files a/two_player_cleaning_game/.DS_Store and /dev/null differ diff --git a/two_player_cleaning_game/assets/level_001.aseprite b/two_player_cleaning_game/assets/level_001.aseprite deleted file mode 100644 index 14f5fb1..0000000 Binary files a/two_player_cleaning_game/assets/level_001.aseprite and /dev/null differ diff --git a/two_player_cleaning_game/assets/level_001.png b/two_player_cleaning_game/assets/level_001.png deleted file mode 100644 index 6e5278a..0000000 Binary files a/two_player_cleaning_game/assets/level_001.png and /dev/null differ diff --git a/two_player_cleaning_game/assets/level_002.aseprite b/two_player_cleaning_game/assets/level_002.aseprite deleted file mode 100644 index 96f2170..0000000 Binary files a/two_player_cleaning_game/assets/level_002.aseprite and /dev/null differ diff --git a/two_player_cleaning_game/assets/level_002.png b/two_player_cleaning_game/assets/level_002.png deleted file mode 100644 index c5ae829..0000000 Binary files a/two_player_cleaning_game/assets/level_002.png and /dev/null differ diff --git a/two_player_cleaning_game/assets/player_001.aseprite b/two_player_cleaning_game/assets/player_001.aseprite deleted file mode 100644 index 80604a7..0000000 Binary files a/two_player_cleaning_game/assets/player_001.aseprite and /dev/null differ diff --git a/two_player_cleaning_game/assets/player_001.png b/two_player_cleaning_game/assets/player_001.png deleted file mode 100644 index fc97a25..0000000 Binary files a/two_player_cleaning_game/assets/player_001.png and /dev/null differ diff --git a/two_player_cleaning_game/main.fnl b/two_player_cleaning_game/main.fnl index 1b7e742..4172050 100644 --- a/two_player_cleaning_game/main.fnl +++ b/two_player_cleaning_game/main.fnl @@ -1,12 +1,4 @@ -(var player-sprite nil) ; 20x20 pixels -(local game-state { - :player-pos [0 0] -}) - (fn love.load [] - (love.window.setMode 600 640) - - (set player-sprite (love.graphics.newImage "assets/player_001.png")) ;; start a thread listening on stdin (: (love.thread.newThread "require('love.event') while 1 do love.event.push('stdin', io.read('*line')) end") :start)) @@ -16,34 +8,8 @@ while 1 do love.event.push('stdin', io.read('*line')) end") :start)) (let [(ok val) (pcall fennel.eval line)] (print (if ok (fennel.view val) val)))) - -;; drawing -(lambda color [full-r full-g full-b] - (let [(r g b) (love.math.colorFromBytes full-r full-g full-b)] - [r g b] -)) - -(local off-white (color 237 230 200)) -(local black [0 0 0]) - -(fn draw-game-outline [] - (love.graphics.setColor (unpack black)) - (love.graphics.rectangle "line" 50 50 500 500)) - -(fn draw-player [] - (love.graphics.setColor 1 1 1) ; reset color to white (no tinting) - (love.graphics.draw player-sprite 50 50 0 1.25 1.25)) - (fn love.draw [] - ;; clear the screen and set bg to off white - (love.graphics.clear) - (love.graphics.setColor (unpack off-white)) - (love.graphics.rectangle "fill" 0 0 600 640) - - (draw-player) - (draw-game-outline) -) - ; (love.graphics.print "Hello from Fennel!\nPress any key to quit" 10 10)) + (love.graphics.print "Hello from Fennel!\nPress any key to quit" 10 10)) (fn love.keypressed [key] (love.event.quit))