180 lines
7.2 KiB
Fennel
180 lines
7.2 KiB
Fennel
(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}
|