diff --git a/game/src/entities/player.fnl b/game/src/entities/player.fnl index b6fdb16..bda7495 100644 --- a/game/src/entities/player.fnl +++ b/game/src/entities/player.fnl @@ -10,6 +10,9 @@ (lambda bump-filter [item other] (if (= other.behavior "block") :slide :cross)) +(lambda vision-bump-filter [other] + (= other.behavior "block")) + (lambda angle-to-direction [angle] "Convert angle (radians) to compass direction keyword" (local tau (* 2 math.pi)) @@ -28,6 +31,7 @@ (local height 15) (local player { :x 50 :y 50 :w 25 :h 25 :speed 80 :battery 100 :rot 0 + :vision-pts [] :hitbox [50 50 width height] :init-move false ; nudge the player at start of game to trigger starting collisions }) @@ -38,6 +42,52 @@ (when col.other.on-hit (col.other:on-hit)) (beholder.trigger "PLAYER.HIT" col.other))) +(lambda origin-pt [x y] + (values (+ x (/ width 2)) (+ y (/ height 2)))) + + +(lambda player.cal-vision-points [self] + (let [pts [] + (ox oy) (origin-pt self.x self.y) + add-pt (lambda [x y] + (let [(rx ry) (utils.rotate-pt x y ox oy self.rot)] + (table.insert pts [rx ry]))) + ] + (for [i 1 5] + (add-pt (- ox (* i 5) 50) (- oy (- 50 (* i 5) )))) + (for [i 1 10] + (add-pt (- ox (* i 5)) (- oy 50))) + (add-pt ox (- oy 50)) ; middle pt + (for [i 1 10] + (add-pt (+ ox (* i 5)) (- oy 50))) + (for [i 1 5] + (add-pt (+ ox (* i 5) 50) (- oy (- 50 (* i 5) )))) + pts + ) +) + +(lambda player.cal-vision-poly [self] + (let [pts (self:cal-vision-points) + (ox oy) (origin-pt self.x self.y) + poly-pts [ox oy] + ] + (each [_ pt (ipairs pts)] + (let [ + items (bump-world:querySegmentWithCoords ox oy (. pt 1) (. pt 2) vision-bump-filter) + first-item (. items 1)] + (if first-item + (do + (table.insert poly-pts (. first-item :x1)) + (table.insert poly-pts (. first-item :y1))) + (do + (table.insert poly-pts (. pt 1)) + (table.insert poly-pts (. pt 2)))))) + + (set self.vision-pts poly-pts) + ; (utils.debug-print {: poly-pts}) + )) + + (fn player.update [self dt] (when (= self.init-move false) (set self.init-move true) @@ -62,7 +112,8 @@ (x y cols len) (bump-world:move self new-x new-y bump-filter)] (handle-collisions cols) (set self.x x) - (set self.y y)) + (set self.y y) + (self:cal-vision-poly)) (if (> self.battery 0) (set self.battery (- self.battery (* dt 2)))))) (beholder.trigger "PLAYER.POS" self.x self.y) @@ -99,25 +150,33 @@ (- self.x 3) (- self.y 7))) -(lambda draw-vision-debug [self] +(lambda player.draw-vision-debug [self] "draw debug lines and points for player vision" (color.set-color :black) - (love.graphics.push) - (let [ox (+ self.x (/ width 2)) - oy (+ self.y (/ height 2)) - steps 20 - vision-step (/ (/ math.pi 2) steps)] ; 90 deg / 20 - (love.graphics.translate ox oy) - (love.graphics.rotate (- self.rot (/ (* steps vision-step) 2))) - (for [i 1 steps] - (love.graphics.rotate vision-step) - (love.graphics.line 0 0 50 0)) - (love.graphics.pop))) + ; (love.graphics.setPointSize 2) + ; (utils.debug-print {:pts self.vision-pts :player {:x self.x :y self.y}}) + ; (each [_ pt (pairs self.vision-pts)] + ; (love.graphics.points (unpack pt))) + (when (> (length self.vision-pts) 2) (love.graphics.polygon "line" self.vision-pts)) + ; (love.graphics.push) + ; (let [ox (+ self.x (/ width 2)) + ; oy (+ self.y (/ height 2)) + ; steps 20 + ; vision-step (/ (/ math.pi 2) steps)] ; 90 deg / 20 + ; (love.graphics.translate ox oy) + ; (love.graphics.rotate (- self.rot (/ (* steps vision-step) 2))) + ; (for [i 1 steps] + ; (love.graphics.rotate vision-step) + ; (love.graphics.line 0 0 50 0)) + ; (love.graphics.pop))) +) + +; local items, len = world:querySegment(x1,y1,x2,y2,filter) (fn player.draw-debug [self] "draw player hitbox and direction line" (color.set-color :black) - (draw-vision-debug self) + (self:draw-vision-debug) (love.graphics.rectangle "line" self.x self.y width height) ; (love.graphics.rectangle "line" self.x self.y 1 1) (love.graphics.push) diff --git a/game/src/utils.fnl b/game/src/utils.fnl index b116641..949c3e1 100644 --- a/game/src/utils.fnl +++ b/game/src/utils.fnl @@ -1,6 +1,49 @@ +; Radian constants at 30-degree increments +(local deg-0 0) +(local deg-30 (/ math.pi 6)) +(local deg-60 (/ math.pi 3)) +(local deg-90 (/ math.pi 2)) +(local deg-120 (* 2 (/ math.pi 3))) +(local deg-150 (* 5 (/ math.pi 6))) +(local deg-180 math.pi) +(local deg-210 (* 7 (/ math.pi 6))) +(local deg-240 (* 4 (/ math.pi 3))) +(local deg-270 (* 3 (/ math.pi 2))) +(local deg-300 (* 5 (/ math.pi 3))) +(local deg-330 (* 11 (/ math.pi 6))) +(local deg-360 (* 2 math.pi)) + + (lambda debug-print [obj] (print (fennel.view obj))) + +(lambda rotate-pt [x y ox oy theta] + (let [ + fix-theta (+ theta deg-90) + cos-theta (math.cos fix-theta) + sin-theta (math.sin fix-theta) + translated-x (- x ox) + translated-y (- y oy) + rotated-x (- (* translated-x cos-theta) (* translated-y sin-theta)) + rotated-y (+ (* translated-x sin-theta) (* translated-y cos-theta))] + (values (+ ox rotated-x) (+ oy rotated-y)))) + + { : debug-print + : rotate-pt + : deg-0 + : deg-30 + : deg-60 + : deg-90 + : deg-120 + : deg-150 + : deg-180 + : deg-210 + : deg-240 + : deg-270 + : deg-300 + : deg-330 + : deg-360 }