4.9 KiB
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
.fnlfiles 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
- LÖVE2D loads
main.lua(the bootstrap file) - Bootstrap loads the Fennel compiler and sets up a custom module loader
- Module loader intercepts
require("main.fnl")and compiles it via Fennel at runtime - 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
love ./two_player_cleaning_game
LÖVE2D must be installed and in your PATH. See 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():
(: (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
; 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:
(love.graphics.setColor 1 0 0) ; red
(love.window.getMode) ; returns width, height, flags table
Access nested Lua objects with colon : syntax:
(: 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
- Create
my_module.fnlin the project directory - Require it:
(local my-module (require "my_module")) - 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:
(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