switch repo to just cleaning game focus
This commit is contained in:
parent
276c7c562b
commit
6d5406c6c5
49 changed files with 0 additions and 150 deletions
9
game/src/assets.fnl
Normal file
9
game/src/assets.fnl
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
(local assets {})
|
||||
|
||||
(love.graphics.setDefaultFilter "nearest" "nearest")
|
||||
(set assets.objects-sprite (love.graphics.newImage "assets/objects.png"))
|
||||
(set assets.walls-sprite (love.graphics.newImage "assets/walls.png"))
|
||||
(set assets.battery-bar-sprite (love.graphics.newImage "assets/battery_bar.png"))
|
||||
(set assets.player-sprite (love.graphics.newImage "assets/player.png"))
|
||||
|
||||
assets
|
||||
32
game/src/colors.fnl
Normal file
32
game/src/colors.fnl
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
(local utils (require "src/utils.fnl"))
|
||||
|
||||
;; colors
|
||||
(lambda color [full-r full-g full-b]
|
||||
(let [(r g b) (love.math.colorFromBytes full-r full-g full-b)]
|
||||
[r g b]
|
||||
))
|
||||
|
||||
(local colors {
|
||||
:cream (color 255 238 204)
|
||||
:dark-purple (color 70 66 94)
|
||||
:dark-pink (color 255 105 115)
|
||||
:dark-blue (color 21 120 140)
|
||||
:light-blue (color 0 185 190)
|
||||
:light-pink (color 255 176 163)
|
||||
:black [0 0 0]
|
||||
:black-half-tone [0 0 0 0.25]
|
||||
})
|
||||
|
||||
(fn reset-color []
|
||||
"reset color to white (no tinting)"
|
||||
(love.graphics.setColor 1 1 1))
|
||||
|
||||
(lambda set-color [color-name]
|
||||
"set color to the given color from the color pallet"
|
||||
(love.graphics.setColor (unpack (. colors color-name))))
|
||||
|
||||
{
|
||||
: reset-color
|
||||
: set-color
|
||||
: colors
|
||||
}
|
||||
38
game/src/entities/info-pad.fnl
Normal file
38
game/src/entities/info-pad.fnl
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
(local utils (require "src/utils.fnl"))
|
||||
(local beholder (require "libs/beholder"))
|
||||
(local color (require "src/colors.fnl"))
|
||||
(local levels (require "levels.fnl"))
|
||||
(local assets (require "src/assets.fnl"))
|
||||
|
||||
(lambda info-pad [obj]
|
||||
(let [
|
||||
x obj.x
|
||||
y obj.y
|
||||
content obj.content
|
||||
pad {: x : y : content :hitbox [x y 25 25]}
|
||||
(w h) (assets.objects-sprite:getDimensions)]
|
||||
(lambda pad.load [self]
|
||||
(set self.quad (love.graphics.newQuad 75 0 25 25 w h)))
|
||||
|
||||
(lambda pad.on-hit [self]
|
||||
(beholder.trigger "NOTIFICATION" self.content))
|
||||
|
||||
(fn pad.draw-debug [self]
|
||||
(color.set-color :black)
|
||||
(love.graphics.rectangle "line" self.x self.y 25 25))
|
||||
|
||||
(lambda pad.draw49 [self]
|
||||
(color.reset-color)
|
||||
(love.graphics.draw assets.objects-sprite self.quad self.x self.y))
|
||||
pad
|
||||
|
||||
|
||||
))
|
||||
|
||||
|
||||
info-pad
|
||||
|
||||
; (lambda [{:bump-world bw :level-key key}]
|
||||
; (set bump-world bw)
|
||||
; (set level-key key)
|
||||
; player)
|
||||
117
game/src/entities/player.fnl
Normal file
117
game/src/entities/player.fnl
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
(local utils (require "src/utils.fnl"))
|
||||
(local beholder (require "libs/beholder"))
|
||||
(local color (require "src/colors.fnl"))
|
||||
(local levels (require "levels.fnl"))
|
||||
(local assets (require "src/assets.fnl"))
|
||||
|
||||
(var bump-world nil)
|
||||
(var level-key nil)
|
||||
|
||||
(lambda bump-filter [item other]
|
||||
(if (= other.behavior "block") :slide :cross))
|
||||
|
||||
(lambda angle-to-direction [angle]
|
||||
"Convert angle (radians) to compass direction keyword"
|
||||
(local tau (* 2 math.pi))
|
||||
; Normalize angle to 0-2π range
|
||||
(local normalized (% (+ angle tau) tau))
|
||||
; Offset by 22.5° (π/8) so section boundaries align with directions
|
||||
(local offset (+ normalized (/ math.pi 8)))
|
||||
; Find which 45° section (π/4) it falls into
|
||||
(local section (math.floor (/ offset (/ math.pi 4))))
|
||||
; Map to compass directions
|
||||
(local directions [:e :se :s :sw :w :nw :n :ne])
|
||||
(. directions (+ (% section 8) 1)))
|
||||
|
||||
|
||||
(local width 19)
|
||||
(local height 15)
|
||||
(local player {
|
||||
:x 50 :y 50 :w 25 :h 25 :speed 80 :battery 100 :rot 0
|
||||
:hitbox [50 50 width height]
|
||||
:init-move false ; nudge the player at start of game to trigger starting collisions
|
||||
})
|
||||
|
||||
|
||||
(lambda handle-collisions [cols]
|
||||
(each [_ col (pairs cols)]
|
||||
(when col.other.on-hit (col.other:on-hit))
|
||||
(beholder.trigger "PLAYER.HIT" col.other)))
|
||||
|
||||
(fn player.update [self dt]
|
||||
(when (= self.init-move false)
|
||||
(set self.init-move true)
|
||||
(let [(x y cols len) (bump-world:move self self.x self.y bump-filter)]
|
||||
(handle-collisions cols)))
|
||||
(let [
|
||||
d-key (love.keyboard.isDown :d)
|
||||
a-key (love.keyboard.isDown :a)
|
||||
e-key (love.keyboard.isDown :e)
|
||||
q-key (love.keyboard.isDown :q)]
|
||||
(match {:d-key d-key :a-key a-key :e-key e-key :q-key q-key}
|
||||
{:d-key true :a-key false :e-key false :q-key false} (set self.rot (+ self.rot (* dt 2)))
|
||||
{:d-key false :a-key true :e-key false :q-key false} (set self.rot (- self.rot (* dt 2)))
|
||||
{:d-key false :a-key false :e-key true :q-key false} (set self.rot (- self.rot (* dt 2)))
|
||||
{:d-key false :a-key false :e-key false :q-key true} (set self.rot (+ self.rot (* dt 2)))
|
||||
)
|
||||
(when (and (> self.battery 0) (or d-key a-key e-key q-key))
|
||||
(let [
|
||||
dir-fn (if (or d-key a-key) #(+ $1 $2) #(- $1 $2))
|
||||
new-x (dir-fn self.x (* self.speed dt (math.cos self.rot)))
|
||||
new-y (dir-fn self.y (* self.speed dt (math.sin self.rot)))
|
||||
(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))
|
||||
(if (> self.battery 0)
|
||||
(set self.battery (- self.battery (* dt 2))))))
|
||||
(beholder.trigger "PLAYER.POS" self.x self.y)
|
||||
(beholder.trigger "PLAYER.BATTERY" self.battery))
|
||||
|
||||
(fn player.load [self]
|
||||
(set self.battery 100)
|
||||
(let [
|
||||
spawn-x (-> (. levels :levels level-key :spawns :player-1 :x) (- (/ width 2)))
|
||||
spawn-y (-> (. levels :levels level-key :spawns :player-1 :y) (- (/ height 2)))
|
||||
(x y cols len) (bump-world:move self spawn-x spawn-y bump-filter)]
|
||||
(set self.x x)
|
||||
(set self.y y))
|
||||
(set self.quads
|
||||
(let [
|
||||
(w h) (assets.player-sprite:getDimensions)]
|
||||
{
|
||||
:n (love.graphics.newQuad 0 0 25 25 w h)
|
||||
:s (love.graphics.newQuad 25 0 25 25 w h)
|
||||
:ne (love.graphics.newQuad 50 0 25 25 w h)
|
||||
:e (love.graphics.newQuad 75 0 25 25 w h)
|
||||
:se (love.graphics.newQuad 100 0 25 25 w h)
|
||||
:sw (love.graphics.newQuad 125 0 25 25 w h)
|
||||
:w (love.graphics.newQuad 150 0 25 25 w h)
|
||||
:nw (love.graphics.newQuad 175 0 25 25 w h)
|
||||
})))
|
||||
|
||||
(fn player.draw50 [self]
|
||||
"draw player sprite and hitbox"
|
||||
(color:reset-color)
|
||||
(love.graphics.draw
|
||||
assets.player-sprite
|
||||
(. self.quads (angle-to-direction player.rot))
|
||||
(- self.x 3) (- self.y 7)))
|
||||
|
||||
(fn player.draw-debug [self]
|
||||
"draw player hitbox and direction line"
|
||||
(color.set-color :black)
|
||||
(love.graphics.rectangle "line" self.x self.y width height)
|
||||
(love.graphics.rectangle "line" self.x self.y 1 1)
|
||||
(love.graphics.push)
|
||||
(let [ox (+ self.x (/ width 2)) oy (+ self.y (/ height 2))]
|
||||
(love.graphics.translate ox oy)
|
||||
(love.graphics.rotate self.rot)
|
||||
(love.graphics.line 0 0 35 0))
|
||||
(love.graphics.pop))
|
||||
|
||||
|
||||
(lambda [{:bump-world bw :level-key key}]
|
||||
(set bump-world bw)
|
||||
(set level-key key)
|
||||
player)
|
||||
72
game/src/levels/dev.fnl
Normal file
72
game/src/levels/dev.fnl
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
(local bump (require "libs/bump"))
|
||||
(local color (require "src/colors.fnl"))
|
||||
(local nata (require "libs/nata"))
|
||||
(local utils (require "src/utils.fnl"))
|
||||
(local camera (require "src/systems/camera.fnl"))
|
||||
(local beholder (require "libs/beholder"))
|
||||
(local player (require "src/entities/player.fnl"))
|
||||
(local walls (require "src/systems/walls.fnl"))
|
||||
(local hud (require "src/systems/hud.fnl"))
|
||||
(local levels (require "levels.fnl"))
|
||||
(local info-pad (require "src/entities/info-pad.fnl"))
|
||||
|
||||
(lambda load-objects [level-key pool]
|
||||
(each [_ object (pairs (. levels :levels level-key :objects))]
|
||||
; (debug-print object)
|
||||
(case object.type
|
||||
"info_pad" (pool:queue (info-pad object))
|
||||
))
|
||||
)
|
||||
|
||||
(lambda collider-manager [bump-world]
|
||||
(local collider-manager {})
|
||||
(lambda collider-manager.addToGroup [self group-name entity]
|
||||
(when (= group-name :hitbox)
|
||||
; (utils.debug-print {:adding entity})
|
||||
(bump-world:add entity (unpack entity.hitbox))))
|
||||
collider-manager)
|
||||
|
||||
; (lambda register-notifications []
|
||||
; (beholder.observe "PLAYER.HIT" (lambda [other]
|
||||
; (when (= other.object-type :info-pad)
|
||||
; (beholder.trigger "NOTIFICATION" "[a] is left wheel forward [d] is right wheel forward"))
|
||||
; (utils.debug-print {: other}))))
|
||||
; (beholder.observe "PLAYER.HIT" :info-pad (lambda [info-pad-name]
|
||||
; (case info-pad-name
|
||||
; :controls (beholder.trigger "NOTIFICATION" "[a] is left wheel forward [d] is right wheel forward")
|
||||
; ))))
|
||||
|
||||
|
||||
(fn load [screen]
|
||||
; (register-notifications)
|
||||
(let [
|
||||
canvas (love.graphics.newCanvas screen.canvas-w screen.canvas-h)
|
||||
level-key :dev
|
||||
bump-world (bump.newWorld 25)
|
||||
pool (nata.new {
|
||||
:data {
|
||||
: screen
|
||||
: canvas
|
||||
: bump-world
|
||||
: level-key
|
||||
}
|
||||
:groups {
|
||||
; gravity = {filter = {'gravity'}},
|
||||
:hitbox {:filter [:hitbox]}
|
||||
; :post-draw {:filter [:post-draw]}
|
||||
}
|
||||
:systems [
|
||||
(nata:oop)
|
||||
(collider-manager bump-world)
|
||||
camera
|
||||
walls
|
||||
(hud {: screen})
|
||||
]
|
||||
})]
|
||||
(pool:queue (player {: bump-world : level-key}))
|
||||
(load-objects level-key pool)
|
||||
pool))
|
||||
|
||||
{
|
||||
: load
|
||||
}
|
||||
71
game/src/levels/tutorial.fnl
Normal file
71
game/src/levels/tutorial.fnl
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
(local bump (require "libs/bump"))
|
||||
(local color (require "src/colors.fnl"))
|
||||
(local nata (require "libs/nata"))
|
||||
(local utils (require "src/utils.fnl"))
|
||||
(local camera (require "src/systems/camera.fnl"))
|
||||
(local beholder (require "libs/beholder"))
|
||||
(local player (require "src/entities/player.fnl"))
|
||||
(local walls (require "src/systems/walls.fnl"))
|
||||
(local hud (require "src/systems/hud.fnl"))
|
||||
(local levels (require "levels.fnl"))
|
||||
(local info-pad (require "src/entities/info-pad.fnl"))
|
||||
|
||||
(lambda load-objects [level-key pool]
|
||||
(each [_ object (pairs (. levels :levels level-key :objects))]
|
||||
; (debug-print object)
|
||||
(case object.type
|
||||
"info_pad" (pool:queue (info-pad object.x object.y object.name))
|
||||
))
|
||||
)
|
||||
|
||||
(lambda collider-manager [bump-world]
|
||||
(local collider-manager {})
|
||||
(lambda collider-manager.addToGroup [self group-name entity]
|
||||
(when (= group-name :hitbox)
|
||||
; (utils.debug-print {:adding entity})
|
||||
(bump-world:add entity (unpack entity.hitbox))))
|
||||
collider-manager)
|
||||
|
||||
(lambda register-notifications []
|
||||
(beholder.observe "PLAYER.HIT" (lambda [other]
|
||||
(when (= other.object-type :info-pad)
|
||||
(beholder.trigger "NOTIFICATION" "[a] is left wheel forward [d] is right wheel forward"))
|
||||
(utils.debug-print {: other}))))
|
||||
; (beholder.observe "PLAYER.HIT" :info-pad (lambda [info-pad-name]
|
||||
; (case info-pad-name
|
||||
; :controls (beholder.trigger "NOTIFICATION" "[a] is left wheel forward [d] is right wheel forward")
|
||||
; ))))
|
||||
|
||||
|
||||
(fn load [screen]
|
||||
(register-notifications)
|
||||
(let [
|
||||
canvas (love.graphics.newCanvas screen.canvas-w screen.canvas-h)
|
||||
bump-world (bump.newWorld 25)
|
||||
pool (nata.new {
|
||||
:data {
|
||||
: screen
|
||||
: canvas
|
||||
: bump-world
|
||||
:level-key :tutorial
|
||||
}
|
||||
:groups {
|
||||
; gravity = {filter = {'gravity'}},
|
||||
:hitbox {:filter [:hitbox]}
|
||||
; :post-draw {:filter [:post-draw]}
|
||||
}
|
||||
:systems [
|
||||
(nata:oop)
|
||||
(collider-manager bump-world)
|
||||
camera
|
||||
walls
|
||||
(hud {: screen})
|
||||
]
|
||||
})]
|
||||
(pool:queue (player {:bump-world bump-world :level-key :tutorial}))
|
||||
(load-objects :tutorial pool)
|
||||
pool))
|
||||
|
||||
{
|
||||
: load
|
||||
}
|
||||
133
game/src/network.fnl
Normal file
133
game/src/network.fnl
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
(local socket (require "socket"))
|
||||
|
||||
;; Guide: https://www.love2d.org/wiki/Tutorial:Networking_with_UDP
|
||||
|
||||
;; Configuration
|
||||
(local config {
|
||||
:host "localhost"
|
||||
:port 9999
|
||||
})
|
||||
|
||||
;; Network state
|
||||
(local state {
|
||||
:socket nil
|
||||
:connected false
|
||||
; :player-id nil
|
||||
; :last-error nil
|
||||
})
|
||||
|
||||
;; Callback functions for network events
|
||||
; (local callbacks {
|
||||
; :on-ready (fn [])
|
||||
; :on-wait (fn [])
|
||||
; :on-opponent-update (fn [data])
|
||||
; :on-error (fn [error])
|
||||
; })
|
||||
|
||||
(fn init []
|
||||
"Initialize UDP connection to server
|
||||
Returns true on success, false on error"
|
||||
(let [udp (socket.udp)]
|
||||
(udp:setpeername config.host config.port)
|
||||
(udp:settimeout 0) ; non-blocking
|
||||
|
||||
(set state.socket udp)
|
||||
(set state.connected true)))
|
||||
|
||||
(fn send-msg [dg]
|
||||
(state.socket:send dg))
|
||||
|
||||
(fn update [dt]
|
||||
(let [(data msg) (state.socket:receive)]
|
||||
(when data
|
||||
(print (fennel.view {: data : msg})))))
|
||||
|
||||
; (fn register []
|
||||
; "Send REGISTER message to server"
|
||||
; (when state.socket
|
||||
; (try
|
||||
; (state.socket:send "REGISTER")
|
||||
; (catch err
|
||||
; (set state.last-error err)
|
||||
; (when callbacks.on-error (callbacks.on-error err))))))
|
||||
|
||||
; (fn split-string [str delimiter]
|
||||
; "Split string by delimiter into table"
|
||||
; (local result [])
|
||||
; (local current "")
|
||||
; (each [i 1 (length str) 1]
|
||||
; (let [char (string.sub str i i)]
|
||||
; (if (= char delimiter)
|
||||
; (do
|
||||
; (table.insert result current)
|
||||
; (set current ""))
|
||||
; (set current (.. current char)))))
|
||||
; (table.insert result current)
|
||||
; result)
|
||||
|
||||
; (fn parse-message [msg]
|
||||
; "Parse message in format: COMMAND#arg1#arg2#..."
|
||||
; (split-string msg "#"))
|
||||
|
||||
; (fn send-update [x y rotation battery]
|
||||
; "Send player state to server in format: UPDATE#x#y#rotation#battery"
|
||||
; (when state.socket
|
||||
; (try
|
||||
; (let [msg (.. "UPDATE#" x "#" y "#" rotation "#" battery)]
|
||||
; (state.socket:send msg))
|
||||
; (catch err
|
||||
; (set state.last-error err)))))
|
||||
|
||||
; (fn update [dt]
|
||||
; "Call from love.update to process incoming messages"
|
||||
; (when state.socket
|
||||
; (let [(msg _src-ip _src-port) (state.socket:receivefrom)]
|
||||
; (when msg
|
||||
; (let [parts (parse-message msg)
|
||||
; command (. parts 1)]
|
||||
; (match command
|
||||
; "READY_TO_PLAY" (callbacks.on-ready)
|
||||
; "WAIT" (callbacks.on-wait)
|
||||
; "UPDATE" (callbacks.on-opponent-update {
|
||||
; :x (tonumber (. parts 2))
|
||||
; :y (tonumber (. parts 3))
|
||||
; :rotation (tonumber (. parts 4))
|
||||
; :battery (tonumber (. parts 5))
|
||||
; })
|
||||
; _ (print (.. "← Message: " msg))))))))
|
||||
|
||||
; (fn set-callback [event cb]
|
||||
; "Register callback for network events
|
||||
; Available events: :on-ready :on-wait :on-opponent-update :on-error"
|
||||
; (tset callbacks event cb))
|
||||
|
||||
(fn close []
|
||||
"Close network connection"
|
||||
(when state.socket
|
||||
(state.socket:close)
|
||||
(set state.socket nil)
|
||||
(set state.connected false)))
|
||||
|
||||
; (fn is-connected []
|
||||
; "Check if currently connected to server"
|
||||
; state.connected)
|
||||
|
||||
; (fn get-last-error []
|
||||
; "Get the last error that occurred"
|
||||
; state.last-error)
|
||||
|
||||
;; Export public API
|
||||
{
|
||||
: init
|
||||
: update
|
||||
: state
|
||||
: send-msg
|
||||
: close
|
||||
; :register register
|
||||
; :send-update send-update
|
||||
; :update update
|
||||
; :set-callback set-callback
|
||||
; :close close
|
||||
; :is-connected is-connected
|
||||
; :get-last-error get-last-error
|
||||
}
|
||||
37
game/src/systems/camera.fnl
Normal file
37
game/src/systems/camera.fnl
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
(local beholder (require "libs/beholder"))
|
||||
(local color (require "src/colors.fnl"))
|
||||
|
||||
;; Camera System
|
||||
|
||||
(local camera {:x 0 :y 0})
|
||||
|
||||
(fn camera.draw2 [self]
|
||||
(love.graphics.push)
|
||||
(love.graphics.translate (* -1 self.x) (* -1 self.y)))
|
||||
|
||||
(fn camera.load [self]
|
||||
(let [screen self.pool.data.screen]
|
||||
(beholder.observe "PLAYER.POS" (lambda [x y]
|
||||
;; Update camera to follow player (keep player centered on screen)
|
||||
(set self.x (- x (/ screen.canvas-w 2)))
|
||||
(set self.y (- y (/ screen.canvas-h 2)))))))
|
||||
|
||||
(fn camera.draw89 [self]
|
||||
(love.graphics.pop)) ; undo camera translation
|
||||
|
||||
(fn camera.draw99 [self]
|
||||
(let [screen self.pool.data.screen canvas self.pool.data.canvas]
|
||||
(love.graphics.setCanvas) ; reset to root canvas
|
||||
(color:reset-color)
|
||||
(love.graphics.draw canvas 0 0 0 screen.scale screen.scale)))
|
||||
|
||||
(fn camera.draw1 [self]
|
||||
(let [screen self.pool.data.screen canvas self.pool.data.canvas]
|
||||
; use canvas
|
||||
(love.graphics.setCanvas canvas)
|
||||
; clear the screen
|
||||
(love.graphics.clear)
|
||||
(color.set-color :cream)
|
||||
(love.graphics.rectangle "fill" 0 0 screen.canvas-w screen.canvas-h)))
|
||||
|
||||
camera
|
||||
88
game/src/systems/hud.fnl
Normal file
88
game/src/systems/hud.fnl
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
(local beholder (require "libs/beholder"))
|
||||
(local assets (require "src/assets.fnl"))
|
||||
(local color (require "src/colors.fnl"))
|
||||
|
||||
(var screen nil)
|
||||
(local hud {
|
||||
:player-battery 0
|
||||
:notification nil
|
||||
:notification-life 0
|
||||
})
|
||||
|
||||
(lambda draw-notification [self]
|
||||
(when (and self.notification (> self.notification-life 0))
|
||||
(love.graphics.push)
|
||||
(love.graphics.translate 0 (- 400 20))
|
||||
(color.set-color :cream)
|
||||
(love.graphics.rectangle "fill" 0 0 screen.canvas-w 20)
|
||||
(color.set-color :dark-purple)
|
||||
(color.set-color :dark-purple)
|
||||
(love.graphics.line 0 0 screen.canvas-w 0)
|
||||
(love.graphics.setFont self.font)
|
||||
(love.graphics.print self.notification 3 3)
|
||||
(love.graphics.pop)))
|
||||
|
||||
(fn hud.load [self]
|
||||
(set self.font (love.graphics.newFont 10))
|
||||
(set self.font-small (love.graphics.newFont 6))
|
||||
|
||||
(beholder.observe "PLAYER.BATTERY" (lambda [bat]
|
||||
(set self.player-battery bat)))
|
||||
|
||||
(beholder.observe "NOTIFICATION" (lambda [text]
|
||||
(set self.notification text)
|
||||
; set life of notification to 5 seconds
|
||||
(set self.notification-life 5))))
|
||||
|
||||
|
||||
(lambda hud.update [self dt]
|
||||
(when (> self.notification-life 0)
|
||||
(set self.notification-life (- self.notification-life dt))))
|
||||
|
||||
(lambda draw-header [self]
|
||||
(color.set-color :cream)
|
||||
(love.graphics.rectangle "fill" 0 0 screen.canvas-w 20)
|
||||
(color.set-color :dark-purple)
|
||||
(love.graphics.line 0 20 screen.canvas-w 20))
|
||||
|
||||
(lambda draw-side-walls [self]
|
||||
(color.set-color :cream)
|
||||
(love.graphics.rectangle "fill" 0 0 20 screen.canvas-h)
|
||||
(love.graphics.rectangle "fill" (- screen.canvas-w 20) 0 20 screen.canvas-h)
|
||||
(color.set-color :dark-purple)
|
||||
(love.graphics.line 20 0 20 screen.canvas-w)
|
||||
(love.graphics.line (- screen.canvas-w 20) 0 (- screen.canvas-w 20) screen.canvas-w))
|
||||
|
||||
(lambda draw-footer [self]
|
||||
(love.graphics.push)
|
||||
(love.graphics.translate 0 400)
|
||||
(color.set-color :cream)
|
||||
(love.graphics.rectangle "fill" 0 0 screen.canvas-w 100)
|
||||
(color.reset-color)
|
||||
(love.graphics.draw assets.battery-bar-sprite 78 8)
|
||||
(color.set-color :dark-purple)
|
||||
(love.graphics.setFont self.font)
|
||||
(love.graphics.print (.. "Battery: " (string.format "%d" self.player-battery) "%") 6 7)
|
||||
(color.set-color :light-blue)
|
||||
(love.graphics.rectangle "fill" 80 12 (* 152 (/ self.player-battery 100)) 4)
|
||||
(love.graphics.setFont self.font-small)
|
||||
(color.set-color :dark-purple)
|
||||
(love.graphics.print "100%" 229 2)
|
||||
(color.set-color :light-pink)
|
||||
(love.graphics.print "125%" 267 2)
|
||||
(love.graphics.print "125%" 306 2)
|
||||
(love.graphics.print "150%" 345 2)
|
||||
(love.graphics.print "200%" 382 2)
|
||||
(color.set-color :dark-purple)
|
||||
(love.graphics.line 0 0 screen.canvas-w 0)
|
||||
(love.graphics.pop))
|
||||
|
||||
(fn hud.draw90 [self]
|
||||
(draw-side-walls self)
|
||||
(draw-footer self)
|
||||
(draw-header self)
|
||||
(draw-notification self))
|
||||
|
||||
(lambda [{:screen s}]
|
||||
(set screen s)
|
||||
hud)
|
||||
58
game/src/systems/walls.fnl
Normal file
58
game/src/systems/walls.fnl
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
(local assets (require "src/assets.fnl"))
|
||||
(local levels (require "levels.fnl"))
|
||||
(local color (require "src/colors.fnl"))
|
||||
|
||||
(local walls {
|
||||
:quads []
|
||||
:batch nil
|
||||
:collider-debug-boxes []
|
||||
})
|
||||
|
||||
(lambda mirror-collider [collider]
|
||||
"Mirror a collider box horizontally within a 25-unit tile (center is at 12.5)
|
||||
Transforms collider positions so they're reflected across the vertical center line."
|
||||
{
|
||||
:x (- 25 collider.x collider.width)
|
||||
:y collider.y
|
||||
:width collider.width
|
||||
:height collider.height
|
||||
})
|
||||
|
||||
(fn walls.load [self]
|
||||
(set self.batch (love.graphics.newSpriteBatch assets.walls-sprite 2500))
|
||||
;; load quads
|
||||
(let [(w h) (assets.walls-sprite:getDimensions)]
|
||||
(for [i 0 19 1]
|
||||
(table.insert self.quads (love.graphics.newQuad (* i 25) 0 25 25 w h))))
|
||||
;; fill batch
|
||||
(each [_ row (pairs (. levels :levels self.pool.data.level-key :tiles))]
|
||||
(each [_ tile (pairs row)]
|
||||
(let [
|
||||
x tile.x
|
||||
y tile.y
|
||||
id tile.tile-id
|
||||
colliders tile.colliders]
|
||||
(if (and (> id 0) (< id 21)) ;; 1-20 are wall tiles
|
||||
(do
|
||||
(self.batch:add (. self.quads id) (if tile.h-flip (+ x 25) x) y 0 (if tile.h-flip -1 1) 1)
|
||||
(each [_ collider (pairs colliders)]
|
||||
(let [
|
||||
mirrored-collider (if tile.h-flip (mirror-collider collider) collider)
|
||||
collider-x (+ x mirrored-collider.x)
|
||||
collider-y (+ y mirrored-collider.y)]
|
||||
(self.pool.data.bump-world:add {: x : y :name :wall :behavior :block} collider-x collider-y mirrored-collider.width mirrored-collider.height)
|
||||
(table.insert
|
||||
self.collider-debug-boxes
|
||||
{:x collider-x :y collider-y :width mirrored-collider.width :height mirrored-collider.height})))))))))
|
||||
|
||||
(fn walls.draw49 [self]
|
||||
(color.reset-color)
|
||||
(love.graphics.draw self.batch))
|
||||
|
||||
(fn walls.draw-debug [self]
|
||||
"draw collider debug boxes"
|
||||
(color.set-color :black)
|
||||
(each [_ collider (pairs self.collider-debug-boxes)]
|
||||
(love.graphics.rectangle "line" collider.x collider.y collider.width collider.height)))
|
||||
|
||||
walls
|
||||
6
game/src/utils.fnl
Normal file
6
game/src/utils.fnl
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
(lambda debug-print [obj]
|
||||
(print (fennel.view obj)))
|
||||
|
||||
{
|
||||
: debug-print
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue