add networking, 3d improvements, reorganize src structure
This commit is contained in:
parent
39b604b333
commit
415d424057
122 changed files with 5358 additions and 721 deletions
393
demo/mod/first_person3d.fnl
Normal file
393
demo/mod/first_person3d.fnl
Normal file
|
|
@ -0,0 +1,393 @@
|
|||
(local pxl8 (require :pxl8))
|
||||
(local effects (require :pxl8.effects))
|
||||
(local net (require :pxl8.net))
|
||||
(local sky (require :mod.sky))
|
||||
|
||||
(local bob-amount 4.0)
|
||||
(local bob-speed 8.0)
|
||||
(local cam-smoothing 0.25)
|
||||
(local cell-size 64)
|
||||
(local cursor-sensitivity 0.008)
|
||||
(local gravity -800)
|
||||
(local grid-size 64)
|
||||
(local ground-y 64)
|
||||
(local jump-force 175)
|
||||
(local land-recovery-speed 20)
|
||||
(local land-squash-amount -4)
|
||||
(local max-pitch 1.5)
|
||||
(local move-speed 200)
|
||||
(local turn-speed 2.0)
|
||||
|
||||
(local sim-tick-rate 60)
|
||||
(local sim-dt (/ 1.0 sim-tick-rate))
|
||||
(local history-size 128)
|
||||
(local correction-threshold 1.0)
|
||||
|
||||
(var auto-run? false)
|
||||
(var auto-run-cancel-key nil)
|
||||
(var bob-time 0)
|
||||
(var cam-pitch 0)
|
||||
(var cam-x 1000)
|
||||
(var cam-y 64)
|
||||
(var cam-yaw 0)
|
||||
(var cam-z 1000)
|
||||
(var camera nil)
|
||||
(var cursor-look? true)
|
||||
(var grounded? true)
|
||||
(var land-squash 0)
|
||||
(var light-time 0)
|
||||
(var network nil)
|
||||
(var smooth-cam-x 1000)
|
||||
(var smooth-cam-z 1000)
|
||||
(var velocity-y 0)
|
||||
(var world nil)
|
||||
(var fps-avg 0)
|
||||
(var fps-sample-count 0)
|
||||
|
||||
(local FIREBALL_COLOR 184)
|
||||
|
||||
(fn init-fireball-palette []
|
||||
(for [i 0 7]
|
||||
(let [t (/ i 7)
|
||||
r (math.floor (+ 0xFF (* t 0)))
|
||||
g (math.floor (+ 0x60 (* t (- 0xE0 0x60))))
|
||||
b (math.floor (+ 0x10 (* t (- 0x80 0x10))))]
|
||||
(pxl8.set_palette_rgb (+ FIREBALL_COLOR i) r g b))))
|
||||
|
||||
(var client-tick 0)
|
||||
(var last-processed-tick 0)
|
||||
(var time-accumulator 0)
|
||||
(var position-history {})
|
||||
(var pending-inputs {})
|
||||
|
||||
(fn history-idx [tick]
|
||||
(+ 1 (% tick history-size)))
|
||||
|
||||
(fn store-position [tick x z yaw]
|
||||
(tset position-history (history-idx tick) {:tick tick :x x :z z :yaw yaw}))
|
||||
|
||||
(fn get-position [tick]
|
||||
(let [entry (. position-history (history-idx tick))]
|
||||
(when (and entry (= entry.tick tick))
|
||||
entry)))
|
||||
|
||||
(fn store-pending-input [tick input]
|
||||
(tset pending-inputs (history-idx tick) {:tick tick :input input}))
|
||||
|
||||
(fn get-pending-input [tick]
|
||||
(let [entry (. pending-inputs (history-idx tick))]
|
||||
(when (and entry (= entry.tick tick))
|
||||
entry.input)))
|
||||
|
||||
(fn apply-movement [x z yaw input]
|
||||
(var new-x x)
|
||||
(var new-z z)
|
||||
|
||||
(let [move-forward (or input.move_y 0)
|
||||
move-right (or input.move_x 0)]
|
||||
(when (or (not= move-forward 0) (not= move-right 0))
|
||||
(let [forward-x (- (math.sin yaw))
|
||||
forward-z (- (math.cos yaw))
|
||||
right-x (math.cos yaw)
|
||||
right-z (- (math.sin yaw))
|
||||
len (math.sqrt (+ (* move-forward move-forward) (* move-right move-right)))
|
||||
norm-forward (/ move-forward len)
|
||||
norm-right (/ move-right len)
|
||||
move-delta (* move-speed sim-dt)]
|
||||
(set new-x (+ new-x (* move-delta (+ (* forward-x norm-forward) (* right-x norm-right)))))
|
||||
(set new-z (+ new-z (* move-delta (+ (* forward-z norm-forward) (* right-z norm-right))))))))
|
||||
|
||||
(values new-x new-z))
|
||||
(fn init []
|
||||
(set camera (pxl8.create_camera_3d))
|
||||
(set world (pxl8.create_world))
|
||||
(sky.generate-stars 12345)
|
||||
(init-fireball-palette)
|
||||
|
||||
(set network (net.Net.new {:port 7777}))
|
||||
(when network
|
||||
(network:connect)
|
||||
(network:spawn cam-x cam-y cam-z cam-yaw cam-pitch))
|
||||
|
||||
(let [result (world:generate {
|
||||
:type pxl8.PROCGEN_ROOMS
|
||||
:width 64
|
||||
:height 64
|
||||
:seed 42
|
||||
:min_room_size 5
|
||||
:max_room_size 10
|
||||
:num_rooms 20})]
|
||||
(if (< result 0)
|
||||
(pxl8.error (.. "Failed to generate rooms - result: " result))
|
||||
(let [floor-tex (pxl8.procgen_tex {:name "floor"
|
||||
:seed 11111
|
||||
:width 64
|
||||
:height 64
|
||||
:base_color 19})
|
||||
wall-tex (pxl8.procgen_tex {:name "wall"
|
||||
:seed 12345
|
||||
:width 64
|
||||
:height 64
|
||||
:base_color 4})
|
||||
sky-tex (pxl8.create_texture [0] 1 1)]
|
||||
|
||||
(let [result (world:apply_textures [
|
||||
{:name "floor"
|
||||
:texture_id floor-tex
|
||||
:rule (fn [normal] (> normal.y 0.7))}
|
||||
{:name "ceiling"
|
||||
:texture_id sky-tex
|
||||
:rule (fn [normal] (< normal.y -0.7))}
|
||||
{:name "wall"
|
||||
:texture_id wall-tex
|
||||
:rule (fn [normal] (and (<= normal.y 0.7) (>= normal.y -0.7)))}])]
|
||||
(when (< result 0)
|
||||
(pxl8.error (.. "Failed to apply textures - result: " result))))))))
|
||||
|
||||
(fn sample-input []
|
||||
(var move-forward 0)
|
||||
(var move-right 0)
|
||||
|
||||
(when (pxl8.key_pressed "`")
|
||||
(set auto-run? (not auto-run?))
|
||||
(when (and auto-run? (pxl8.key_down "w"))
|
||||
(set auto-run-cancel-key "w")))
|
||||
(when (and auto-run? (not auto-run-cancel-key) (or (pxl8.key_down "w") (pxl8.key_down "s")))
|
||||
(set auto-run? false)
|
||||
(when (pxl8.key_down "s")
|
||||
(set auto-run-cancel-key "s")))
|
||||
(when (and auto-run-cancel-key (not (pxl8.key_down auto-run-cancel-key)))
|
||||
(set auto-run-cancel-key nil))
|
||||
|
||||
(when (or (pxl8.key_down "w") auto-run?)
|
||||
(set move-forward (+ move-forward 1)))
|
||||
(when (and (pxl8.key_down "s") (not= auto-run-cancel-key "s"))
|
||||
(set move-forward (- move-forward 1)))
|
||||
(when (pxl8.key_down "a")
|
||||
(set move-right (- move-right 1)))
|
||||
(when (pxl8.key_down "d")
|
||||
(set move-right (+ move-right 1)))
|
||||
|
||||
{:move_x move-right
|
||||
:move_y move-forward
|
||||
:look_dx (pxl8.mouse_dx)
|
||||
:look_dy (pxl8.mouse_dy)})
|
||||
|
||||
(fn reconcile [server-tick server-x server-z]
|
||||
(let [predicted (get-position server-tick)]
|
||||
(when predicted
|
||||
(let [dx (- predicted.x server-x)
|
||||
dz (- predicted.z server-z)
|
||||
error (math.sqrt (+ (* dx dx) (* dz dz)))]
|
||||
(when (> error correction-threshold)
|
||||
(set cam-x server-x)
|
||||
(set cam-z server-z)
|
||||
|
||||
(for [t (+ server-tick 1) client-tick]
|
||||
(let [input (get-pending-input t)
|
||||
hist (get-position t)]
|
||||
(when (and input hist)
|
||||
(let [(new-x new-z) (apply-movement cam-x cam-z hist.yaw input)]
|
||||
(set cam-x new-x)
|
||||
(set cam-z new-z)
|
||||
(store-position t cam-x cam-z hist.yaw))))))))))
|
||||
|
||||
(fn update [dt]
|
||||
(let [fps (pxl8.get_fps)]
|
||||
(set fps-sample-count (+ fps-sample-count 1))
|
||||
(set fps-avg (+ (* fps-avg (/ (- fps-sample-count 1) fps-sample-count))
|
||||
(/ fps fps-sample-count)))
|
||||
(when (>= fps-sample-count 120)
|
||||
(set fps-sample-count 0)
|
||||
(set fps-avg 0)))
|
||||
|
||||
(when (world:is_loaded)
|
||||
(let [input (sample-input)
|
||||
grid-max (* grid-size cell-size)
|
||||
movement-yaw cam-yaw]
|
||||
|
||||
(set time-accumulator (+ time-accumulator dt))
|
||||
|
||||
(while (>= time-accumulator sim-dt)
|
||||
(set time-accumulator (- time-accumulator sim-dt))
|
||||
(set client-tick (+ client-tick 1))
|
||||
|
||||
(store-pending-input client-tick input)
|
||||
|
||||
(let [(new-x new-z) (apply-movement cam-x cam-z movement-yaw input)]
|
||||
(when (and (>= new-x 0) (<= new-x grid-max)
|
||||
(>= new-z 0) (<= new-z grid-max))
|
||||
(let [(resolved-x _ resolved-z) (world:resolve_collision cam-x cam-y cam-z new-x cam-y new-z 5)]
|
||||
(set cam-x resolved-x)
|
||||
(set cam-z resolved-z)))
|
||||
|
||||
(store-position client-tick cam-x cam-z movement-yaw)))
|
||||
|
||||
(when cursor-look?
|
||||
(set cam-yaw (- cam-yaw (* input.look_dx cursor-sensitivity)))
|
||||
(set cam-pitch (math.max (- max-pitch)
|
||||
(math.min max-pitch
|
||||
(- cam-pitch (* input.look_dy cursor-sensitivity))))))
|
||||
|
||||
(when (and (not cursor-look?) (pxl8.key_down "up"))
|
||||
(set cam-pitch (math.min max-pitch (+ cam-pitch (* turn-speed dt)))))
|
||||
(when (and (not cursor-look?) (pxl8.key_down "down"))
|
||||
(set cam-pitch (math.max (- max-pitch) (- cam-pitch (* turn-speed dt)))))
|
||||
(when (and (not cursor-look?) (pxl8.key_down "left"))
|
||||
(set cam-yaw (+ cam-yaw (* turn-speed dt))))
|
||||
(when (and (not cursor-look?) (pxl8.key_down "right"))
|
||||
(set cam-yaw (- cam-yaw (* turn-speed dt))))
|
||||
|
||||
(when network
|
||||
(let [(ok err) (pcall (fn []
|
||||
(network:send_input {:move_x input.move_x
|
||||
:move_y input.move_y
|
||||
:look_dx input.look_dx
|
||||
:look_dy input.look_dy
|
||||
:yaw movement-yaw
|
||||
:tick client-tick})
|
||||
(network:update dt)
|
||||
(when (network:poll)
|
||||
(let [snapshot (network:snapshot)]
|
||||
(when (and snapshot (> snapshot.tick last-processed-tick))
|
||||
(set last-processed-tick snapshot.tick)
|
||||
(let [player-id (network:player_id)]
|
||||
(when (> player-id 0)
|
||||
(let [curr (network:entity_userdata player-id)]
|
||||
(when curr
|
||||
(let [srv-x (pxl8.unpack_f32_be curr 0)
|
||||
srv-z (pxl8.unpack_f32_be curr 8)]
|
||||
(reconcile snapshot.tick srv-x srv-z)))))))))))]
|
||||
(when (not ok)
|
||||
(pxl8.error (.. "Network error: " err)))))
|
||||
|
||||
(set smooth-cam-x (+ (* smooth-cam-x (- 1 cam-smoothing)) (* cam-x cam-smoothing)))
|
||||
(set smooth-cam-z (+ (* smooth-cam-z (- 1 cam-smoothing)) (* cam-z cam-smoothing)))
|
||||
|
||||
(when (and (pxl8.key_pressed "space") grounded?)
|
||||
(set velocity-y jump-force)
|
||||
(set grounded? false))
|
||||
|
||||
(set velocity-y (+ velocity-y (* gravity dt)))
|
||||
(set cam-y (+ cam-y (* velocity-y dt)))
|
||||
|
||||
(when (<= cam-y ground-y)
|
||||
(when (not grounded?)
|
||||
(set land-squash land-squash-amount))
|
||||
(set cam-y ground-y)
|
||||
(set velocity-y 0)
|
||||
(set grounded? true))
|
||||
|
||||
(when (< land-squash 0)
|
||||
(set land-squash (math.min 0 (+ land-squash (* land-recovery-speed dt)))))
|
||||
|
||||
(let [moving (or (not= input.move_x 0) (not= input.move_y 0))]
|
||||
(if (and moving grounded?)
|
||||
(set bob-time (+ bob-time (* dt bob-speed)))
|
||||
(let [target-phase (* (math.floor (/ bob-time math.pi)) math.pi)]
|
||||
(set bob-time (+ (* bob-time 0.8) (* target-phase 0.2))))))
|
||||
|
||||
(set light-time (+ light-time (* dt 0.15))))))
|
||||
|
||||
(fn frame []
|
||||
(pxl8.clear 1)
|
||||
|
||||
(when (not camera)
|
||||
(pxl8.error "camera is nil!"))
|
||||
|
||||
(when (not world)
|
||||
(pxl8.error "world is nil!"))
|
||||
|
||||
(when (and world (not (world:is_loaded)))
|
||||
(pxl8.text "World not loaded yet..." 5 30 12))
|
||||
|
||||
(when (and camera world (world:is_loaded))
|
||||
(let [bob-offset (* (math.sin bob-time) bob-amount)
|
||||
eye-y (+ cam-y bob-offset land-squash)
|
||||
forward-x (- (math.sin cam-yaw))
|
||||
forward-z (- (math.cos cam-yaw))
|
||||
target-x (+ smooth-cam-x forward-x)
|
||||
target-y (+ eye-y (math.sin cam-pitch))
|
||||
target-z (+ smooth-cam-z forward-z)
|
||||
aspect (/ (pxl8.get_width) (pxl8.get_height))]
|
||||
|
||||
(camera:lookat [smooth-cam-x eye-y smooth-cam-z]
|
||||
[target-x target-y target-z]
|
||||
[0 1 0])
|
||||
(camera:set_perspective 1.047 aspect 1.0 4096.0)
|
||||
|
||||
(let [light-pulse (+ 0.7 (* 0.3 (math.sin (* light-time 2))))
|
||||
forward-x (- (math.sin cam-yaw))
|
||||
forward-z (- (math.cos cam-yaw))
|
||||
light-x (+ smooth-cam-x (* 150 forward-x) (* 50 (math.cos light-time)))
|
||||
light-z (+ smooth-cam-z (* 150 forward-z) (* 50 (math.sin light-time)))
|
||||
light-y (+ eye-y 30)]
|
||||
(pxl8.begin_frame_3d camera {
|
||||
:ambient 80
|
||||
:celestial_dir [0.5 -0.8 0.3]
|
||||
:celestial_intensity 0.5
|
||||
:lights [{:x light-x :y light-y :z light-z
|
||||
:r 255 :g 200 :b 150
|
||||
:intensity (* 255 light-pulse)
|
||||
:radius 400}]})
|
||||
(pxl8.clear_depth)
|
||||
|
||||
(sky.update-gradient 1 2 6 6 10 18)
|
||||
(sky.render smooth-cam-x eye-y smooth-cam-z)
|
||||
(pxl8.clear_depth)
|
||||
|
||||
(world:render [smooth-cam-x eye-y smooth-cam-z])
|
||||
|
||||
(pxl8.end_frame_3d)
|
||||
|
||||
(let [dx (- light-x smooth-cam-x)
|
||||
dy (- light-y eye-y)
|
||||
dz (- light-z smooth-cam-z)
|
||||
dist (math.sqrt (+ (* dx dx) (* dy dy) (* dz dz)))]
|
||||
(when (> dist 1)
|
||||
(let [inv-dist (/ 1 dist)
|
||||
dir-x (* dx inv-dist)
|
||||
dir-y (* dy inv-dist)
|
||||
dir-z (* dz inv-dist)
|
||||
cos-yaw (math.cos cam-yaw)
|
||||
sin-yaw (math.sin cam-yaw)
|
||||
cos-pitch (math.cos cam-pitch)
|
||||
sin-pitch (math.sin cam-pitch)
|
||||
rx (+ (* dir-x cos-yaw) (* dir-z sin-yaw))
|
||||
rz (+ (* (- dir-x) sin-yaw) (* dir-z cos-yaw))
|
||||
ry (- (* dir-y cos-pitch) (* rz sin-pitch))
|
||||
fz (+ (* dir-y sin-pitch) (* rz cos-pitch))]
|
||||
(when (> fz 0.01)
|
||||
(let [width (pxl8.get_width)
|
||||
height (pxl8.get_height)
|
||||
fov 1.047
|
||||
half-fov-tan (math.tan (* fov 0.5))
|
||||
ndc-x (/ rx (* fz half-fov-tan aspect))
|
||||
ndc-y (/ ry (* fz half-fov-tan))
|
||||
sx (math.floor (* (+ 1 ndc-x) 0.5 width))
|
||||
sy (math.floor (* (- 1 ndc-y) 0.5 height))
|
||||
screen-size (/ 400 dist)
|
||||
base-radius (math.max 2 (math.min 12 (math.floor screen-size)))
|
||||
pulse-int (math.floor (* 180 light-pulse))]
|
||||
(when (and (>= sx 0) (< sx width) (>= sy 0) (< sy height))
|
||||
(effects.glows [
|
||||
{:x sx :y sy :radius (+ base-radius 2) :intensity (/ pulse-int 5) :color (+ FIREBALL_COLOR 1) :shape effects.GLOW_CIRCLE}
|
||||
{:x sx :y sy :radius base-radius :intensity pulse-int :color (+ FIREBALL_COLOR 5) :shape effects.GLOW_DIAMOND}]))))))))
|
||||
|
||||
(sky.render-stars cam-yaw cam-pitch 1.0)
|
||||
|
||||
(let [cx (/ (pxl8.get_width) 2)
|
||||
cy (/ (pxl8.get_height) 2)
|
||||
crosshair-size 4
|
||||
red-color 18]
|
||||
(pxl8.line (- cx crosshair-size) cy (+ cx crosshair-size) cy red-color)
|
||||
(pxl8.line cx (- cy crosshair-size) cx (+ cy crosshair-size) red-color))
|
||||
|
||||
(pxl8.text (.. "fps: " (string.format "%.0f" fps-avg)) 5 5 12)
|
||||
(pxl8.text (.. "pos: " (string.format "%.0f" cam-x) ","
|
||||
(string.format "%.0f" cam-y) ","
|
||||
(string.format "%.0f" cam-z)) 5 15 12))))
|
||||
|
||||
{:init init
|
||||
:update update
|
||||
:frame frame}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
(local pxl8 (require :pxl8))
|
||||
(local music (require :mod.music))
|
||||
|
||||
(var paused false)
|
||||
(var gui nil)
|
||||
|
|
@ -36,12 +37,18 @@
|
|||
(when gui
|
||||
(gui:begin_frame)
|
||||
|
||||
(pxl8.gui_window 200 100 240 140 "pxl8 demo")
|
||||
(pxl8.gui_window 200 100 240 180 "pxl8 demo")
|
||||
|
||||
(when (gui:button 1 215 145 210 32 "Resume")
|
||||
(hide))
|
||||
|
||||
(when (gui:button 2 215 185 210 32 "Quit")
|
||||
(let [music-label (if (music.is-playing) "Music: On" "Music: Off")]
|
||||
(when (gui:button 3 215 185 210 32 music-label)
|
||||
(if (music.is-playing)
|
||||
(music.stop)
|
||||
(music.start))))
|
||||
|
||||
(when (gui:button 2 215 225 210 32 "Quit")
|
||||
(pxl8.quit))
|
||||
|
||||
(if (gui:is_hovering)
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@
|
|||
(fn update [dt]
|
||||
(when playing
|
||||
(set time (+ time dt))
|
||||
(when (>= time step-duration)
|
||||
(while (>= time step-duration)
|
||||
(set time (- time step-duration))
|
||||
|
||||
(local melody-idx (+ 1 (% step (length melody))))
|
||||
|
|
@ -125,4 +125,5 @@
|
|||
:start start
|
||||
:stop stop
|
||||
:update update
|
||||
:is-playing (fn [] playing)}
|
||||
:is-playing (fn [] playing)
|
||||
:get-step (fn [] step)}
|
||||
|
|
|
|||
250
demo/mod/sky.fnl
Normal file
250
demo/mod/sky.fnl
Normal file
|
|
@ -0,0 +1,250 @@
|
|||
(local ffi (require :ffi))
|
||||
(local pxl8 (require :pxl8))
|
||||
(local effects (require :pxl8.effects))
|
||||
|
||||
(local SKY_GRADIENT_START 144)
|
||||
(local SKY_GRADIENT_COUNT 16)
|
||||
(local sky-radius 900)
|
||||
(local sky-segments 16)
|
||||
(local sky-rings 16)
|
||||
(local max-theta (* math.pi 0.55))
|
||||
|
||||
(local STAR_COUNT 200)
|
||||
(local TINY_STAR_COUNT 5000)
|
||||
(local STAR_SILVER_START 160)
|
||||
(local STAR_BLUE_START 168)
|
||||
(local STAR_RED_START 176)
|
||||
|
||||
(var sky-mesh nil)
|
||||
(var last-gradient-key nil)
|
||||
(var stars [])
|
||||
(var tiny-stars [])
|
||||
|
||||
(fn generate-sky-gradient [zenith-r zenith-g zenith-b horizon-r horizon-g horizon-b]
|
||||
(for [i 0 (- SKY_GRADIENT_COUNT 1)]
|
||||
(let [t (/ i (- SKY_GRADIENT_COUNT 1))
|
||||
r (math.floor (+ zenith-r (* t (- horizon-r zenith-r))))
|
||||
g (math.floor (+ zenith-g (* t (- horizon-g zenith-g))))
|
||||
b (math.floor (+ zenith-b (* t (- horizon-b zenith-b))))]
|
||||
(pxl8.set_palette_rgb (+ SKY_GRADIENT_START i) r g b))))
|
||||
|
||||
(fn create-sky-dome []
|
||||
(let [verts []
|
||||
indices []]
|
||||
|
||||
(for [i 0 (- sky-rings 1)]
|
||||
(let [theta0 (* (/ i sky-rings) max-theta)
|
||||
theta1 (* (/ (+ i 1) sky-rings) max-theta)
|
||||
sin-t0 (math.sin theta0)
|
||||
cos-t0 (math.cos theta0)
|
||||
sin-t1 (math.sin theta1)
|
||||
cos-t1 (math.cos theta1)
|
||||
y0 (* sky-radius cos-t0)
|
||||
y1 (* sky-radius cos-t1)
|
||||
r0 (* sky-radius sin-t0)
|
||||
r1 (* sky-radius sin-t1)
|
||||
t0 (/ i sky-rings)
|
||||
t1 (/ (+ i 1) sky-rings)
|
||||
c0 (math.floor (+ SKY_GRADIENT_START (* t0 (- SKY_GRADIENT_COUNT 1)) 0.5))
|
||||
c1 (math.floor (+ SKY_GRADIENT_START (* t1 (- SKY_GRADIENT_COUNT 1)) 0.5))]
|
||||
|
||||
(for [j 0 (- sky-segments 1)]
|
||||
(let [phi0 (* (/ j sky-segments) math.pi 2)
|
||||
phi1 (* (/ (+ j 1) sky-segments) math.pi 2)
|
||||
cos-p0 (math.cos phi0)
|
||||
sin-p0 (math.sin phi0)
|
||||
cos-p1 (math.cos phi1)
|
||||
sin-p1 (math.sin phi1)
|
||||
x00 (* r0 cos-p0) z00 (* r0 sin-p0)
|
||||
x01 (* r0 cos-p1) z01 (* r0 sin-p1)
|
||||
x10 (* r1 cos-p0) z10 (* r1 sin-p0)
|
||||
x11 (* r1 cos-p1) z11 (* r1 sin-p1)
|
||||
nx00 (- (* sin-t0 cos-p0)) ny00 (- cos-t0) nz00 (- (* sin-t0 sin-p0))
|
||||
nx01 (- (* sin-t0 cos-p1)) ny01 (- cos-t0) nz01 (- (* sin-t0 sin-p1))
|
||||
nx10 (- (* sin-t1 cos-p0)) ny10 (- cos-t1) nz10 (- (* sin-t1 sin-p0))
|
||||
nx11 (- (* sin-t1 cos-p1)) ny11 (- cos-t1) nz11 (- (* sin-t1 sin-p1))
|
||||
base-idx (# verts)]
|
||||
|
||||
(if (= i 0)
|
||||
(do
|
||||
;; First ring is degenerate - just a triangle from pole
|
||||
;; Vertices: v00 (pole, c0), v11 (bottom-right, c1), v10 (bottom-left, c1)
|
||||
(table.insert verts {:x x00 :y y0 :z z00 :nx nx00 :ny ny00 :nz nz00 :color c0 :light 255})
|
||||
(table.insert verts {:x x11 :y y1 :z z11 :nx nx11 :ny ny11 :nz nz11 :color c1 :light 255})
|
||||
(table.insert verts {:x x10 :y y1 :z z10 :nx nx10 :ny ny10 :nz nz10 :color c1 :light 255})
|
||||
;; Triangle: base, base+2, base+1
|
||||
(table.insert indices base-idx)
|
||||
(table.insert indices (+ base-idx 2))
|
||||
(table.insert indices (+ base-idx 1)))
|
||||
(do
|
||||
;; Regular quad: v00 (top-left), v01 (top-right), v11 (bottom-right), v10 (bottom-left)
|
||||
(table.insert verts {:x x00 :y y0 :z z00 :nx nx00 :ny ny00 :nz nz00 :color c0 :light 255})
|
||||
(table.insert verts {:x x01 :y y0 :z z01 :nx nx01 :ny ny01 :nz nz01 :color c0 :light 255})
|
||||
(table.insert verts {:x x11 :y y1 :z z11 :nx nx11 :ny ny11 :nz nz11 :color c1 :light 255})
|
||||
(table.insert verts {:x x10 :y y1 :z z10 :nx nx10 :ny ny10 :nz nz10 :color c1 :light 255})
|
||||
;; push_quad(base, base+3, base+2, base+1) = triangles (base,base+3,base+2) and (base,base+2,base+1)
|
||||
(table.insert indices base-idx)
|
||||
(table.insert indices (+ base-idx 3))
|
||||
(table.insert indices (+ base-idx 2))
|
||||
(table.insert indices base-idx)
|
||||
(table.insert indices (+ base-idx 2))
|
||||
(table.insert indices (+ base-idx 1))))))))
|
||||
|
||||
(set sky-mesh (pxl8.create_mesh verts indices))))
|
||||
|
||||
(fn update-gradient [zenith-r zenith-g zenith-b horizon-r horizon-g horizon-b]
|
||||
(let [key (.. zenith-r "," zenith-g "," zenith-b "," horizon-r "," horizon-g "," horizon-b)]
|
||||
(when (not= key last-gradient-key)
|
||||
(generate-sky-gradient zenith-r zenith-g zenith-b horizon-r horizon-g horizon-b)
|
||||
(set last-gradient-key key))))
|
||||
|
||||
(fn palette-ramp [start c0 c1]
|
||||
(let [r0 (bit.rshift (bit.band c0 0xFF0000) 16)
|
||||
g0 (bit.rshift (bit.band c0 0x00FF00) 8)
|
||||
b0 (bit.band c0 0x0000FF)
|
||||
r1 (bit.rshift (bit.band c1 0xFF0000) 16)
|
||||
g1 (bit.rshift (bit.band c1 0x00FF00) 8)
|
||||
b1 (bit.band c1 0x0000FF)]
|
||||
(for [i 0 7]
|
||||
(let [t (/ i 7)
|
||||
r (math.floor (+ r0 (* t (- r1 r0))))
|
||||
g (math.floor (+ g0 (* t (- g1 g0))))
|
||||
b (math.floor (+ b0 (* t (- b1 b0))))]
|
||||
(pxl8.set_palette_rgb (+ start i) r g b)))))
|
||||
|
||||
(fn init-star-palette []
|
||||
(palette-ramp STAR_SILVER_START 0x707888 0xFFFFFF) ;; silver
|
||||
(palette-ramp STAR_BLUE_START 0x5070B0 0xD0E8FF) ;; blue
|
||||
(palette-ramp STAR_RED_START 0x802020 0xFF9090)) ;; red
|
||||
|
||||
(fn generate-stars [seed]
|
||||
(set stars [])
|
||||
(set tiny-stars [])
|
||||
(init-star-palette)
|
||||
(pxl8.rng_seed seed)
|
||||
|
||||
(for [i 1 STAR_COUNT]
|
||||
(let [theta (math.acos (- 1 (* (pxl8.rng_f32) 0.85)))
|
||||
phi (* (pxl8.rng_f32) math.pi 2)
|
||||
brightness (pxl8.rng_range 1 4)
|
||||
color-type (pxl8.rng_range 0 100)
|
||||
shade (pxl8.rng_range 0 5)
|
||||
color (if (< color-type 3) (+ STAR_RED_START shade)
|
||||
(< color-type 15) (+ STAR_BLUE_START shade)
|
||||
(+ STAR_SILVER_START shade))
|
||||
sin-t (math.sin theta)
|
||||
cos-t (math.cos theta)]
|
||||
(table.insert stars {:dx (* sin-t (math.cos phi))
|
||||
:dy cos-t
|
||||
:dz (* sin-t (math.sin phi))
|
||||
:brightness brightness
|
||||
:color color})))
|
||||
|
||||
(pxl8.rng_seed (+ seed 0xCAFEBABE))
|
||||
(for [i 1 TINY_STAR_COUNT]
|
||||
(let [theta (math.acos (- 1 (* (pxl8.rng_f32) 0.95)))
|
||||
phi (* (pxl8.rng_f32) math.pi 2)
|
||||
brightness (+ 25 (pxl8.rng_range 0 40))
|
||||
shade (pxl8.rng_range 0 3)
|
||||
color-type (pxl8.rng_range 0 100)
|
||||
color (if (< color-type 15) (+ STAR_BLUE_START shade)
|
||||
(+ STAR_SILVER_START shade))
|
||||
sin-t (math.sin theta)
|
||||
cos-t (math.cos theta)]
|
||||
(table.insert tiny-stars {:dx (* sin-t (math.cos phi))
|
||||
:dy cos-t
|
||||
:dz (* sin-t (math.sin phi))
|
||||
:brightness brightness
|
||||
:color color}))))
|
||||
|
||||
(fn project-direction [dir-x dir-y dir-z yaw pitch width height]
|
||||
(let [cos-yaw (math.cos yaw)
|
||||
sin-yaw (math.sin yaw)
|
||||
cos-pitch (math.cos pitch)
|
||||
sin-pitch (math.sin pitch)
|
||||
rotated-x (+ (* dir-x cos-yaw) (* dir-z sin-yaw))
|
||||
rotated-z (+ (* (- dir-x) sin-yaw) (* dir-z cos-yaw))
|
||||
rotated-y (- (* dir-y cos-pitch) (* rotated-z sin-pitch))
|
||||
final-z (+ (* dir-y sin-pitch) (* rotated-z cos-pitch))]
|
||||
(when (> final-z 0.01)
|
||||
(let [fov 1.047
|
||||
aspect (/ width height)
|
||||
half-fov-tan (math.tan (* fov 0.5))
|
||||
ndc-x (/ rotated-x (* final-z half-fov-tan aspect))
|
||||
ndc-y (/ rotated-y (* final-z half-fov-tan))]
|
||||
(when (and (>= ndc-x -1) (<= ndc-x 1) (>= ndc-y -1) (<= ndc-y 1))
|
||||
{:x (math.floor (* (+ 1 ndc-x) 0.5 width))
|
||||
:y (math.floor (* (- 1 ndc-y) 0.5 height))})))))
|
||||
|
||||
(fn render-stars [yaw pitch intensity]
|
||||
(when (> intensity 0)
|
||||
(let [width (pxl8.get_width)
|
||||
height (pxl8.get_height)
|
||||
glows []
|
||||
fade-sq (* intensity intensity)]
|
||||
|
||||
(each [_ star (ipairs tiny-stars)]
|
||||
(let [screen (project-direction star.dx star.dy star.dz yaw pitch width height)]
|
||||
(when screen
|
||||
(let [int (math.floor (* star.brightness fade-sq))]
|
||||
(when (> int 8)
|
||||
(table.insert glows {:x screen.x :y screen.y
|
||||
:radius 1
|
||||
:intensity int
|
||||
:color star.color
|
||||
:shape effects.GLOW_CIRCLE}))))))
|
||||
|
||||
(each [_ star (ipairs stars)]
|
||||
(let [screen (project-direction star.dx star.dy star.dz yaw pitch width height)]
|
||||
(when screen
|
||||
(let [base-int (math.floor (* star.brightness 50 fade-sq 1.5))]
|
||||
(if (>= star.brightness 4)
|
||||
(do
|
||||
(table.insert glows {:x screen.x :y screen.y
|
||||
:radius 4
|
||||
:intensity (math.floor (/ base-int 4))
|
||||
:color star.color
|
||||
:shape effects.GLOW_CIRCLE})
|
||||
(table.insert glows {:x screen.x :y screen.y
|
||||
:radius 2
|
||||
:intensity base-int
|
||||
:color star.color
|
||||
:shape effects.GLOW_DIAMOND}))
|
||||
(>= star.brightness 3)
|
||||
(do
|
||||
(table.insert glows {:x screen.x :y screen.y
|
||||
:radius 3
|
||||
:intensity (math.floor (/ base-int 4))
|
||||
:color star.color
|
||||
:shape effects.GLOW_CIRCLE})
|
||||
(table.insert glows {:x screen.x :y screen.y
|
||||
:radius 2
|
||||
:intensity base-int
|
||||
:color star.color
|
||||
:shape effects.GLOW_DIAMOND}))
|
||||
(>= star.brightness 2)
|
||||
(table.insert glows {:x screen.x :y screen.y
|
||||
:radius 2
|
||||
:intensity base-int
|
||||
:color star.color
|
||||
:shape effects.GLOW_DIAMOND})
|
||||
(table.insert glows {:x screen.x :y screen.y
|
||||
:radius 1
|
||||
:intensity (math.floor (* base-int 0.7))
|
||||
:color star.color
|
||||
:shape effects.GLOW_CIRCLE}))))))
|
||||
|
||||
(when (> (length glows) 0)
|
||||
(effects.glows glows)))))
|
||||
|
||||
(fn render [cam-x cam-y cam-z]
|
||||
(when (not sky-mesh) (create-sky-dome))
|
||||
(when sky-mesh
|
||||
(pxl8.draw_mesh sky-mesh {:x cam-x :y cam-y :z cam-z :passthrough true})))
|
||||
|
||||
{:render render
|
||||
:render-stars render-stars
|
||||
:generate-stars generate-stars
|
||||
:update-gradient update-gradient
|
||||
:SKY_GRADIENT_START SKY_GRADIENT_START
|
||||
:SKY_GRADIENT_COUNT SKY_GRADIENT_COUNT}
|
||||
75
demo/mod/vfx.fnl
Normal file
75
demo/mod/vfx.fnl
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
(local vfx {})
|
||||
|
||||
(fn vfx.explosion [ps x y ?opts]
|
||||
(let [opts (or ?opts {})
|
||||
color (or opts.color 208)
|
||||
force (or opts.force 200)]
|
||||
(ps:set_position x y)
|
||||
(ps:set_colors color (+ color 15))
|
||||
(ps:set_velocity (- force) force (- force) force)
|
||||
(ps:set_gravity 0 100)
|
||||
(ps:set_life 0.3 0.8)
|
||||
(ps:set_size 1 3)
|
||||
(ps:set_drag 0.98)
|
||||
(ps:set_spawn_rate 0)
|
||||
(ps:emit (or opts.count 50))))
|
||||
|
||||
(fn vfx.fire [ps x y ?opts]
|
||||
(let [opts (or ?opts {})
|
||||
width (or opts.width 50)
|
||||
color (or opts.color 208)]
|
||||
(ps:set_position x y)
|
||||
(ps:set_spread width 5)
|
||||
(ps:set_colors color (+ color 15))
|
||||
(ps:set_velocity -20 20 -80 -40)
|
||||
(ps:set_gravity 0 -30)
|
||||
(ps:set_life 0.5 1.5)
|
||||
(ps:set_size 1 2)
|
||||
(ps:set_turbulence 30)
|
||||
(ps:set_drag 0.95)
|
||||
(ps:set_spawn_rate (or opts.rate 50))))
|
||||
|
||||
(fn vfx.rain [ps width ?opts]
|
||||
(let [opts (or ?opts {})
|
||||
wind (or opts.wind 0)
|
||||
color (or opts.color 153)]
|
||||
(ps:set_position (/ width 2) -10)
|
||||
(ps:set_spread width 0)
|
||||
(ps:set_colors color (+ color 3))
|
||||
(ps:set_velocity (- wind 10) (+ wind 10) 300 400)
|
||||
(ps:set_gravity 0 200)
|
||||
(ps:set_life 1 2)
|
||||
(ps:set_size 1 1)
|
||||
(ps:set_drag 1)
|
||||
(ps:set_spawn_rate (or opts.rate 100))))
|
||||
|
||||
(fn vfx.smoke [ps x y ?opts]
|
||||
(let [opts (or ?opts {})
|
||||
color (or opts.color 248)]
|
||||
(ps:set_position x y)
|
||||
(ps:set_spread 10 5)
|
||||
(ps:set_colors color (+ color 7))
|
||||
(ps:set_velocity -15 15 -30 -10)
|
||||
(ps:set_gravity 0 -20)
|
||||
(ps:set_life 1 3)
|
||||
(ps:set_size 2 4)
|
||||
(ps:set_turbulence 20)
|
||||
(ps:set_drag 0.98)
|
||||
(ps:set_spawn_rate (or opts.rate 20))))
|
||||
|
||||
(fn vfx.snow [ps width ?opts]
|
||||
(let [opts (or ?opts {})
|
||||
wind (or opts.wind 10)
|
||||
color (or opts.color 15)]
|
||||
(ps:set_position (/ width 2) -10)
|
||||
(ps:set_spread width 0)
|
||||
(ps:set_colors color color)
|
||||
(ps:set_velocity (- wind 20) (+ wind 20) 30 60)
|
||||
(ps:set_gravity 0 10)
|
||||
(ps:set_life 3 6)
|
||||
(ps:set_size 1 2)
|
||||
(ps:set_turbulence 15)
|
||||
(ps:set_drag 0.99)
|
||||
(ps:set_spawn_rate (or opts.rate 30))))
|
||||
|
||||
vfx
|
||||
|
|
@ -1,224 +0,0 @@
|
|||
(local pxl8 (require :pxl8))
|
||||
|
||||
(local bob-amount 4.0)
|
||||
(local bob-speed 8.0)
|
||||
(local cam-smoothing 0.25)
|
||||
(local cell-size 64)
|
||||
(local cursor-sensitivity 0.008)
|
||||
(local gravity -800)
|
||||
(local grid-size 64)
|
||||
(local ground-y 64)
|
||||
(local jump-force 175)
|
||||
(local land-recovery-speed 20)
|
||||
(local land-squash-amount -4)
|
||||
(local max-pitch 1.5)
|
||||
(local move-speed 200)
|
||||
(local turn-speed 2.0)
|
||||
|
||||
(var auto-run? false)
|
||||
(var auto-run-cancel-key nil)
|
||||
(var bob-time 0)
|
||||
(var cam-pitch 0)
|
||||
(var cam-x 1000)
|
||||
(var cam-y 64)
|
||||
(var cam-yaw 0)
|
||||
(var cam-z 1000)
|
||||
(var camera nil)
|
||||
(var cursor-look? true)
|
||||
(var grounded? true)
|
||||
(var land-squash 0)
|
||||
(var smooth-cam-x 1000)
|
||||
(var smooth-cam-z 1000)
|
||||
(var velocity-y 0)
|
||||
(var world nil)
|
||||
|
||||
(fn init []
|
||||
(set camera (pxl8.create_camera_3d))
|
||||
(set world (pxl8.create_world))
|
||||
(let [result (world:generate {
|
||||
:type pxl8.PROCGEN_ROOMS
|
||||
:width 64
|
||||
:height 64
|
||||
:seed 42
|
||||
:min_room_size 5
|
||||
:max_room_size 10
|
||||
:num_rooms 20})]
|
||||
(if (< result 0)
|
||||
(pxl8.error (.. "Failed to generate rooms - result: " result))
|
||||
(let [floor-tex (pxl8.procgen_tex {:name "floor"
|
||||
:seed 11111
|
||||
:width 64
|
||||
:height 64
|
||||
:base_color 19})
|
||||
ceiling-tex (pxl8.procgen_tex {:name "ceiling"
|
||||
:seed 22222
|
||||
:width 64
|
||||
:height 64
|
||||
:base_color 1})
|
||||
wall-tex (pxl8.procgen_tex {:name "wall"
|
||||
:seed 12345
|
||||
:width 64
|
||||
:height 64
|
||||
:base_color 4})]
|
||||
|
||||
(let [result (world:apply_textures [
|
||||
{:name "floor"
|
||||
:texture_id floor-tex
|
||||
:rule (fn [normal] (> normal.y 0.7))}
|
||||
{:name "ceiling"
|
||||
:texture_id ceiling-tex
|
||||
:rule (fn [normal] (< normal.y -0.7))}
|
||||
{:name "wall"
|
||||
:texture_id wall-tex
|
||||
:rule (fn [normal] (and (<= normal.y 0.7) (>= normal.y -0.7)))}])]
|
||||
(when (< result 0)
|
||||
(pxl8.error (.. "Failed to apply textures - result: " result))))))))
|
||||
|
||||
(fn update [dt]
|
||||
(when (pxl8.key_pressed "`")
|
||||
(set auto-run? (not auto-run?))
|
||||
(when (and auto-run? (pxl8.key_down "w"))
|
||||
(set auto-run-cancel-key "w")))
|
||||
(when (and auto-run? (not auto-run-cancel-key) (or (pxl8.key_down "w") (pxl8.key_down "s")))
|
||||
(set auto-run? false)
|
||||
(when (pxl8.key_down "s")
|
||||
(set auto-run-cancel-key "s")))
|
||||
(when (and auto-run-cancel-key (not (pxl8.key_down auto-run-cancel-key)))
|
||||
(set auto-run-cancel-key nil))
|
||||
|
||||
(when (world:is_loaded)
|
||||
(let [forward-x (- (math.sin cam-yaw))
|
||||
forward-z (- (math.cos cam-yaw))
|
||||
right-x (math.cos cam-yaw)
|
||||
right-z (- (math.sin cam-yaw))
|
||||
grid-max (* grid-size cell-size)
|
||||
move-delta (* move-speed dt)]
|
||||
|
||||
(var moving false)
|
||||
(var move-forward 0)
|
||||
(var move-right 0)
|
||||
|
||||
(when (or (pxl8.key_down "w") auto-run?)
|
||||
(set move-forward (+ move-forward 1)))
|
||||
|
||||
(when (and (pxl8.key_down "s") (not= auto-run-cancel-key "s"))
|
||||
(set move-forward (- move-forward 1)))
|
||||
|
||||
(when (pxl8.key_down "a")
|
||||
(set move-right (- move-right 1)))
|
||||
|
||||
(when (pxl8.key_down "d")
|
||||
(set move-right (+ move-right 1)))
|
||||
|
||||
(set moving (or (not= move-forward 0) (not= move-right 0)))
|
||||
|
||||
(var new-x cam-x)
|
||||
(var new-z cam-z)
|
||||
|
||||
(when moving
|
||||
(let [len (math.sqrt (+ (* move-forward move-forward) (* move-right move-right)))
|
||||
norm-forward (/ move-forward len)
|
||||
norm-right (/ move-right len)]
|
||||
(set new-x (+ new-x (* move-delta (+ (* forward-x norm-forward) (* right-x norm-right)))))
|
||||
(set new-z (+ new-z (* move-delta (+ (* forward-z norm-forward) (* right-z norm-right)))))))
|
||||
|
||||
(when (and (>= new-x 0) (<= new-x grid-max)
|
||||
(>= new-z 0) (<= new-z grid-max))
|
||||
(let [(resolved-x resolved-y resolved-z) (world:resolve_collision cam-x cam-y cam-z new-x cam-y new-z 5)]
|
||||
(set cam-x resolved-x)
|
||||
(set cam-z resolved-z)))
|
||||
|
||||
(set smooth-cam-x (+ (* smooth-cam-x (- 1 cam-smoothing)) (* cam-x cam-smoothing)))
|
||||
(set smooth-cam-z (+ (* smooth-cam-z (- 1 cam-smoothing)) (* cam-z cam-smoothing)))
|
||||
|
||||
(when cursor-look?
|
||||
(let [dx (pxl8.mouse_dx)
|
||||
dy (pxl8.mouse_dy)]
|
||||
(set cam-yaw (- cam-yaw (* dx cursor-sensitivity)))
|
||||
(set cam-pitch (math.max (- max-pitch)
|
||||
(math.min max-pitch
|
||||
(- cam-pitch (* dy cursor-sensitivity)))))))
|
||||
|
||||
(when (and (not cursor-look?) (pxl8.key_down "left"))
|
||||
(set cam-yaw (+ cam-yaw (* turn-speed dt))))
|
||||
|
||||
(when (and (not cursor-look?) (pxl8.key_down "right"))
|
||||
(set cam-yaw (- cam-yaw (* turn-speed dt))))
|
||||
|
||||
(when (and (not cursor-look?) (pxl8.key_down "up"))
|
||||
(set cam-pitch (math.min max-pitch (+ cam-pitch (* turn-speed dt)))))
|
||||
|
||||
(when (and (not cursor-look?) (pxl8.key_down "down"))
|
||||
(set cam-pitch (math.max (- max-pitch) (- cam-pitch (* turn-speed dt)))))
|
||||
|
||||
(when (and (pxl8.key_pressed "space") grounded?)
|
||||
(set velocity-y jump-force)
|
||||
(set grounded? false))
|
||||
|
||||
(set velocity-y (+ velocity-y (* gravity dt)))
|
||||
(set cam-y (+ cam-y (* velocity-y dt)))
|
||||
|
||||
(when (<= cam-y ground-y)
|
||||
(when (not grounded?)
|
||||
(set land-squash land-squash-amount))
|
||||
(set cam-y ground-y)
|
||||
(set velocity-y 0)
|
||||
(set grounded? true))
|
||||
|
||||
(when (< land-squash 0)
|
||||
(set land-squash (math.min 0 (+ land-squash (* land-recovery-speed dt)))))
|
||||
|
||||
(if (and moving grounded?)
|
||||
(set bob-time (+ bob-time (* dt bob-speed)))
|
||||
(let [target-phase (* (math.floor (/ bob-time math.pi)) math.pi)]
|
||||
(set bob-time (+ (* bob-time 0.8) (* target-phase 0.2))))))))
|
||||
|
||||
(fn frame []
|
||||
(pxl8.clear 0)
|
||||
|
||||
(when (not camera)
|
||||
(pxl8.error "camera is nil!"))
|
||||
|
||||
(when (not world)
|
||||
(pxl8.error "world is nil!"))
|
||||
|
||||
(when (and world (not (world:is_loaded)))
|
||||
(pxl8.text "World not loaded yet..." 5 30 12))
|
||||
|
||||
(when (and camera world (world:is_loaded))
|
||||
(let [bob-offset (* (math.sin bob-time) bob-amount)
|
||||
eye-y (+ cam-y bob-offset land-squash)
|
||||
forward-x (- (math.sin cam-yaw))
|
||||
forward-z (- (math.cos cam-yaw))
|
||||
target-x (+ smooth-cam-x forward-x)
|
||||
target-y (+ eye-y (math.sin cam-pitch))
|
||||
target-z (+ smooth-cam-z forward-z)
|
||||
aspect (/ (pxl8.get_width) (pxl8.get_height))]
|
||||
|
||||
(camera:lookat [smooth-cam-x eye-y smooth-cam-z]
|
||||
[target-x target-y target-z]
|
||||
[0 1 0])
|
||||
(camera:set_perspective 1.047 aspect 1.0 4096.0)
|
||||
|
||||
(pxl8.begin_frame_3d camera)
|
||||
(pxl8.clear_depth)
|
||||
|
||||
(world:render [smooth-cam-x eye-y smooth-cam-z])
|
||||
|
||||
(pxl8.end_frame_3d)
|
||||
|
||||
(let [cx (/ (pxl8.get_width) 2)
|
||||
cy (/ (pxl8.get_height) 2)
|
||||
crosshair-size 4
|
||||
red-color 18]
|
||||
(pxl8.line (- cx crosshair-size) cy (+ cx crosshair-size) cy red-color)
|
||||
(pxl8.line cx (- cy crosshair-size) cx (+ cy crosshair-size) red-color))
|
||||
|
||||
(pxl8.text (.. "fps: " (string.format "%.1f" (pxl8.get_fps))) 5 5 12)
|
||||
(pxl8.text (.. "pos: " (string.format "%.0f" cam-x) ","
|
||||
(string.format "%.0f" cam-y) ","
|
||||
(string.format "%.0f" cam-z)) 5 15 12))))
|
||||
|
||||
{:init init
|
||||
:update update
|
||||
:frame frame}
|
||||
Loading…
Add table
Add a link
Reference in a new issue