2021-03-07 16:55:50 +00:00
|
|
|
(local util (require :lib.util))
|
|
|
|
(local dim (require :game.dim))
|
|
|
|
(local {: direct : move} (util.require :game.entity))
|
2021-04-04 02:36:12 +00:00
|
|
|
(local {: edge : edge-crosses : vec*} (util.require :game.helpers))
|
2021-03-07 16:55:50 +00:00
|
|
|
(local map (require :game.tilemap))
|
|
|
|
|
2021-03-30 23:24:52 +00:00
|
|
|
(local bomberman (util.hot-table ...))
|
2021-03-07 16:55:50 +00:00
|
|
|
(set bomberman.keymap {:up :w :down :s :left :a :right :d :bomb :x})
|
|
|
|
|
|
|
|
(fn bomberman.draw [entity]
|
|
|
|
(love.graphics.setColor 0.2 0.2 0.2)
|
|
|
|
(love.graphics.circle :fill (. entity.pos 1) (. entity.pos 2) (/ dim.tilesize 2)))
|
2021-03-28 19:23:08 +00:00
|
|
|
|
2021-04-04 02:36:12 +00:00
|
|
|
(fn tile-at [x y rules]
|
2021-03-28 19:23:08 +00:00
|
|
|
(-?> [x y]
|
|
|
|
(map.world-to-tile)
|
2021-04-04 02:36:12 +00:00
|
|
|
(rules.tile-at)))
|
|
|
|
|
|
|
|
(fn bomberman.collides? [[x y] rules]
|
|
|
|
(let [tile (tile-at x y rules)]
|
|
|
|
(and tile (or tile.bomb tile.wall))))
|
|
|
|
|
|
|
|
(fn bomberman.tile-edge [c dc]
|
|
|
|
(let [tc (math.floor (/ c dim.tilesize))
|
|
|
|
cfloor (* tc dim.tilesize)]
|
|
|
|
(if (= dc 0) c
|
|
|
|
(> dc 0) (- cfloor dim.halftile)
|
|
|
|
(+ cfloor dim.tilesize dim.halftile))))
|
|
|
|
|
|
|
|
; Collision model for Bomberman works like this (in order):
|
|
|
|
; * if the moving edge is NOT crossing over a tile boundary, allow the movement
|
|
|
|
; * if there is no solid tile in in front of Bomberman, allow the movement
|
|
|
|
; * if there are two solid tiles in front of Bomberman, push Bomberman back onto
|
|
|
|
; the tile boundary
|
|
|
|
; * if there is one solid and one empty tile in front of Bomberman, push Bomberman
|
|
|
|
; back onto the tile boundary, and push Bomberman towards the empty tile in the
|
|
|
|
; other axis
|
2021-04-04 17:26:47 +00:00
|
|
|
; Movement only happens along one axis; diagonal movement is not allowed.
|
|
|
|
(fn horizontal [c copp] [c copp])
|
|
|
|
(fn vertical [c copp] [copp c])
|
|
|
|
(fn bomberman.axis-movement [make-xy c copp dc rules]
|
|
|
|
(let [(edge-prev edge-next) (edge c dc dim.halftile)
|
2021-04-04 02:36:12 +00:00
|
|
|
crosses (edge-crosses edge-prev edge-next dim.tilesize)
|
2021-04-04 17:26:47 +00:00
|
|
|
neg-edge (- copp dim.halftile)
|
|
|
|
neg-collides (bomberman.collides? (make-xy edge-next neg-edge) rules)
|
|
|
|
pos-edge (+ copp dim.halftile -0.01)
|
|
|
|
pos-collides (bomberman.collides? (make-xy edge-next pos-edge) rules)
|
|
|
|
dc-edge (- (bomberman.tile-edge edge-next dc) c)
|
|
|
|
dcopp (math.abs dc)
|
|
|
|
[cn coppn]
|
|
|
|
(if (not crosses) [dc 0]
|
|
|
|
(and (not neg-collides) (not pos-collides)) [dc 0]
|
|
|
|
(and neg-collides pos-collides) [dc-edge 0]
|
|
|
|
neg-collides [dc-edge (math.min dcopp (- (bomberman.tile-edge (+ pos-edge dim.tilesize) 1) copp))]
|
|
|
|
pos-collides [dc-edge (math.max (- dcopp) (- (bomberman.tile-edge (- neg-edge dim.tilesize) -1) copp))])]
|
|
|
|
(make-xy cn coppn)))
|
2021-03-28 19:23:08 +00:00
|
|
|
|
2021-03-07 16:55:50 +00:00
|
|
|
(fn bomberman.update [entity dt rules]
|
|
|
|
(set entity.vel (direct bomberman.keymap (* dim.tilesize 3)))
|
2021-04-04 03:13:33 +00:00
|
|
|
(let [[x y] entity.pos
|
|
|
|
[dx dy] (vec* entity.vel dt)
|
2021-04-04 17:26:47 +00:00
|
|
|
[dx dy] (if (not= dx 0) (bomberman.axis-movement horizontal x y dx rules)
|
|
|
|
(bomberman.axis-movement vertical y x dy rules))]
|
2021-04-04 03:13:33 +00:00
|
|
|
(set entity.pos [(+ x dx) (+ y dy)]))
|
2021-03-07 16:55:50 +00:00
|
|
|
(when (love.keyboard.isDown bomberman.keymap.bomb)
|
|
|
|
(rules.place-bomb (map.world-to-tile entity.pos))))
|
|
|
|
|
|
|
|
(fn bomberman.new [pos]
|
2021-03-30 23:24:52 +00:00
|
|
|
{: pos :vel [0 0] :draw #(bomberman.draw $...) :update #(bomberman.update $...)})
|
2021-03-07 16:55:50 +00:00
|
|
|
|
2021-03-30 23:24:52 +00:00
|
|
|
bomberman.hot
|