(local pxl8 (require :pxl8)) (local bit (require :bit)) (local effects (require :pxl8.effects)) (local net (require :pxl8.net)) (local entities (require :mod.entities)) (local menu (require :mod.menu)) (local sky (require :mod.sky)) (local textures (require :mod.textures)) (local bob-amount 4.0) (local bob-speed 8.0) (local cam-smoothing 0.25) (local land-recovery-speed 20) (local land-squash-amount -4) (local player-eye-height 64) (local day-length 1800) (local SIM_FLAG_GROUNDED 4) (local sim-cfg (pxl8.sim_config {:move_speed 150 :gravity 600 :jump_velocity 180 :player_radius 12 :player_height 72 :max_pitch 1.5 :friction 6.0 :ground_accel 10.0 :air_accel 1.0 :stop_speed 100.0})) (var auto-run-cancel-key nil) (var auto-run? false) (var was-auto-running false) (var bob-time 0) (var cam-pitch 0) (var day-time 0) (var cam-x 416) (var cam-y 0) (var cam-yaw 0) (var cam-z 416) (var camera nil) (var ceiling-tex nil) (var current-bsp-id 1) (var floor-tex nil) (var land-squash 0) (var last-dt 0.016) (var light-time 0) (var glows nil) (var lights nil) (var bsp-materials-setup false) (var network nil) (var portal-cooldown 0) (var real-time 0) (var smooth-cam-x 416) (var smooth-cam-z 416) (var was-grounded true) (var trim-tex nil) (var wall-tex nil) (var world nil) (local MOSS_COLOR 200) (local PLASTER_COLOR 16) (local STONE_WALL_START 2) (local WOOD_COLOR 88) (local ASHLAR_COLOR 64) (local ASHLAR_MOSS 68) (local STONE_FLOOR_COLOR 72) (local STONE_TRIM_COLOR 72) (fn preload [] (when (not network) (set network (net.get)) (when network (network:spawn cam-x cam-y cam-z cam-yaw cam-pitch))) (when (not world) (set world (pxl8.get_world)) (when world (world:set_sim_config sim-cfg) (world:init_local_player cam-x cam-y cam-z)))) (fn is-connected [] (and network (network:connected))) (fn is-ready [] (if (not world) false (let [chunk (world:active_chunk)] (and chunk (chunk:ready))))) (fn setup-textures [bsp-id] (if (= bsp-id 2) (do (set floor-tex (textures.rough-stone 44442 STONE_FLOOR_COLOR)) (set wall-tex (textures.ashlar-wall 55552 ASHLAR_COLOR ASHLAR_MOSS)) (set trim-tex (textures.rough-stone 77772 STONE_TRIM_COLOR)) (set ceiling-tex (textures.plaster-wall 66662 PLASTER_COLOR))) (do (set floor-tex (textures.wood-planks 44444 WOOD_COLOR)) (set wall-tex (textures.cobble-timber 55555 STONE_WALL_START MOSS_COLOR WOOD_COLOR)) (set trim-tex (textures.wood-trim 77777 WOOD_COLOR)) (set ceiling-tex (textures.plaster-wall 66666 PLASTER_COLOR)))) (set current-bsp-id bsp-id)) (fn init [] (pxl8.set_relative_mouse_mode true) (pxl8.load_palette "res/palettes/palette.ase") (for [i 0 7] (let [t (/ i 7) r 0xFF g (math.floor (+ 0x60 (* t (- 0xE0 0x60)))) b (math.floor (+ 0x10 (* t (- 0x80 0x10))))] (pxl8.set_palette_rgb (+ entities.FIREBALL_COLOR i) r g b))) (pxl8.set_palette_rgb (- entities.FIREBALL_COLOR 1) 0xFF 0x20 0x10) (sky.reset-gradient) (sky.update-gradient 1 2 6 6 10 18) (pxl8.update_palette_deps) (when (not camera) (set camera (pxl8.create_camera_3d))) (when (not glows) (set glows (pxl8.create_glows))) (when (not lights) (set lights (pxl8.create_lights))) (entities.init textures) (sky.generate-stars) (preload) (when world (world:init_local_player cam-x cam-y cam-z) (set smooth-cam-x cam-x) (set smooth-cam-z cam-z)) (setup-textures 1)) (fn setup-materials [] (when (and world (not bsp-materials-setup) floor-tex trim-tex wall-tex) (let [chunk (world:active_chunk)] (when (and chunk (chunk:ready)) (let [floor-mat (pxl8.create_material {:texture floor-tex :lighting true :double_sided true}) trim-mat (pxl8.create_material {:texture trim-tex :lighting true :double_sided true}) wall-mat (pxl8.create_material {:texture wall-tex :lighting true :double_sided true})] (world:set_bsp_material 0 floor-mat) (world:set_bsp_material 1 wall-mat) (world:set_bsp_material 3 trim-mat) (entities.setup-lighting (chunk:bsp) 2) (set bsp-materials-setup true)))))) (fn sample-input [] (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)) (set was-auto-running auto-run?) (pxl8.make_input_msg {:move_x (+ (if (pxl8.key_down "d") 1 0) (if (pxl8.key_down "a") -1 0)) :move_y (+ (if (or (pxl8.key_down "w") auto-run?) 1 0) (if (and (pxl8.key_down "s") (not= auto-run-cancel-key "s")) -1 0)) :look_dx (pxl8.mouse_dx) :look_dy (pxl8.mouse_dy) :buttons (if (pxl8.key_down "space") 1 0)})) (fn update [dt] (set last-dt dt) (setup-materials) (when (> portal-cooldown 0) (set portal-cooldown (- portal-cooldown dt))) (when (and world network (<= portal-cooldown 0)) (let [(door-x door-z) (entities.get-door-position) door-radius (entities.get-door-radius) dist-to-door (math.sqrt (+ (* (- cam-x door-x) (- cam-x door-x)) (* (- cam-z door-z) (- cam-z door-z))))] (when (< dist-to-door door-radius) (let [current-id (network:chunk_id)] (if (= current-id 1) (do (pxl8.info "Door: BSP 1 -> BSP 2") (network:enter_scene 1 2 416 0 416) (world:init_local_player 416 0 416) (set cam-x 416) (set cam-y 0) (set cam-z 416) (set smooth-cam-x 416) (set smooth-cam-z 416) (set bsp-materials-setup false) (setup-textures 2) (set portal-cooldown 2.0)) (= current-id 2) (do (pxl8.info "Door: BSP 2 -> BSP 1") (network:enter_scene 1 1 416 0 416) (world:init_local_player 416 0 416) (set cam-x 416) (set cam-y 0) (set cam-z 416) (set smooth-cam-x 416) (set smooth-cam-z 416) (set bsp-materials-setup false) (setup-textures 1) (set portal-cooldown 2.0))))))) (when world (let [input-msg (sample-input) player (world:local_player)] (world:push_input input-msg) (when player (set cam-x player.pos.x) (set cam-y player.pos.y) (set cam-z player.pos.z) (set cam-yaw player.yaw) (set cam-pitch player.pitch)) (let [now-grounded (if player (not= (bit.band player.flags SIM_FLAG_GROUNDED) 0) true)] (when (and (not was-grounded) now-grounded) (set land-squash land-squash-amount)) (set was-grounded now-grounded)) (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 (< land-squash 0) (set land-squash (math.min 0 (+ land-squash (* land-recovery-speed dt))))) (let [moving (or (not= input-msg.move_x 0) (not= input-msg.move_y 0))] (if (and moving was-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 day-time (% (+ day-time (/ dt day-length)) 1)) (set light-time (+ light-time (* dt 0.5))) (set real-time (+ real-time dt))))) (fn frame [] (pxl8.clear 1) (when (or (not camera) (not world)) (lua "return")) (let [chunk (when world (world:active_chunk)) ready (and chunk (chunk:ready))] (when ready (let [bob-offset (* (math.sin bob-time) bob-amount) eye-y (+ cam-y player-eye-height 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-x (+ 384 (* 50 (math.cos light-time))) light-z (+ 324 (* 50 (math.sin light-time))) light-y 80 phase (+ (* light-x 0.01) 1.7) f1 (* 0.08 (math.sin (+ (* real-time 2.5) phase))) f2 (* 0.05 (math.sin (+ (* real-time 4.1) (* phase 0.7)))) f3 (* 0.03 (math.sin (+ (* real-time 7.3) (* phase 1.2)))) flicker (+ 0.92 f1 f2 f3) light-intensity (math.floor (math.max 0 (math.min 255 (* 255 flicker)))) r1 (* 0.06 (math.sin (+ (* real-time 1.8) (* phase 0.5)))) r2 (* 0.04 (math.sin (+ (* real-time 3.2) phase))) light-radius (* 150 (+ 0.95 r1 r2))] (lights:clear) (lights:add light-x light-y light-z 2 light-intensity light-radius) (pxl8.push_target) (pxl8.begin_frame_3d camera lights { :ambient 2 :dither true :fog_density 0.002 :celestial_dir [0.5 -0.8 0.3] :celestial_intensity 0.3}) (when (not (menu.is-wireframe)) (sky.update-gradient 1 2 6 6 10 18)) (sky.render smooth-cam-x eye-y smooth-cam-z (menu.is-wireframe)) (pxl8.clear_depth) (pxl8.set_wireframe (menu.is-wireframe)) (world:render [smooth-cam-x eye-y smooth-cam-z]) (when chunk (entities.render-fireball light-x light-y light-z (menu.is-wireframe))) (entities.render-door (menu.is-wireframe) 0) (pxl8.end_frame_3d) (when (not (menu.is-wireframe)) (sky.render-stars smooth-cam-x eye-y smooth-cam-z day-time 0 last-dt)) (pxl8.pop_target)) (pxl8.push_target) (let [cx (/ (pxl8.get_width) 2) cy (/ (pxl8.get_height) 2) crosshair-size 4 crosshair-color 240] (pxl8.line (- cx crosshair-size) cy (+ cx crosshair-size) cy crosshair-color) (pxl8.line cx (- cy crosshair-size) cx (+ cy crosshair-size) crosshair-color)) (pxl8.pop_target))))) {:preload preload :is-connected is-connected :is-ready is-ready :init init :update update :frame frame}