diff --git a/.gitignore b/.gitignore index 9142865..2e4e2bd 100644 --- a/.gitignore +++ b/.gitignore @@ -62,4 +62,9 @@ test/data/Materials/Textures/*.dds test/data/Models/* -kitty-gridlock \ No newline at end of file +kitty-gridlock + +*.kra-autosave.kra +.stfolder +.stversions +*.bmp~ \ No newline at end of file diff --git a/Dependencies/gamelib b/Dependencies/gamelib index 81db032..040283f 160000 --- a/Dependencies/gamelib +++ b/Dependencies/gamelib @@ -1 +1 @@ -Subproject commit 81db0329e93f8ef802a6c162e731d63c50d7ee10 +Subproject commit 040283f01ceb4b9e2708e2610f10f564915ee75e diff --git a/assets/Board.xcf b/assets/Board.xcf index 2d07af2..6ad8921 100644 Binary files a/assets/Board.xcf and b/assets/Board.xcf differ diff --git a/assets/FromV/Exports/KittyGridlockInitialCatAssets.bmp b/assets/FromV/Exports/KittyGridlockInitialCatAssets.bmp new file mode 100644 index 0000000..f597f74 Binary files /dev/null and b/assets/FromV/Exports/KittyGridlockInitialCatAssets.bmp differ diff --git a/assets/FromV/First Draft Assets.kra b/assets/FromV/First Draft Assets.kra new file mode 100644 index 0000000..1da2398 Binary files /dev/null and b/assets/FromV/First Draft Assets.kra differ diff --git a/assets/Grid.xcf b/assets/Grid.xcf new file mode 100644 index 0000000..262575b Binary files /dev/null and b/assets/Grid.xcf differ diff --git a/data/Board.bmp b/data/Board.bmp index 7388742..4bcbe63 100644 Binary files a/data/Board.bmp and b/data/Board.bmp differ diff --git a/data/Grid.bmp b/data/Grid.bmp new file mode 100644 index 0000000..00ab1bf Binary files /dev/null and b/data/Grid.bmp differ diff --git a/src/Main.cake b/src/Main.cake index 40954f5..10e799c 100644 --- a/src/Main.cake +++ b/src/Main.cake @@ -72,7 +72,7 @@ ;; movement constraints. -1 = empty cell. Values are indices into g-game-board-pieces. Used to ;; easily pick from tap/click (def-type-alias BoardPieceIndex char) -(var g-game-board-occupied-state ([] 6 ([] 6 BoardPieceIndex)) (array 0)) +(var g-game-board-spatial-state ([] 6 ([] 6 BoardPieceIndex)) (array 0)) ;; Max pieces is determined as follows: ;; 6x6 grid = 36 squares @@ -112,7 +112,7 @@ (while (< row g-game-board-grid-size) (var column int 0) (while (< column g-game-board-grid-size) - (var index BoardPieceIndex (at row column g-game-board-occupied-state)) + (var index BoardPieceIndex (at row column g-game-board-spatial-state)) (if (and (>= index 0) (field (at index g-game-board-pieces) num-cells)) (scope (var piece-in-cell (* board-piece) (addr (at index g-game-board-pieces))) @@ -141,8 +141,8 @@ (defun-local game-board-sync-occupied-state (&return bool) ;; Zero out to make overlap validation easy - (memset g-game-board-occupied-state -1 - (sizeof g-game-board-occupied-state)) + (memset g-game-board-spatial-state -1 + (sizeof g-game-board-spatial-state)) (on-each-existing-board-piece piece piece-index (when debug-log-enabled @@ -179,7 +179,7 @@ (set (vec-y cell-to-set) (vec-y (path piece > grid-position))))) (var occupy-space-pointer (* BoardPieceIndex) - (addr (at (vec-y cell-to-set) (vec-x cell-to-set) g-game-board-occupied-state))) + (addr (at (vec-y cell-to-set) (vec-x cell-to-set) g-game-board-spatial-state))) (when (!= -1 (deref occupy-space-pointer)) (printf "error: Piece %d overlapping %d at (%d, %d)! Aborting\n" piece-index (deref occupy-space-pointer) @@ -284,6 +284,61 @@ (printf "%s\n" fogleman-board-string) (return true)) +(defun-local game-piece-position-to-screen-position (piece (* (const board-piece)) &return vec2) + (var piece-position vec2 (array (type-cast (vec-x (path piece > grid-position)) float) + (type-cast (vec-y (path piece > grid-position)) float))) + ;; Transfer to pixel space + (set piece-position (vec2-multiply (array (repeat g-game-board-cell-size-px)) piece-position)) + ;; Add in moving position + (set piece-position (vec2-add piece-position (path piece > moving-position))) + ;; Add board offset + (set piece-position (vec2-add piece-position g-game-board-inner-top-left-px)) + (return piece-position)) + +(defun-local game-piece-get-screen-size (piece (* (const board-piece)) &return vec2) + (var piece-grid-size vec2 + (array + (? (path piece > is-vertical) 1.f (type-cast (path piece > num-cells) float)) + (? (path piece > is-vertical) (type-cast (path piece > num-cells) float) 1.f))) + (var piece-size vec2 (array (repeat g-game-board-cell-size-px))) + (set piece-size (vec2-multiply piece-size piece-grid-size)) + (return piece-size)) + +(defun-local is-within-game-piece (piece (* (const board-piece)) point-to-test vec2 &return bool) + (var piece-top-left-px vec2 (game-piece-position-to-screen-position piece)) + (var piece-bottom-right-px vec2 (game-piece-get-screen-size piece)) + (set piece-bottom-right-px (vec2-add piece-top-left-px piece-bottom-right-px)) + (return + (and + (>= (vec-x piece-top-left-px) (vec-x point-to-test)) + (>= (vec-y piece-top-left-px) (vec-y point-to-test)) + (< (vec-x piece-bottom-right-px) (vec-x point-to-test)) + (< (vec-y piece-bottom-right-px) (vec-y point-to-test))))) + +(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))) + (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) + (/ (type-cast (vec-y board-position) int) g-game-board-cell-size-px))) + + (unless + (and + (>= (vec-x grid-position) 0) + (>= (vec-y grid-position) 0) + (< (vec-x grid-position) g-game-board-grid-size) + (< (vec-y grid-position) g-game-board-grid-size)) + (return null)) + + (var piece-index char + (at (vec-y grid-position) (vec-x grid-position) g-game-board-spatial-state)) + (unless (!= -1 piece-index) + (return null)) + (var piece (* board-piece) (addr (at piece-index g-game-board-pieces))) + ;; (unless (is-within-game-piece piece position) ;; TODO Broken + ;; (return null)) + (return piece)) + ;; ;; Helpers ;; @@ -320,6 +375,39 @@ (return false)) (return true)) +(defun-local sdl-texture-from-bmp (filename (* (const char)) renderer (* SDL_Renderer) + &return (* SDL_Texture)) + (var surface (* SDL_Surface) (SDL_LoadBMP filename)) + (unless surface + (printf "Failed to load surface\n") + (sdl-print-error) + (return null)) + + (var texture (* SDL_Texture) + (SDL_CreateTextureFromSurface renderer surface)) + ;; No need to hold on to surface after texture has been created + (SDL_FreeSurface surface) + (unless texture (sdl-print-error)) + (return texture)) + +(defun-local sdl-texture-from-bmp-color-to-transparent + (filename (* (const char)) renderer (* SDL_Renderer) r char g char b char + &return (* SDL_Texture)) + (var surface (* SDL_Surface) (SDL_LoadBMP filename)) + (unless surface + (printf "Failed to load surface\n") + (sdl-print-error) + (return null)) + + (SDL_SetColorKey surface SDL_TRUE (SDL_MapRGB (path surface > format) r g b)) + + (var texture (* SDL_Texture) + (SDL_CreateTextureFromSurface renderer surface)) + ;; No need to hold on to surface after texture has been created + (SDL_FreeSurface surface) + (unless texture (sdl-print-error)) + (return texture)) + ;; ;; Main ;; @@ -333,7 +421,7 @@ Licensed under GPL-3.0-or-later.\n Rush Hour database from Michael Fogleman.\n\n") ;; Useful reference for creating assets - (printf "Window and board dimensions:\n + (debug-log "Window and board dimensions:\n \twindow width: %d\n \twindow height: %d\n \twindow safe area margin px: %d\n @@ -364,34 +452,45 @@ Rush Hour database from Michael Fogleman.\n\n") (var renderer (* SDL_Renderer) null) (unless (sdl-intialize-2d-renderer (addr renderer) window) (return 1)) - (var background-surface (* SDL_Surface) (SDL_LoadBMP - (in-data-dir "Board.bmp"))) - (unless background-surface - (printf "Failed to load surface. Is the data directory in the right location?\n") - (sdl-print-error) - (return 1)) - (var background-texture (* SDL_Texture) - (SDL_CreateTextureFromSurface renderer background-surface)) - (unless background-texture (sdl-print-error) (return 1)) - ;; No need to hold on to surface after texture has been created - (SDL_FreeSurface background-surface) - - (set (field (at 0 g-game-board-pieces) num-cells) 3) - (set (vec-x (field (at 0 g-game-board-pieces) grid-position)) 0) - (set (vec-y (field (at 0 g-game-board-pieces) grid-position)) 3) - (set (field (at 0 g-game-board-pieces) is-vertical) true) - (set (field (at 0 g-game-board-pieces) label) 'b') - - (set (field (at 1 g-game-board-pieces) num-cells) 3) - (set (vec-x (field (at 1 g-game-board-pieces) grid-position)) 1) - (set (vec-y (field (at 1 g-game-board-pieces) grid-position)) 3) - (set (field (at 1 g-game-board-pieces) is-vertical) false) - (set (field (at 1 g-game-board-pieces) label) 'c') - (unless (game-board-sync-occupied-state) - (return 1)) - - (game-board-load "60 IBBxooIooLDDJAALooJoKEEMFFKooMGGHHHM 2332") - + (var background-texture (* SDL_Texture) (sdl-texture-from-bmp (in-data-dir "Board.bmp") + renderer)) + (unless background-texture (return 1)) + (var grid-texture (* SDL_Texture) (sdl-texture-from-bmp (in-data-dir "Grid.bmp") + renderer)) + (unless grid-texture (return 1)) + + (var pieces-texture (* SDL_Texture) + (sdl-texture-from-bmp-color-to-transparent + "assets/FromV/Exports/KittyGridlockInitialCatAssets.bmp" + renderer + 0xff 0x00 0xd3)) + (unless pieces-texture (return 1)) + ;; Texture atlas + (var piece-primary-origin (const vec2) (array 334.f 525.f)) + (var piece-2-1-origin (const vec2) (array 534.f 686.f)) + (var piece-3-1-origin (const vec2) (array 516.f 841.f)) + (var piece-1-2-origin (const vec2) (array 853.f 519.f)) + (var piece-1-3-origin (const vec2) (array 843.f 9.f)) + (var wall-a-origin (const vec2) (array 674.f 507.f)) + (var wall-b-origin (const vec2) (array 342.f 682.f)) + + (ignore ;; Example of setting pieces manually + (set (field (at 0 g-game-board-pieces) num-cells) 3) + (set (vec-x (field (at 0 g-game-board-pieces) grid-position)) 0) + (set (vec-y (field (at 0 g-game-board-pieces) grid-position)) 3) + (set (field (at 0 g-game-board-pieces) is-vertical) true) + (set (field (at 0 g-game-board-pieces) label) 'b') + + (set (field (at 1 g-game-board-pieces) num-cells) 3) + (set (vec-x (field (at 1 g-game-board-pieces) grid-position)) 1) + (set (vec-y (field (at 1 g-game-board-pieces) grid-position)) 3) + (set (field (at 1 g-game-board-pieces) is-vertical) false) + (set (field (at 1 g-game-board-pieces) label) 'c') + (unless (game-board-sync-occupied-state) + (return 1))) + + ;; (game-board-load "60 IBBxooIooLDDJAALooJoKEEMFFKooMGGHHHM 2332") + (game-board-load "05 oooooEooDooEAADooEoBBCCCoooooooooooo 69") ;; ;; Game loop ;; @@ -405,10 +504,67 @@ Rush Hour database from Michael Fogleman.\n\n") (when (at SDL_SCANCODE_ESCAPE currentKeyStates) (set exit-reason "Escape pressed")) + (var mouse-x int 0) + (var mouse-y int 0) + (var mouse-buttons Uint32 (SDL_GetMouseState (addr mouse-x) (addr mouse-y))) + + (var hovered-piece (* board-piece) (pick-game-piece-from-screen-position mouse-x mouse-y)) + (SDL_RenderClear renderer) (unless (= 0 (SDL_RenderCopy renderer background-texture null null)) (sdl-print-error) - (return 1)) + (set exit-reason "Render error")) + + (scope ;; Draw grid + (var row int 0) + (while (< row g-game-board-grid-size) + (var column int 0) + (while (< column g-game-board-grid-size) + (var current-cell vec2 (array (type-cast row float) (type-cast column float))) + (var cell-position vec2 + (vec2-add g-game-board-inner-top-left-px + (vec2-multiply (array (repeat g-game-board-cell-size-px)) + current-cell))) + (var dest-grid-rect SDL_Rect (array (type-cast (vec-x cell-position) int) + (type-cast (vec-y cell-position) int) + (repeat g-game-board-cell-size-px))) + (unless (= 0 (SDL_RenderCopy renderer grid-texture null (addr dest-grid-rect))) + (sdl-print-error) + (set exit-reason "Render error")) + (incr column)) + (incr row))) + + (on-each-existing-board-piece ;; Draw pieces + piece piece-index + (when (= hovered-piece piece) + (continue)) + (var piece-position vec2 (game-piece-position-to-screen-position piece)) + + (var piece-size vec2 (game-piece-get-screen-size piece)) + + (var selected-piece-origin vec2 piece-2-1-origin) + (cond ((path piece > is-primary-piece) ;; Pick atlas texture coords for piece + (set selected-piece-origin piece-primary-origin)) + ((path piece > is-wall) + (set selected-piece-origin wall-a-origin)) + ((and (path piece > is-vertical) (= 3 (path piece > num-cells))) + (set selected-piece-origin piece-1-3-origin)) + ((and (path piece > is-vertical) (= 2 (path piece > num-cells))) + (set selected-piece-origin piece-1-2-origin)) + ((and (not (path piece > is-vertical)) (= 2 (path piece > num-cells))) + (set selected-piece-origin piece-2-1-origin)) + ((and (not (path piece > is-vertical)) (= 3 (path piece > num-cells))) + (set selected-piece-origin piece-3-1-origin))) + + (var dest-rect SDL_Rect (array (vec-xy-to-int piece-position) + (vec-xy-to-int piece-size))) + (var src-rect SDL_Rect (array (vec-xy-to-int selected-piece-origin) + (vec-xy-to-int piece-size))) + (unless (= 0 (SDL_RenderCopy renderer pieces-texture + (addr src-rect) (addr dest-rect))) + (sdl-print-error) + (set exit-reason "Render error"))) + (SDL_RenderPresent renderer)) ;; @@ -465,6 +621,19 @@ Rush Hour database from Michael Fogleman.\n\n") statement (array-size statement) output))) +(defmacro repeat (thing any) + (tokenize-push + output + (token-splice thing) (token-splice thing)) + (return true)) + +(defmacro vec-xy-to-int (vec symbol) + (tokenize-push + output + (type-cast (vec-x (token-splice vec)) int) + (type-cast (vec-y (token-splice vec)) int)) + (return true)) + ;; ;; Building ;;