206 lines
7.8 KiB
Fennel
206 lines
7.8 KiB
Fennel
(local state (require :state))
|
|
(local mapper (require :mapper))
|
|
(local overlay (require :overlay))
|
|
(local pi math.pi)
|
|
; ### Screen Size ###
|
|
(var (screen-width screen-height) (love.window.getMode))
|
|
|
|
; ### Map Information ###
|
|
(var map (mapper.generate 15 15))
|
|
; (var map [[1 1 1 1 1 1 1 1 1 1 1 ]
|
|
; [2 0 0 0 0 0 0 0 0 0 4 ]
|
|
; [2 0 0 0 0 0 0 0 0 0 4 ]
|
|
; [2 0 0 0 0 0 0 0 0 0 4 ]
|
|
; [2 0 0 0 0 0 0 0 0 0 4 ]
|
|
; [2 0 0 0 0 0 0 0 0 0 4 ]
|
|
; [2 0 0 0 0 0 0 0 3 0 4 ]
|
|
; [2 0 0 0 0 0 0 3 3 0 4 ]
|
|
; [2 0 0 0 0 0 0 0 0 0 4 ]
|
|
; [1 1 1 1 1 1 1 1 1 1 1 ]])
|
|
|
|
; ### Texture Information ###
|
|
(var walls [])
|
|
(var wall-textures (love.filesystem.getDirectoryItems "textures/walls"))
|
|
(var (tex-height tex-width) (values 64 64))
|
|
|
|
(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))
|
|
|
|
; ### "Player" variables ###
|
|
(var (posx posy) (values 4.0 4.0)) ; Initial map position
|
|
(var (dirx diry) (values -1.0 0.0)) ; Initial direction vector
|
|
(var (planex planey) (values 0 0.80)) ; Camera plane
|
|
|
|
{
|
|
:draw (fn love.draw []
|
|
(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)))
|
|
(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.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 wall slice
|
|
; (var color [1 1 1 1])
|
|
; (case (. map mapx mapy)
|
|
; 1 (set color [1 1 1 1])
|
|
; 2 (set color [1 0 0 1])
|
|
; 3 (set color [0 1 0 1])
|
|
; 4 (set color [0 0 1 1])
|
|
; )
|
|
|
|
; (when (= side 1)
|
|
; (tset color 1 (/ (. color 1) 2))
|
|
; (tset color 2 (/ (. color 2) 2))
|
|
; (tset color 3 (/ (. color 3) 2)))
|
|
|
|
; (love.graphics.setColor color)
|
|
; (love.graphics.line i draw-start i draw-end)
|
|
; (love.graphics.setColor 1 1 1)
|
|
|
|
; Draw textured wall
|
|
;; Choose texture
|
|
(var tex-num (. walls (. map mapx mapy)))
|
|
;; 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
|
|
(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)))
|
|
)
|
|
|
|
(overlay.overlay)
|
|
)
|
|
|
|
:update (fn update [dt]
|
|
(var mvspeed (* dt 3.0))
|
|
(var rtspeed (* dt 1.0))
|
|
|
|
(when (love.keyboard.isDown "up")
|
|
(when (= 0 (. map (math.floor (+ (* mvspeed dirx) posx)) (math.floor posy)))
|
|
(set posx (+ (* mvspeed dirx) posx)))
|
|
(when (= 0 (. map (math.floor posx) (math.floor (+ (* mvspeed diry) posy))))
|
|
(set posy (+ (* mvspeed diry) posy)))
|
|
)
|
|
|
|
(when (love.keyboard.isDown "down")
|
|
(when (= 0 (. map (math.floor (+ (* mvspeed dirx) posx)) (math.floor posy)))
|
|
(set posx (- posx (* mvspeed dirx))))
|
|
(when (= 0 (. map (math.floor posx) (math.floor (+ (* mvspeed diry) posy))))
|
|
(set posy (- posy (* mvspeed diry))))
|
|
)
|
|
|
|
(when (love.keyboard.isDown "right")
|
|
(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 "left")
|
|
(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))))
|
|
)
|
|
)
|
|
|
|
:keypressed (fn keypressed [k]
|
|
(when (= k "x") (love.event.quit))
|
|
)
|
|
}
|
|
|
|
; (fn move-player [x]
|
|
; (let [new-x (+ posx (* (math.cos dirx)) x) new-y (+ posy (* (math.sin diry)) x)]
|
|
; (when (= (. map (math.floor new-y) (math.floor new-x)) 0)
|
|
; (set posx new-x) (set posy new-y))))
|
|
|
|
; (fn rotate-player [d]
|
|
; (local rotation-speed 1)
|
|
; (var old-dirx dirx)
|
|
; (set dirx (- (* dirx (math.cos (* d rotation-speed))) (* diry (math.sin (* d rotation-speed)))))
|
|
; (set diry (+ (* old-dirx (math.sin (* d rotation-speed))) (* diry (math.cos (* d rotation-speed)))))
|
|
; (var old-planex planex)
|
|
; (set planex (- (* planex (math.cos (* d rotation-speed))) (* planey (math.sin (* d rotation-speed)))))
|
|
; (set planey (+ (* old-planex (math.sin (* d rotation-speed))) (* planey (math.cos (* d rotation-speed))))))
|