From f12058bb6f1fa5c23e1b67471b22f2638ff9997a Mon Sep 17 00:00:00 2001 From: Bill Niblock Date: Thu, 14 Aug 2025 11:40:42 -0400 Subject: [PATCH] Begin work on floor casting --- assets/textures/floors/1.png | Bin 0 -> 1690 bytes mode-play.fnl | 284 +++++++++++++++++++++-------------- 2 files changed, 172 insertions(+), 112 deletions(-) create mode 100644 assets/textures/floors/1.png diff --git a/assets/textures/floors/1.png b/assets/textures/floors/1.png new file mode 100644 index 0000000000000000000000000000000000000000..6c4511e0283dd3073d23ff45da1c59ac3b5eda52 GIT binary patch literal 1690 zcmV;L24(q)P)E>&-}iBSeGMT5j4_C!2mla&@jMSn zk{}2I06?0io#M+)z(NS#Ms$zB+q6{ePg=6&?CcDVz#u&J+%g?&Rm%#dP`T6rFwARS73`J4!ZxuX_V;Ezg zwJvEPiXto)3*>o@JkK{yg!+>SW=WFp|2)r;rYVNQA)+WM zZB>$!lN0_=V>yn4EX#0rcLxBNOeUS;t1Qb(TTg2Z&-0L`X>CA~IF6yUF5O!!7Nu*) zaj;x2`I@w7Ym+qHCBB+Yr~H6ciMZACJpB0a1Gl%g0D$Rq3MnPRFoaTy+rN49h6f~} z6FQ0_Twh;j)Zfhs4{!9w?a--nbEp6AuTNQi^&=Ryd$t_$Dy zVT@^f`7ZHQbr3ovXj=wBfHX}ZgkW%BePUNBs!2!_S(fn$T;=vI@l})IP`&3kPKmbY z*)}e&j+bQ_lzLe6qA2)9JHxlPiV%V)v|KJ>jA2vK2CizYNunr%loG4e3dR^dkg_a8 zmSxEEoO!-Wd_|L>EoF?suV23a0E5ARJ1C_#0u%Qxm&-=$O(}&qj`vo6Q)=o{UX5B#XrYq~15tuVN(DrbEhhOX+%>KmRB3YYWiS@o)C$_r+Jw z-JjnVpL;x4e|}$lMc~iXpWhdsZOrHD&+m(`!Z0jxFaX@&-}86%{{4G=`SJw-FdB`x zjcuO~heMv2t;wP&@ZrM;eEaqdz=Pj@eturkPM7$KTul2gA{*S+isyN3Xpo$qo^oG% zi)yWLdwUBhC6rPnudmnZVYOOeI2@K1p(}hv0{{7?#8*|W?f3ggk_4{n@;0Q&*a3+)p~>4c)$jK)7z|4HXc9$Hbc!#f zlx%L&cXf7l1|bA`y&j69cr>tWZE3BM=Q)o9phinlO8f=*4<{(uI)m7`n2#Dy1yu8U|!rOc{n{9llF7Qi1(IiRW zc^>BTc`blw^LA7EnO3|giW;ZeV^jMkU!V(oMaD)LhU`+(sk<$|E`(rzd@`Bro!{>Q z{}>ObHaf-w8af{10XW73N)tK81CH^4wY->k!0XqqTjTE2=@j3;e+K}3{P>Y4@mQYq zeIK*g3|ec9$729>L#9i7`Bcj6H9h|?>-Y|h zFJC&(Z^P%Mx9Ng-)^Qx>OJJ=D+o~d-&GVeo*g%D6rEGLgs?rsH%@S8 zu@}!D3SV7ZTmab4vrI15|`HPDSuGgph zyq%i|z_iqqo4>ia!OhJLfOUR;Fc{P{(-cZ0wSoKR-XmXf%3qZNQ=NmCdu8a`W4Of#%%&U@(AEiZuf4RvU0Ad=81V z<>sqpDQ&>ErDf;l=_KE^HsH|srGUu)tu{bPS+5TeqB%DYpf$fwKux*%G)-BnRe!u~ ktUrm*eDZ&+4FG_D0IB;RJLXcjl>h($07*qoM6N<$f)pb?YXATM literal 0 HcmV?d00001 diff --git a/mode-play.fnl b/mode-play.fnl index 5390787..218b9b1 100644 --- a/mode-play.fnl +++ b/mode-play.fnl @@ -16,6 +16,10 @@ (var wall-textures (love.filesystem.getDirectoryItems "assets/textures/walls")) (var (tex-height tex-width) (values 64 64)) +(var floors []) +(var floor-textures (love.filesystem.getDirectoryItems "assets/textures/floors")) +(var (tex-height tex-width) (values 64 64)) + (var skybox []) (var skybox-textures (love.filesystem.getDirectoryItems "assets/textures/skybox")) @@ -26,6 +30,13 @@ (tset wall :h (love.graphics.getHeight (. wall :t))) (table.insert walls wall)) +(each [_ v (ipairs floor-textures)] + (local floor {}) + (tset floor :t (love.graphics.newImage (.. "assets/textures/floors/" v))) + (tset floor :w (love.graphics.getWidth (. floor :t))) + (tset floor :h (love.graphics.getHeight (. floor :t))) + (table.insert floors floor)) + (each [_ v (ipairs skybox-textures)] (local skyb {}) (tset skyb :t (love.graphics.newImage (.. "assets/textures/skybox/" v))) @@ -41,6 +52,164 @@ ; ### Offset experimentation ### (var (offst-x offst-y) (values 0 0)) +(fn floor-casting [wall-dists] + (for [y (math.floor (/ screen-height 2)) (- screen-height 1)] + + ; Distance to floor row + (var floor-dist (/ screen-height (- (* 2 y) screen-height))) + + ; Calculate step distances for row + (var (step-x step-y) (values (/ (* floor-dist planex) screen-width) + (/ (* floor-dist planey) screen-width))) + + ; Starting position for leftmost pixel of this row + (var (floor-x floor-y) (values + (+ posx (* dirx floor-dist) (* step-x (/ screen-width -2))) + (+ posy (* diry floor-dist) (* step-y (/ screen-width -2))))) + + ; Draw each pixel across this row + (for [x 0 screen-width] + ; Only draw if actually visible + (when (< floor-dist (. wall-dists x)) + + ; Get pixel of texture to draw + ; (set tex-x (- (. tex-num :w) tex-x 1)) + (var (tex-x tex-y) (values + (math.floor (- floor-x (* (. floors 1 :w) (math.floor floor-x)))) + (math.floor (- floor-y (* (. floors 1 :h) (math.floor floor-y)))))) + + ; Set lighting/fog + ; (var fog-dist (- 1 (/ (. wall-dists x) 10))) + ; (var light-dist (- 0.8 (/ (. wall-dists x) 5))) + ; (love.graphics.setColor light-dist light-dist light-dist fog-dist) + + ; Draw texture-pixel to world coordinate + (var tex-num (. floors 1)) + (love.graphics.draw (. tex-num :t) + (love.graphics.newQuad tex-x tex-y 1 1 (. tex-num :w) (. tex-num :h)) + x y)) + + ; Step forward a pixel + (set (floor-x floor-y) (values + (+ floor-x step-x) (+ floor-y step-y))))) +) + +(fn sky-casting []) + +(fn wall-casting [] + (var wall-dist []) + ; 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))) + ) + (tset wall-dist i perp-wall-dist) + ; ) + ) + wall-dist +) + { :draw (fn love.draw [] (state.setDirX dirx) @@ -48,118 +217,9 @@ ; 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))) - ) - ; ) - ) + ; (sky-casting) + (var wall-dists (wall-casting)) + (floor-casting wall-dists) (overlay.overlay offst-x offst-y) )