|
|
@ -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) |
|
|
|
(block |
|
|
|
(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)))) |
|
|
|
(block |
|
|
|
(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 |
|
|
|
(array furthest-adjacent-cell position-delta-increase true) |
|
|
|
(array nearest-adjacent-cell position-delta-decrease false))) |
|
|
|
(each-in-array |
|
|
|
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) |
|
|
|
g-game-board-spatial-state)) |
|
|
|
(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 |
|
|
|
(break))) |
|
|
|
|
|
|
|
(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) |
|
|
|
(block |
|
|
|
(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)))) |
|
|
|
(block |
|
|
|
(when selected-piece |
|
|
|
;; TODO: Selection released; let block finish move and update grid |
|
|
|
(ignore)) |
|
|
|
(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) |
|
|
|
(scope |
|
|
|
(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) |
|
|
|
mouse-board-pos)) |
|
|
|
(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) |
|
|
|
(tokenize-push |
|
|
|
output |
|
|
|
(type-cast (token-splice expression) float)) |
|
|
|
(return true)) |
|
|
|
|
|
|
|
|
|
|
|
(defmacro each-in-array (array-name symbol iterator-name symbol &rest body any) |
|
|
|
(tokenize-push |
|
|
|
output |
|
|
|
(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 |
|
|
|
;; |
|
|
|