Compare commits
No commits in common. "bd12a4d50469119cc5fbb1f99309979d050ac9be" and "31fb931c4ae71c4a463cbe189ac9a00619393cd7" have entirely different histories.
bd12a4d504
...
31fb931c4a
6 changed files with 41 additions and 1957 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -6,8 +6,6 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|||
|
||||
This is a two-player cooperative cleaning game built with LÖVE2D using Fennel (a Lisp dialect that compiles to Lua).
|
||||
|
||||
Fennel docs are available locally at `.claude/API_DOCs/fennel.md`
|
||||
|
||||
## Key Architecture
|
||||
|
||||
### Fennel + LÖVE2D Setup
|
||||
|
|
@ -43,7 +41,7 @@ Games define lifecycle callbacks (all optional):
|
|||
### Running the Game
|
||||
|
||||
```bash
|
||||
love ./game
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -30,10 +30,10 @@
|
|||
(local width 19)
|
||||
(local height 15)
|
||||
(local player {
|
||||
:x 50 :y 50 :speed 80 :battery 100 :rot 0
|
||||
:x 50 :y 50 :w 25 :h 25 :speed 80 :battery 100 :rot 0
|
||||
:vision-pts []
|
||||
:hitbox [50 50 width height]
|
||||
:ever-moved false ; useful for inital update
|
||||
:init-move false ; nudge the player at start of game to trigger starting collisions
|
||||
})
|
||||
|
||||
|
||||
|
|
@ -42,13 +42,13 @@
|
|||
(when col.other.on-hit (col.other:on-hit))
|
||||
(beholder.trigger "PLAYER.HIT" col.other)))
|
||||
|
||||
; TODO: make this internal
|
||||
(lambda player.origin-pt [self]
|
||||
(values (+ self.x (/ width 2)) (+ self.y (/ height 2))))
|
||||
(lambda origin-pt [x y]
|
||||
(values (+ x (/ width 2)) (+ y (/ height 2))))
|
||||
|
||||
|
||||
(lambda player.cal-vision-points [self]
|
||||
(let [
|
||||
(ox oy) (self:origin-pt)
|
||||
(ox oy) (origin-pt self.x self.y)
|
||||
pts []]
|
||||
(lambda add-pt [x y] (table.insert pts [x y]))
|
||||
(for [i 1 5]
|
||||
|
|
@ -72,7 +72,7 @@
|
|||
|
||||
(lambda player.cal-vision-poly [self]
|
||||
(let [pts (self:cal-vision-points)
|
||||
(ox oy) (self:origin-pt)
|
||||
(ox oy) (origin-pt self.x self.y)
|
||||
poly-pts [ox oy]
|
||||
]
|
||||
(each [_ pt (ipairs pts)]
|
||||
|
|
@ -91,6 +91,10 @@
|
|||
|
||||
|
||||
(fn player.update [self dt]
|
||||
(when (= self.init-move false)
|
||||
(set self.init-move true)
|
||||
(let [(x y cols len) (bump-world:move self self.x self.y bump-filter)]
|
||||
(handle-collisions cols)))
|
||||
(let [
|
||||
d-key (love.keyboard.isDown :d)
|
||||
a-key (love.keyboard.isDown :a)
|
||||
|
|
@ -102,10 +106,7 @@
|
|||
{:d-key false :a-key false :e-key true :q-key false} (set self.rot (- self.rot (* dt 2)))
|
||||
{:d-key false :a-key false :e-key false :q-key true} (set self.rot (+ self.rot (* dt 2)))
|
||||
)
|
||||
(when (or
|
||||
(= self.ever-moved false)
|
||||
(and (> self.battery 0) (or d-key a-key e-key q-key)))
|
||||
(set self.ever-moved true)
|
||||
(when (and (> self.battery 0) (or d-key a-key e-key q-key))
|
||||
(let [
|
||||
dir-fn (if (or d-key a-key) #(+ $1 $2) #(- $1 $2))
|
||||
new-x (dir-fn self.x (* self.speed dt (math.cos self.rot)))
|
||||
|
|
@ -115,10 +116,10 @@
|
|||
(set self.x x)
|
||||
(set self.y y)
|
||||
(self:cal-vision-poly))
|
||||
(when (> self.battery 0) (set self.battery (- self.battery (* dt 2))))
|
||||
(beholder.trigger "PLAYER.MOVED" self)))
|
||||
; (beholder.trigger "PLAYER.POS" self.x self.y)
|
||||
; (beholder.trigger "PLAYER.VISION" self.vision-pts)
|
||||
(if (> self.battery 0)
|
||||
(set self.battery (- self.battery (* dt 2))))))
|
||||
(beholder.trigger "PLAYER.POS" self.x self.y)
|
||||
(beholder.trigger "PLAYER.VISION" self.vision-pts)
|
||||
(beholder.trigger "PLAYER.BATTERY" self.battery))
|
||||
|
||||
(fn player.load [self]
|
||||
|
|
|
|||
|
|
@ -11,11 +11,10 @@
|
|||
|
||||
(fn camera.load [self]
|
||||
(let [screen self.pool.data.screen]
|
||||
(beholder.observe "PLAYER.MOVED" (lambda [player]
|
||||
(let [(ox oy) (player:origin-pt)]
|
||||
;; Update camera to follow player (keep player centered on screen)
|
||||
(set self.x (- ox (/ screen.canvas-w 2)))
|
||||
(set self.y (- oy (/ screen.canvas-h 2))))))))
|
||||
(beholder.observe "PLAYER.POS" (lambda [x y]
|
||||
;; Update camera to follow player (keep player centered on screen)
|
||||
(set self.x (- x (/ screen.canvas-w 2)))
|
||||
(set self.y (- y (/ screen.canvas-h 2)))))))
|
||||
|
||||
(fn camera.draw89 [self]
|
||||
(love.graphics.origin)) ; reset camera translation
|
||||
|
|
|
|||
|
|
@ -8,15 +8,19 @@
|
|||
{
|
||||
:player-vision-pts []
|
||||
:player-pos [0 0]
|
||||
:player-quad nil
|
||||
:font nil
|
||||
:canvas nil })
|
||||
|
||||
(lambda fow.load [self]
|
||||
(let [(w h) (assets.player-sprite:getDimensions)]
|
||||
(set self.player-quad (love.graphics.newQuad 0 0 25 25 w h)))
|
||||
(set self.font (love.graphics.newFont 10))
|
||||
(set self.canvas (love.graphics.newCanvas 1000 1000))
|
||||
(beholder.observe "PLAYER.MOVED" (lambda [player]
|
||||
(set self.player-pos [player.x player.y])
|
||||
(set self.player-vision-pts player.vision-pts)))
|
||||
|
||||
(beholder.observe "PLAYER.VISION" (lambda [pts]
|
||||
(set self.player-vision-pts pts)))
|
||||
(beholder.observe "PLAYER.POS" (lambda [x y]
|
||||
(set self.player-pos [x y])))
|
||||
(let [previousCanvas (love.graphics.getCanvas)]
|
||||
(love.graphics.setCanvas self.canvas)
|
||||
(color.set-color :dark-purple)
|
||||
|
|
@ -35,6 +39,7 @@
|
|||
(love.graphics.rectangle "fill" 0 0 1000 1000)
|
||||
(love.graphics.setBlendMode "replace")
|
||||
(love.graphics.setColor 0 0 0 0) ; transparent
|
||||
; draw player quad to uncover the player
|
||||
(love.graphics.push)
|
||||
(love.graphics.translate (- x 3) (- y 7))
|
||||
(love.graphics.polygon "fill" 3 11 3 17 7 21 17 21 21 17 21 11 17 7 7 7)
|
||||
|
|
|
|||
|
|
@ -5,29 +5,32 @@
|
|||
(local assets (require "src/assets.fnl"))
|
||||
|
||||
(local radar
|
||||
{ :x 0
|
||||
:y 0
|
||||
{ :player-pos [0 0]
|
||||
:rot 0
|
||||
:speed 4 })
|
||||
|
||||
(lambda radar.load [self]
|
||||
(beholder.observe "PLAYER.MOVED" (lambda [player]
|
||||
(let [(x y) (player:origin-pt)]
|
||||
(set self.x x)
|
||||
(set self.y y)))))
|
||||
(beholder.observe "PLAYER.POS" (lambda [x y]
|
||||
(set self.player-pos [x y]))))
|
||||
|
||||
(lambda radar.update [self dt]
|
||||
(set self.rot (+ self.rot (* (/ dt self.speed)))))
|
||||
|
||||
(lambda radar.draw81 [self]
|
||||
(let [
|
||||
w 19 h 15
|
||||
[x y] self.player-pos
|
||||
ox (+ x (/ w 2))
|
||||
oy (+ y (/ h 2))
|
||||
]
|
||||
(color.set-color :dark-pink)
|
||||
(love.graphics.push)
|
||||
(love.graphics.translate self.x self.y)
|
||||
(love.graphics.translate ox oy)
|
||||
(love.graphics.rotate self.rot)
|
||||
(love.graphics.setPointSize 2)
|
||||
(love.graphics.points 0 0)
|
||||
(love.graphics.circle "line" 0 0 150)
|
||||
(love.graphics.line 0 0 0 150)
|
||||
(love.graphics.pop))
|
||||
(love.graphics.pop)))
|
||||
|
||||
radar
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue