(local pxl8 (require :pxl8)) (local DOOR_HEIGHT 96) (local DOOR_WIDTH 48) (local DOOR_X 892) (local DOOR_Z 416) (local FIREBALL_COLOR 218) (var door-mesh nil) (var door-tex nil) (var fireball-mesh nil) (fn create-door-mesh [] (let [verts [] indices [] hw (/ DOOR_WIDTH 2) y0 0 y1 DOOR_HEIGHT x DOOR_X] (table.insert verts {:x x :y y0 :z (- DOOR_Z hw) :u 0 :v 1 :nx -1 :ny 0 :nz 0 :color 80 :light 200}) (table.insert verts {:x x :y y0 :z (+ DOOR_Z hw) :u 1 :v 1 :nx -1 :ny 0 :nz 0 :color 80 :light 200}) (table.insert verts {:x x :y y1 :z (+ DOOR_Z hw) :u 1 :v 0 :nx -1 :ny 0 :nz 0 :color 80 :light 200}) (table.insert verts {:x x :y y1 :z (- DOOR_Z hw) :u 0 :v 0 :nx -1 :ny 0 :nz 0 :color 80 :light 200}) (table.insert indices 0) (table.insert indices 1) (table.insert indices 2) (table.insert indices 0) (table.insert indices 2) (table.insert indices 3) (set door-mesh (pxl8.create_mesh verts indices)))) (fn create-fireball-mesh [] (let [verts [] indices [] radius 5 rings 4 segments 6 core-color (+ FIREBALL_COLOR 6) spike-color (- FIREBALL_COLOR 1)] (table.insert verts {:x 0 :y radius :z 0 :nx 0 :ny 1 :nz 0 :color core-color :light 255}) (for [ring 1 (- rings 1)] (let [phi (* (/ ring rings) math.pi) sin-phi (math.sin phi) cos-phi (math.cos phi) y (* radius cos-phi) ring-radius (* radius sin-phi)] (for [seg 0 (- segments 1)] (let [theta (* (/ seg segments) math.pi 2) x (* ring-radius (math.cos theta)) z (* ring-radius (math.sin theta)) nx (* sin-phi (math.cos theta)) nz (* sin-phi (math.sin theta))] (table.insert verts {:x x :y y :z z :nx nx :ny cos-phi :nz nz :color core-color :light 255}))))) (let [bottom-idx (length verts)] (table.insert verts {:x 0 :y (- radius) :z 0 :nx 0 :ny -1 :nz 0 :color core-color :light 255}) (for [seg 0 (- segments 1)] (let [next-seg (% (+ seg 1) segments)] (table.insert indices 0) (table.insert indices (+ 1 next-seg)) (table.insert indices (+ 1 seg)))) (for [ring 0 (- rings 3)] (for [seg 0 (- segments 1)] (let [next-seg (% (+ seg 1) segments) curr-row (+ 1 (* ring segments)) next-row (+ 1 (* (+ ring 1) segments))] (table.insert indices (+ curr-row seg)) (table.insert indices (+ curr-row next-seg)) (table.insert indices (+ next-row seg)) (table.insert indices (+ curr-row next-seg)) (table.insert indices (+ next-row next-seg)) (table.insert indices (+ next-row seg))))) (let [last-ring-start (+ 1 (* (- rings 2) segments))] (for [seg 0 (- segments 1)] (let [next-seg (% (+ seg 1) segments)] (table.insert indices bottom-idx) (table.insert indices (+ last-ring-start seg)) (table.insert indices (+ last-ring-start next-seg)))))) (let [num-spikes 12 spike-len 8 base-size 1.2 golden-ratio (/ (+ 1 (math.sqrt 5)) 2)] (for [i 0 (- num-spikes 1)] (let [y (- 1 (* (/ i (- num-spikes 1)) 2)) r-at-y (math.sqrt (- 1 (* y y))) theta (* math.pi 2 i golden-ratio) nx (* r-at-y (math.cos theta)) ny y nz (* r-at-y (math.sin theta)) tx (if (> (math.abs ny) 0.9) 1 0) ty (if (> (math.abs ny) 0.9) 0 1) tz 0 px (- (* ty nz) (* tz ny)) py (- (* tz nx) (* tx nz)) pz (- (* tx ny) (* ty nx)) pl (math.sqrt (+ (* px px) (* py py) (* pz pz))) px (/ px pl) py (/ py pl) pz (/ pz pl) qx (- (* ny pz) (* nz py)) qy (- (* nz px) (* nx pz)) qz (- (* nx py) (* ny px)) bx (* radius 0.8 nx) by (* radius 0.8 ny) bz (* radius 0.8 nz) sx (* (+ radius spike-len) nx) sy (* (+ radius spike-len) ny) sz (* (+ radius spike-len) nz) base-idx (length verts)] (table.insert verts {:x (+ bx (* base-size px) (* base-size qx)) :y (+ by (* base-size py) (* base-size qy)) :z (+ bz (* base-size pz) (* base-size qz)) :nx nx :ny ny :nz nz :color core-color :light 255}) (table.insert verts {:x (+ bx (* base-size px) (* (- base-size) qx)) :y (+ by (* base-size py) (* (- base-size) qy)) :z (+ bz (* base-size pz) (* (- base-size) qz)) :nx nx :ny ny :nz nz :color core-color :light 255}) (table.insert verts {:x (+ bx (* (- base-size) px) (* (- base-size) qx)) :y (+ by (* (- base-size) py) (* (- base-size) qy)) :z (+ bz (* (- base-size) pz) (* (- base-size) qz)) :nx nx :ny ny :nz nz :color core-color :light 255}) (table.insert verts {:x (+ bx (* (- base-size) px) (* base-size qx)) :y (+ by (* (- base-size) py) (* base-size qy)) :z (+ bz (* (- base-size) pz) (* base-size qz)) :nx nx :ny ny :nz nz :color core-color :light 255}) (table.insert verts {:x sx :y sy :z sz :nx nx :ny ny :nz nz :color spike-color :light 255}) (table.insert indices base-idx) (table.insert indices (+ base-idx 1)) (table.insert indices (+ base-idx 4)) (table.insert indices (+ base-idx 1)) (table.insert indices (+ base-idx 2)) (table.insert indices (+ base-idx 4)) (table.insert indices (+ base-idx 2)) (table.insert indices (+ base-idx 3)) (table.insert indices (+ base-idx 4)) (table.insert indices (+ base-idx 3)) (table.insert indices base-idx) (table.insert indices (+ base-idx 4))))) (set fireball-mesh (pxl8.create_mesh verts indices)))) (fn get-door-position [] (values DOOR_X DOOR_Z)) (fn get-door-radius [] 20) (fn init [textures] (when (not door-mesh) (create-door-mesh)) (when (not fireball-mesh) (create-fireball-mesh)) (when (and (not door-tex) textures) (set door-tex (textures.door)))) (fn render-door [wireframe floor-y] (when (and door-mesh door-tex) (pxl8.draw_mesh door-mesh {:x 0 :y (or floor-y 0) :z 0 :texture door-tex :lighting true :double_sided true :wireframe wireframe}))) (fn render-fireball [x y z wireframe] (when fireball-mesh (pxl8.draw_mesh fireball-mesh {:x x :y y :z z :passthrough true :wireframe wireframe :emissive 1.0}))) {:FIREBALL_COLOR FIREBALL_COLOR :get-door-position get-door-position :get-door-radius get-door-radius :init init :render-door render-door :render-fireball render-fireball}