(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)) ) }