Browse Source

Piece constraints based on grid now working

Macoy Madson 3 years ago
  1. 116


@ -56,6 +56,12 @@
X int
Y int)
(defun-local grid-vec2-add (a grid-vec2 b grid-vec2 &return grid-vec2)
(var result grid-vec2)
(set (vec-x result) (+ (vec-x a) (vec-x b)))
(set (vec-y result) (+ (vec-y a) (vec-y b)))
(return result))
(defstruct-local board-piece
grid-position grid-vec2 ;; Always from the top left
moving-position vec2 ;; Floating point for animation, smooth dragging
@ -321,8 +327,7 @@
(< (vec-x screen-point-to-test) (vec-x piece-bottom-right-px))
(< (vec-y screen-point-to-test) (vec-y piece-bottom-right-px)))))
(defun-local pick-game-piece-from-screen-position (x int y int &return (* board-piece))
(var position vec2 (array (type-cast x float) (type-cast y float)))
(defun-local pick-game-piece-from-screen-position (position vec2 &return (* board-piece))
(var board-position vec2 (vec2-subtract position g-game-board-inner-top-left-px))
(var grid-position grid-vec2
(array (/ (type-cast (vec-x board-position) int) g-game-board-cell-size-px)
@ -345,6 +350,79 @@
(return null))
(return piece))
(defun-local clamp-within (moving float minimum float maximum float &return float)
(when (< moving minimum)
(return minimum))
(when (> moving maximum)
(return maximum))
(return moving))
(defun-local constrain-piece-moving-position (piece (* (const board-piece))
delta-position vec2 &return vec2)
(var constrained-position vec2 delta-position)
(if (path piece > is-vertical) ;; Constrain on axes
(set (vec-x constrained-position) 0.f)
(set (vec-y constrained-position) 0.f))
;; Constrain based on empty spaces
(var min-position grid-vec2 (array 0))
(var max-position grid-vec2 (array 0))
(var position-delta-increase grid-vec2 (array 0))
(var position-delta-decrease grid-vec2 (array 0))
(var nearest-adjacent-cell grid-vec2 (path piece > grid-position))
(var furthest-adjacent-cell grid-vec2 (path piece > grid-position))
(if (path piece > is-vertical)
(set (vec-y position-delta-increase) 1)
(set (vec-y position-delta-decrease) -1)
(set (vec-y nearest-adjacent-cell) (- (vec-y nearest-adjacent-cell) 1))
(set (vec-y furthest-adjacent-cell)
(+ (vec-y (path piece > grid-position)) (path piece > num-cells))))
(set (vec-x position-delta-increase) 1)
(set (vec-x position-delta-decrease) -1)
(set (vec-x nearest-adjacent-cell) (- (vec-x nearest-adjacent-cell) 1))
(set (vec-x furthest-adjacent-cell)
(+ (vec-x (path piece > grid-position)) (path piece > num-cells)))))
(defstruct scan-direction
start-position grid-vec2
delta grid-vec2
is-increasing bool)
(var directions ([] 2 scan-direction)
(array furthest-adjacent-cell position-delta-increase true)
(array nearest-adjacent-cell position-delta-decrease false)))
directions i
(var direction (* scan-direction) (addr (at i directions)))
(var scan-position grid-vec2 (path direction > start-position))
(while (and (>= (vec-x scan-position) 0)
(>= (vec-y scan-position) 0)
(< (vec-x scan-position) g-game-board-grid-size)
(< (vec-y scan-position) g-game-board-grid-size))
(var space-index int (at (vec-y scan-position) (vec-x scan-position)
(when (= -1 space-index)
(if (path direction > is-increasing)
(set max-position (grid-vec2-add max-position (path direction > delta)))
(set min-position (grid-vec2-add min-position (path direction > delta))))
(set scan-position (grid-vec2-add scan-position (path direction > delta))))
;; Anything other than empty space can immediately break us out
(var min-delta-px vec2 (array (* g-game-board-cell-size-px (to-float (vec-x min-position)))
(* g-game-board-cell-size-px (to-float (vec-y min-position)))))
(var max-delta-px vec2 (array (* g-game-board-cell-size-px (to-float (vec-x max-position)))
(* g-game-board-cell-size-px (to-float (vec-y max-position)))))
(if (path piece > is-vertical)
(set (vec-y constrained-position)
(clamp-within (vec-y constrained-position) (vec-y min-delta-px) (vec-y max-delta-px)))
(set (vec-x constrained-position)
(clamp-within (vec-x constrained-position) (vec-x min-delta-px) (vec-x max-delta-px))))
(return constrained-position))
;; Helpers
@ -501,6 +579,7 @@ Rush Hour database from Michael Fogleman.\n\n")
;; Game loop
(var selected-piece (* board-piece) null)
(var selection-start-position vec2 (array 0))
(var exit-reason (* (const char)) null)
(while (not exit-reason)
(var event SDL_Event)
@ -514,12 +593,18 @@ Rush Hour database from Michael Fogleman.\n\n")
(var mouse-x int 0)
(var mouse-y int 0)
(var mouse-button-state Uint32 (SDL_GetMouseState (addr mouse-x) (addr mouse-y)))
(var mouse-position vec2 (array (type-cast mouse-x float) (type-cast mouse-y float)))
(if (bit-and mouse-button-state SDL_BUTTON_LMASK)
(unless selected-piece ;; If holding, allow dragging even when not exactly on piece
(set selected-piece (pick-game-piece-from-screen-position mouse-x mouse-y))))
(set selected-piece nullptr))
(set selection-start-position mouse-position)
(set selected-piece (pick-game-piece-from-screen-position mouse-position))))
(when selected-piece
;; TODO: Selection released; let block finish move and update grid
(set selected-piece nullptr)))
(SDL_RenderClear renderer)
(unless (= 0 (SDL_RenderCopy renderer background-texture null null))
@ -550,10 +635,9 @@ Rush Hour database from Michael Fogleman.\n\n")
(if (= selected-piece piece)
(var piece-position vec2 (game-piece-grid-position-to-screen-position piece))
(var mouse-board-pos vec2 (array (type-cast mouse-x float) (type-cast mouse-y float)))
(set mouse-board-pos (vec2-subtract mouse-board-pos piece-position))
(var mouse-delta-pos vec2 (vec2-subtract mouse-position selection-start-position))
(set (path piece > moving-position)
(constrain-piece-moving-position piece mouse-delta-pos)))
;; Reset positions on release
(set (path piece > moving-position) (array 0)))
@ -652,6 +736,24 @@ Rush Hour database from Michael Fogleman.\n\n")
(type-cast (vec-y (token-splice vec)) int))
(return true))
(defmacro to-float (expression any)
(type-cast (token-splice expression) float))
(return true))
(defmacro each-in-array (array-name symbol iterator-name symbol &rest body any)
(var (token-splice iterator-name) int 0)
(var next-iterator int 0) ;; TODO needs unique name
(while (< next-iterator (array-size (token-splice array-name)))
(set (token-splice iterator-name) next-iterator)
(incr next-iterator)
(token-splice-rest body tokens)))
(return true))
;; Building