it's sort of playable!

This commit is contained in:
Jeremy Penner 2022-04-24 21:26:00 -04:00
parent 914731713a
commit c8a42fd631
3 changed files with 85 additions and 11 deletions

View file

@ -6,18 +6,18 @@
(local dim (require :game.dim))
(local {: draw : update} (util.require :game.entity))
(fn game-update [dt])
(fn exception-update [dt]
(fn exception-update []
(when (love.keyboard.isDown :f2)
(set state.update-exception nil)))
(fn update [dt]
(fn wrap-call [thunk]
(if state.update-exception
(exception-update dt)
(xpcall #(game-update dt) (fn [msg]
(exception-update)
(xpcall thunk (fn [msg]
(set state.update-exception (.. msg "\n" (debug.traceback)))))))
(fn update [dt] (wrap-call #(rules.update dt)))
(fn game-draw []
(let [xnext (/ dim.tilesize 2)
xwell (* dim.tilesize 5)
@ -37,5 +37,10 @@
(exception-draw)
(game-draw)))
{: update : draw}
(fn handler [ev ...]
(let [f (. rules ev)
args [...]]
(when f (wrap-call #(f (table.unpack args))))))
{: update : draw : handler}

View file

@ -2,6 +2,7 @@
(local map (require :game.tilemap))
(local tileset (require :game.tiles))
(local state (require :game.state))
(local helpers (require :game.helpers))
(local Rules {})
@ -78,7 +79,7 @@
(. possible-values ivalue)))
(fn Rules.tetromino [k irotation]
(let [rotations (or (. state.tetrominoes k) [["##" "##"]])
(let [rotations (or (. state.tetrominoes k) [])
irotation (+ (% (- irotation 1) (length rotations)) 1)]
(. rotations irotation)))
@ -90,12 +91,12 @@
(map.set-itile-at 11 y state.well "X"))
(for [x 0 11]
(map.set-itile-at x 20 state.well "X"))
(set state.drop-ms 750)
(set state.drop-speed-ms 750)
(Rules.play-next-piece))
(fn Rules.play-next-piece []
(let [piece (or state.next-piece (Rules.choose-random-tetromino))
x (/ (- (length (. state.well 1)) 2) 2)]
x (math.floor (/ (- (length (. state.well 1)) 2) 2))]
(set state.current {: piece : x :y 0 :irotation 1})
(set state.next-piece (Rules.choose-random-tetromino))))
@ -103,5 +104,73 @@
(when state.current
(Rules.tetromino state.current.piece state.current.irotation)))
(fn solid-positions [tetromino ?x ?y]
(let [h (length tetromino)
w (length (. tetromino 1))
x (or ?x 0)
y (or ?y 0)]
(icollect [tx ty (helpers.all-coordinates w h)]
(let [itile (map.itile-at tx ty tetromino)]
(when (not= itile " ") [(+ x tx) (+ y ty) itile])))))
(fn Rules.collides? [tetromino x y]
(var collides false)
(when tetromino
(each [_ [wx wy] (ipairs (solid-positions tetromino x y)) :until collides]
(set collides (not= (map.itile-at wx wy state.well) " "))))
collides)
(fn Rules.place-piece [tetromino x y]
(each [_ [wx wy itile] (ipairs (solid-positions tetromino x y))]
(map.set-itile-at wx wy state.well itile)))
(fn Rules.try-move-piece [dx dy]
(when state.current
(let [tetromino (Rules.current-tetromino)
x (+ state.current.x dx)
y (+ state.current.y dy)
stopped (Rules.collides? tetromino x y)]
(if (and stopped (not= dy 0)) ; dropping
(do (Rules.place-piece tetromino state.current.x state.current.y)
(Rules.play-next-piece))
(not stopped)
(do (set state.current.x x)
(set state.current.y y))))))
(fn Rules.rotate [di]
(when state.current
(set state.current.irotation (+ state.current.irotation di))))
(set Rules.commands
{:move Rules.try-move-piece
:rotate Rules.rotate
:reset Rules.reset-game})
(set Rules.keymap
{:left [:move -1 0]
:right [:move 1 0]
:down [:move 0 1]
:up [:rotate 1]
:z [:rotate -1]
:x [:rotate 1]
:r [:reset]})
(fn Rules.run-command [cmd]
(when cmd
(let [[command & args] cmd
f (. Rules.commands command)]
(when f (f (table.unpack args))))))
(fn Rules.keypressed [key]
(Rules.run-command (. Rules.keymap key)))
(fn Rules.update [dt]
(let [drop-ms (- (or state.drop-ms state.drop-speed-ms) (* dt 1000))]
(if (<= drop-ms 0)
(do (set state.drop-ms nil)
(Rules.try-move-piece 0 1))
(set state.drop-ms drop-ms))))
Rules

View file

@ -689,7 +689,7 @@ function lume.hotswap(modname)
local oldglobal = lume.clone(_G)
local updated = {}
local function update(old, new)
if updated[old] then return end
if old == nil or updated[old] then return end
updated[old] = true
local oldmt, newmt = getmetatable(old), getmetatable(new)
if oldmt and newmt then update(oldmt, newmt) end