(local overlay (require :overlay)) (local state (require :state)) (local mapper (require :mapper)) (love.graphics.setNewFont 10) (local pi math.pi) (var map (mapper.generate 10 10)) ; This sets the wall texture data (var walls []) (var wall-textures (love.filesystem.getDirectoryItems "textures/walls")) (each [_ v (ipairs wall-textures)] (local wall {}) (tset wall :t (love.graphics.newImage (.. "textures/walls/" v))) (tset wall :w (love.graphics.getWidth (. wall :t))) (tset wall :h (love.graphics.getHeight (. wall :t))) (table.insert walls wall)) ; Map size (var map-height (length map)) (var map-width (length (. map 1))) ; Player position and direction (var player (state.getPlayer)) ; Screen size (var (screen-width screen-height) (love.window.getMode)) ; (var screen-width 1280) ; (var screen-height 720) (var texel-width 64) (var texel-height 64) ; Ray-casting function (fn cast-ray [ray-angle] (local dx (math.cos ray-angle)) (local dy (math.sin ray-angle)) (var rays []) (var (distance tex done hit-pos) (values 0 1 false {})) (while (not done) (var ray-x (+ player.x (* dx distance))) (var ray-y (+ player.y (* dy distance))) (set rays [ray-x ray-y]) ; Check if ray hits a wall (>= 1) on the map (if (or (>= (math.floor ray-x) map-width) (>= (math.floor ray-y) map-height) (<= ray-x 0) (<= ray-y 0) (>= (. map (math.floor ray-y) (math.floor ray-x)) 1)) (do (set done true) (set tex (. map (math.floor ray-y) (math.floor ray-x))) (set hit-pos {:x (- ray-x (math.floor ray-x)) :y (- ray-y (math.floor ray-y))})) ; Increment distance (set distance (+ distance 0.01)))) (values distance hit-pos tex rays)) ; Function to handle player movement (fn move-player [move-speed] (let [new-x (+ player.x (* (math.cos player.d) move-speed)) new-y (+ player.y (* (math.sin player.d) move-speed))] ; Check for collisions with walls (when (= (. map (math.floor new-y) (math.floor new-x)) 0) (state.modO -1) (state.setX new-x) (state.setY new-y)))) ; Draw function for rendering {:draw (fn love.draw [] (love.graphics.clear) ; For each vertical slice of the screen (var (last-x last-y) (values 0 0)) (for [i 0 (- screen-width 1)] ; Calculate angle of ray relative to player direction (local ray-angle (+ player.d (- (* (/ i screen-width) player.f) (/ player.f 2)))) ; Cast the ray to find distance to the nearest wall (local (distance hit-pos tex rays) (values (cast-ray ray-angle))) ; Calculate height of the wall slice (local wall-height (math.floor (/ screen-height distance))) (local start-y (/ (- screen-height wall-height) 2)) (local end-y (/ (+ screen-height wall-height) 2)) ; Draw a textured wall (local wall-texture (. walls tex)) (var texture-x 0) (if (> (/ (- (. rays 1) last-x) (- (. rays 2) last-y)) (/ (- (. rays 2) last-y) (- (. rays 1) last-x))) (set texture-x (math.floor (* (. hit-pos :y) (. wall-texture :w)))) (set texture-x (math.floor (* (. hit-pos :x) (. wall-texture :w))))) (love.graphics.draw (. wall-texture :t) (love.graphics.newQuad texture-x 0 1 (. wall-texture :h) (. wall-texture :w) (. wall-texture :h)) i start-y 0 1 (/ wall-height (. wall-texture :h))) (when (= 0 (% i 200)) (love.graphics.print (.. "r: " ray-angle) i 10) (love.graphics.print (.. "h-x: " (. rays 1)) i 20) (love.graphics.print (.. "h-y: " (. rays 2)) i 30) ) (set (last-x last-y) (values (. rays 1) (. rays 2))) ) (overlay.overlay) (set player (state.getPlayer)) ) :keypressed (fn keypressed [key set-mode] (when (= key "j") (state.setD (- player.d (/ pi 2)))) (when (= key "l") (state.setD (+ player.d (/ pi 2)))) (when (= key "i") (move-player 1)) (when (= key "k") (move-player -1)) (when (= key "x") (love.event.quit)))}