fennel_love2d_experiments/CLAUDE.md
Travis Shears e9b36dc9e1
render colors
Press any key to quit" 10 10))
Press any key to quit" 10 10))
2026-04-05 21:59:23 +02:00

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 .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

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

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:

(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