lispjam-autumn-2024/mode-play.fnl

248 lines
9.6 KiB
Fennel

(local state (require :state))
(local mapper (require :mapper))
(local overlay (require :overlay))
(local pi math.pi)
(var count-down true)
; ### Screen Size ###
(var (screen-width screen-height) (love.window.getMode))
(love.mouse.setGrabbed true)
(love.mouse.setRelativeMode true)
; ### Map Information ###
(var (map spawn) (mapper.generate))
; ### Texture Information ###
(var walls [])
(var wall-textures (love.filesystem.getDirectoryItems "assets/textures/walls"))
(var (tex-height tex-width) (values 64 64))
(var skybox [])
(var skybox-textures (love.filesystem.getDirectoryItems "assets/textures/skybox"))
(each [_ v (ipairs wall-textures)]
(local wall {})
(tset wall :t (love.graphics.newImage (.. "assets/textures/walls/" v)))
(tset wall :w (love.graphics.getWidth (. wall :t)))
(tset wall :h (love.graphics.getHeight (. wall :t)))
(table.insert walls wall))
(each [_ v (ipairs skybox-textures)]
(local skyb {})
(tset skyb :t (love.graphics.newImage (.. "assets/textures/skybox/" v)))
(tset skyb :w (love.graphics.getWidth (. skyb :t)))
(tset skyb :h (love.graphics.getHeight (. skyb :t)))
(table.insert skybox skyb))
; ### "Player" variables ###
(var (posx posy) (values (+ (. spawn :x) 0.5) (+ (. spawn :y) 0.5)))
(var (dirx diry) (values -1.0 0.0)) ; Initial direction vector
(var (planex planey) (values 0 0.66)) ; Camera plane
; ### Offset experimentation ###
(var (offst-x offst-y) (values 0 0))
{
:draw (fn love.draw []
(state.setDirX dirx)
(state.setDirY diry)
; Mouse-Look
(love.graphics.translate offst-x offst-y)
; "Skybox"
; Draw a big thing before everything else
; (love.graphics.draw (. skybox 1 :t) -20 -20)
; WALL CASTING
(for [i 0 screen-width]
; Calculate ray position and direction
; Originals, giving a fish-eye lens effect:
; (var camerax (/ (* 2 i) (- screen-width 1)))
; (var (ray-dir-x ray-dir-y) (values (+ dirx (* planex camerax)) (+ diry (* planey camerax))))
(var camerax (- (/ (* 2 i) (- screen-width 1)) 1.0))
(var (ray-dir-x ray-dir-y) (values (+ dirx (* planex camerax)) (+ diry (* planey camerax))))
; Which map square we're in
(var (mapx mapy) (values (math.floor posx) (math.floor posy)))
; Length of ray from current position to next x or y side
(var (side-dist-x side-dist-y) (values 0 0))
; Length of ray from one x or y side to the next x or y side
; (var (delta-dist-x delta-dist-y) (values
; (math.sqrt (+ 1 (/ (* ray-dir-y ray-dir-y) (* ray-dir-x ray-dir-x))))
; (math.sqrt (+ 1 (/ (* ray-dir-x ray-dir-x) (* ray-dir-y ray-dir-y))))))
; (var (delta-dist-x delta-dist-y) (values
; (math.sqrt (+ 1 (* (/ ray-dir-y ray-dir-x) (/ ray-dir-y ray-dir-x))))
; (math.sqrt (+ 1 (* (/ ray-dir-x ray-dir-y) (/ ray-dir-x ray-dir-y))))))
(var (delta-dist-x delta-dist-y) (values (math.abs (/ 1 ray-dir-x)) (math.abs (/ 1 ray-dir-y))))
(var perp-wall-dist 0)
; Direction to step in, x or y
(var (stepx stepy) (values 0 0))
; Side the ray hits, x (0) or y (1)
(var side 0)
; Calculate step and initial side-dist-*
(if (< ray-dir-x 0)
(do
(set stepx -1)
(set side-dist-x (* (- posx mapx) delta-dist-x)))
(do
(set stepx 1)
(set side-dist-x (* (- (+ mapx 1.0) posx) delta-dist-x))))
(if (< ray-dir-y 0)
(do
(set stepy -1)
(set side-dist-y (* (- posy mapy) delta-dist-y)))
(do
(set stepy 1)
(set side-dist-y (* (- (+ mapy 1.0) posy) delta-dist-y))))
; Perform DDA (Digital Differential Analysis)
(var hit false)
(while (not hit)
(if (< side-dist-x side-dist-y)
(do
(set side-dist-x (+ side-dist-x delta-dist-x))
(set mapx (+ mapx stepx))
(set side 0))
(do
(set side-dist-y (+ side-dist-y delta-dist-y))
(set mapy (+ mapy stepy))
(set side 1)))
(if (> (. map mapx mapy) 0) (set hit true)))
; Calculate distance of perpendicular ray, to avoid fisheye effect
(if (= side 0)
(set perp-wall-dist (- side-dist-x delta-dist-x))
(set perp-wall-dist (- side-dist-y delta-dist-y)))
; Calculate height of line to draw on screen
(var line-height (/ screen-height perp-wall-dist))
; Calculate lowest and highest pixel to fill in current stripe
(var draw-start (+ (/ (- line-height) 2) (/ screen-height 2)))
(if (< draw-start 0) (set draw-start 0))
(var draw-end (+ (/ line-height 2) (/ screen-height 2)))
(if (>= draw-end screen-height) (set draw-end (- screen-height 1)))
; Draw textured wall
;; Choose texture
; (var tex-num (. walls (. map mapx mapy)))
(var tex-num (. walls (math.floor (/ (. map mapx mapy) 10))))
;; Calculate exactly where the wall was hit
(var wallx 0)
(if (= side 0)
(set wallx (+ posy (* perp-wall-dist ray-dir-y)))
(set wallx (+ posx (* perp-wall-dist ray-dir-x))))
(set wallx (- wallx (math.floor wallx)))
;; Find the x-coordinate on the texture
(var tex-x (math.floor (* wallx (. tex-num :w))))
(if (and (= side 0) (> ray-dir-x 0)) (set tex-x (- (. tex-num :w) tex-x 1)))
(if (and (= side 1) (< ray-dir-y 0)) (set tex-x (- (. tex-num :w) tex-x 1)))
;; Draw the texture, accounting for "fog"
(var fog-dist (- 1 (/ perp-wall-dist 10)))
(var light-dist (- 0.8 (/ perp-wall-dist 5)))
(love.graphics.setColor light-dist light-dist light-dist fog-dist)
; (love.graphics.draw (. tex-num :t)
; (love.graphics.newQuad tex-x 0 1 (. tex-num :h) (. tex-num :w) (. tex-num :h))
; i draw-start 0 1 (/ line-height (. tex-num :h)))
; (when (= (. map mapx mapy) 3)
(for [q 0 (% (. map mapx mapy) 10)]
(set fog-dist (- fog-dist 0.1))
(set light-dist (- light-dist 0.1))
(love.graphics.setColor light-dist light-dist light-dist fog-dist)
(love.graphics.draw (. tex-num :t)
(love.graphics.newQuad tex-x 0 1 (. tex-num :h) (. tex-num :w) (. tex-num :h))
i (- draw-start (* line-height q)) 0 1 (/ line-height (. tex-num :h)))
)
; )
)
(overlay.overlay offst-x offst-y)
)
:update (fn update [dt]
(var mvspeed (* dt 3.0))
(var rtspeed (* dt 1.0))
(when (love.keyboard.isDown "w")
(when (= 0 (. map (math.floor (+ (* mvspeed dirx) posx)) (math.floor posy)))
(set posx (+ (* mvspeed dirx) posx))
(state.modDis mvspeed))
(when (= 0 (. map (math.floor posx) (math.floor (+ (* mvspeed diry) posy))))
(set posy (+ (* mvspeed diry) posy))
(state.modDis mvspeed))
)
(when (love.keyboard.isDown "s")
(when (= 0 (. map (math.floor (- posx (* mvspeed dirx))) (math.floor posy)))
(set posx (- posx (* mvspeed dirx)))
(state.modDis mvspeed))
(when (= 0 (. map (math.floor posx) (math.floor (- posy (* mvspeed diry)))))
(set posy (- posy (* mvspeed diry)))
(state.modDis mvspeed))
)
(when (love.keyboard.isDown "d")
(when (= 0 (. map (math.floor (+ (* mvspeed planex) posx)) (math.floor posy)))
(set posx (+ (* mvspeed planex) posx))
(state.modDis mvspeed))
(when (= 0 (. map (math.floor posx) (math.floor (+ (* mvspeed planey) posy))))
(set posy (+ (* mvspeed planey) posy))
(state.modDis mvspeed))
)
(when (love.keyboard.isDown "a")
(when (= 0 (. map (math.floor (- posx (* mvspeed planex))) (math.floor posy)))
(set posx (- posx (* mvspeed planex)))
(state.modDis mvspeed))
(when (= 0 (. map (math.floor posx) (math.floor (- posy (* mvspeed planey)))))
(set posy (- posy (* mvspeed planey)))
(state.modDis mvspeed))
)
(when (love.keyboard.isDown "e")
(var old-dirx dirx)
(set dirx (- (* dirx (math.cos (- rtspeed))) (* diry (math.sin (- rtspeed)))))
(set diry (+ (* old-dirx (math.sin (- rtspeed))) (* diry (math.cos (- rtspeed)))))
(var old-planex planex)
(set planex (- (* planex (math.cos (- rtspeed))) (* planey (math.sin (- rtspeed)))))
(set planey (+ (* old-planex (math.sin (- rtspeed))) (* planey (math.cos (- rtspeed)))))
)
(when (love.keyboard.isDown "q")
(var old-dirx dirx)
(set dirx (- (* dirx (math.cos rtspeed)) (* diry (math.sin rtspeed))))
(set diry (+ (* old-dirx (math.sin rtspeed)) (* diry (math.cos rtspeed))))
(var old-planex planex)
(set planex (- (* planex (math.cos rtspeed)) (* planey (math.sin rtspeed))))
(set planey (+ (* old-planex (math.sin rtspeed)) (* planey (math.cos rtspeed))))
)
(if (= 0 (% (+ 1 (math.floor (state.getDis))) 10))
(when count-down
(set count-down false)
(state.modO -1))
(set count-down true))
)
:mousemoved (fn mousemoved [x y dx dy]
(var rtspeed (* dx -0.001))
(var yawspeed (* dy -0.5))
(var old-dirx dirx)
(set dirx (- (* dirx (math.cos rtspeed)) (* diry (math.sin rtspeed))))
(set diry (+ (* old-dirx (math.sin rtspeed)) (* diry (math.cos rtspeed))))
(var old-planex planex)
(set planex (- (* planex (math.cos rtspeed)) (* planey (math.sin rtspeed))))
(set planey (+ (* old-planex (math.sin rtspeed)) (* planey (math.cos rtspeed))))
(set offst-y (+ offst-y yawspeed))
)
:keypressed (fn keypressed [k]
(when (= k "x") (love.event.quit))
)
}