aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavi.dcr@tutanota.com>2024-01-28 03:01:13 +0100
committerXavier Del Campo Romero <xavi.dcr@tutanota.com>2024-01-28 15:17:49 +0100
commitfd53c7da8c5f2b79b87f624e313ff508072361ad (patch)
treedb569413cd3d42034a22368a7980aa99d7d55235
parente49e3073c67af785447ddb0ecbdc521b68cf3ea9 (diff)
Big rushed update
-rw-r--r--README.md2
-rw-r--r--jancity.pngbin0 -> 9735 bytes
-rw-r--r--res/CMakeLists.txt144
-rw-r--r--res/btn_left.bmpbin586 -> 0 bytes
-rw-r--r--res/btn_left_24.bmpbin2358 -> 1590 bytes
-rw-r--r--res/btn_mid.bmpbin542 -> 0 bytes
-rw-r--r--res/btn_mid_24.bmpbin2358 -> 1590 bytes
-rw-r--r--res/btn_right.bmpbin586 -> 0 bytes
-rw-r--r--res/btn_right_24.bmpbin2358 -> 1590 bytes
-rw-r--r--res/btn_small.bmpbin0 -> 490 bytes
-rw-r--r--res/btn_small_24.bmpbin0 -> 1782 bytes
-rw-r--r--res/car1_24.bmpbin0 -> 9270 bytes
-rw-r--r--res/car2_24.bmpbin0 -> 9270 bytes
-rw-r--r--res/checkbox_24.bmpbin0 -> 1998 bytes
-rw-r--r--res/city1.txt44
-rw-r--r--res/font.bmpbin0 -> 8206 bytes
-rw-r--r--res/font_24.bmpbin0 -> 48438 bytes
-rw-r--r--res/functions.cmake2
-rw-r--r--res/line_edit_left_24.bmpbin0 -> 1590 bytes
-rw-r--r--res/line_edit_mid_24.bmpbin0 -> 1590 bytes
-rw-r--r--res/line_edit_right_24.bmpbin0 -> 1590 bytes
-rw-r--r--res/sel_down_left_24.bmpbin0 -> 822 bytes
-rw-r--r--res/sel_down_right_24.bmpbin0 -> 822 bytes
-rw-r--r--res/sel_mid_down_24.bmpbin0 -> 822 bytes
-rw-r--r--res/sel_mid_top_24.bmpbin0 -> 150 bytes
-rw-r--r--res/sel_mid_v_24.bmpbin0 -> 182 bytes
-rw-r--r--res/sel_up_left_24.bmpbin0 -> 822 bytes
-rw-r--r--res/sel_up_right_24.bmpbin0 -> 822 bytes
-rw-r--r--res/unit5_24.bmpbin9270 -> 9270 bytes
-rw-r--r--src/building/inc/building.h2
-rw-r--r--src/building/src/building.c2
-rw-r--r--src/camera/inc/camera.h3
-rw-r--r--src/camera/src/camera.c25
-rw-r--r--src/camera/src/mouse.c52
-rw-r--r--src/camera/src/pad.c2
-rw-r--r--src/game/src/res.c96
-rw-r--r--src/gui/inc/gui/rounded_rect.h5
-rw-r--r--src/gui/src/rounded_rect.c30
-rw-r--r--src/instance/CMakeLists.txt2
-rw-r--r--src/instance/src/instance.c55
-rw-r--r--src/menu/src/gamecfg_menu.c5
-rw-r--r--src/menu/src/main_menu.c50
-rw-r--r--src/menu/src/menu.c20
-rw-r--r--src/mouse/inc/mouse.h1
-rw-r--r--src/mouse/sdl-1.2/src/mouse.c8
-rw-r--r--src/peripheral/inc/peripheral.h2
-rw-r--r--src/player/CMakeLists.txt3
-rw-r--r--src/player/inc/human_player.h12
-rw-r--r--src/player/inc/player.h2
-rw-r--r--src/player/src/human_player.c23
-rw-r--r--src/player/src/human_player_gui.c170
-rw-r--r--src/player/src/player.c17
-rw-r--r--src/terrain/inc/terrain.h4
-rw-r--r--src/terrain/privinc/terrain_tiles.h114
-rw-r--r--src/terrain/src/init.c2
-rw-r--r--src/terrain/src/render.c10
-rw-r--r--src/unit/inc/unit.h21
-rw-r--r--src/unit/inc/unit_type.h9
-rw-r--r--src/unit/src/unit.c459
59 files changed, 1028 insertions, 370 deletions
diff --git a/README.md b/README.md
index cf7032d..f0ee3ac 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,8 @@
`jancity` is a cross-platform, tile-based sandbox video game.
+![Screenshot](jancity.png)
+
Mostly written during the Global Game Jam 2024 event, reusing its engine
from [`rts`](https://gitea.privatedns.org/xavi/rts).
diff --git a/jancity.png b/jancity.png
new file mode 100644
index 0000000..26d04dd
--- /dev/null
+++ b/jancity.png
Binary files differ
diff --git a/res/CMakeLists.txt b/res/CMakeLists.txt
index 65f1ccd..e063d17 100644
--- a/res/CMakeLists.txt
+++ b/res/CMakeLists.txt
@@ -128,10 +128,143 @@ sprite(NAME unit6
CY 48
TRANSPARENT TRUE)
+sprite(NAME sel_down_left
+ X 384
+ Y 0
+ BPP 4
+ CX 0
+ CY 0
+ TRANSPARENT TRUE)
+
+sprite(NAME sel_down_right
+ X 384
+ Y 0
+ BPP 4
+ CX 0
+ CY 0
+ TRANSPARENT TRUE)
+
+sprite(NAME sel_mid_down
+ X 384
+ Y 0
+ BPP 4
+ CX 0
+ CY 0
+ TRANSPARENT TRUE)
+
+sprite(NAME sel_mid_top
+ X 384
+ Y 0
+ BPP 4
+ CX 0
+ CY 0
+ TRANSPARENT TRUE)
+
+sprite(NAME sel_mid_v
+ X 384
+ Y 0
+ BPP 4
+ CX 0
+ CY 0
+ TRANSPARENT TRUE)
+
+sprite(NAME sel_up_left
+ X 384
+ Y 0
+ BPP 4
+ CX 0
+ CY 0
+ TRANSPARENT TRUE)
+
+sprite(NAME sel_up_right
+ X 384
+ Y 0
+ BPP 4
+ CX 0
+ CY 0
+ TRANSPARENT TRUE)
+
+sprite(NAME checkbox
+ X 384
+ Y 0
+ BPP 4
+ CX 0
+ CY 0
+ TRANSPARENT TRUE)
+
+sprite(NAME line_edit_left
+ X 0
+ Y 0
+ BPP 4
+ CX 0
+ CY 0
+ TRANSPARENT TRUE)
+
+sprite(NAME line_edit_mid
+ X 0
+ Y 0
+ BPP 4
+ CX 0
+ CY 0
+ TRANSPARENT FALSE)
+
+sprite(NAME line_edit_right
+ X 0
+ Y 0
+ BPP 4
+ CX 0
+ CY 0
+ TRANSPARENT TRUE)
+
+sprite(NAME car1
+ X 0
+ Y 0
+ BPP 4
+ CX 0
+ CY 0
+ TRANSPARENT TRUE)
+
+sprite(NAME pavement
+ X 0
+ Y 0
+ BPP 4
+ CX 0
+ CY 0
+ TRANSPARENT FALSE)
+
+sprite(NAME car2
+ X 0
+ Y 0
+ BPP 4
+ CX 0
+ CY 0
+ TRANSPARENT TRUE)
+
+sprite(NAME building1
+ X 0
+ Y 0
+ BPP 4
+ CX 0
+ CY 0
+ TRANSPARENT TRUE)
+
+sprite(NAME building2
+ X 0
+ Y 0
+ BPP 4
+ CX 0
+ CY 0
+ TRANSPARENT TRUE)
+
level(NAME city1)
container(NAME jancity
SPRITES
+ building1
+ building2
+ car1
+ car2
+ checkbox
grass
sidewalk
roof1
@@ -148,4 +281,15 @@ container(NAME jancity
unit4
unit5
unit6
+ sel_down_left
+ sel_down_right
+ sel_mid_down
+ sel_mid_top
+ sel_mid_v
+ sel_up_left
+ sel_up_right
+ line_edit_left
+ line_edit_mid
+ line_edit_right
+ pavement
)
diff --git a/res/btn_left.bmp b/res/btn_left.bmp
deleted file mode 100644
index 7d8ee4e..0000000
--- a/res/btn_left.bmp
+++ /dev/null
Binary files differ
diff --git a/res/btn_left_24.bmp b/res/btn_left_24.bmp
index 36e2370..2ab8bf0 100644
--- a/res/btn_left_24.bmp
+++ b/res/btn_left_24.bmp
Binary files differ
diff --git a/res/btn_mid.bmp b/res/btn_mid.bmp
deleted file mode 100644
index 801e0d5..0000000
--- a/res/btn_mid.bmp
+++ /dev/null
Binary files differ
diff --git a/res/btn_mid_24.bmp b/res/btn_mid_24.bmp
index f7a0ca0..fb2e82f 100644
--- a/res/btn_mid_24.bmp
+++ b/res/btn_mid_24.bmp
Binary files differ
diff --git a/res/btn_right.bmp b/res/btn_right.bmp
deleted file mode 100644
index ae7cc85..0000000
--- a/res/btn_right.bmp
+++ /dev/null
Binary files differ
diff --git a/res/btn_right_24.bmp b/res/btn_right_24.bmp
index 26da50f..c56b308 100644
--- a/res/btn_right_24.bmp
+++ b/res/btn_right_24.bmp
Binary files differ
diff --git a/res/btn_small.bmp b/res/btn_small.bmp
new file mode 100644
index 0000000..43dacf6
--- /dev/null
+++ b/res/btn_small.bmp
Binary files differ
diff --git a/res/btn_small_24.bmp b/res/btn_small_24.bmp
new file mode 100644
index 0000000..0f19504
--- /dev/null
+++ b/res/btn_small_24.bmp
Binary files differ
diff --git a/res/car1_24.bmp b/res/car1_24.bmp
new file mode 100644
index 0000000..cb7475f
--- /dev/null
+++ b/res/car1_24.bmp
Binary files differ
diff --git a/res/car2_24.bmp b/res/car2_24.bmp
new file mode 100644
index 0000000..6ca8f3d
--- /dev/null
+++ b/res/car2_24.bmp
Binary files differ
diff --git a/res/checkbox_24.bmp b/res/checkbox_24.bmp
new file mode 100644
index 0000000..00bfe00
--- /dev/null
+++ b/res/checkbox_24.bmp
Binary files differ
diff --git a/res/city1.txt b/res/city1.txt
index 35aa10f..88ec6cc 100644
--- a/res/city1.txt
+++ b/res/city1.txt
@@ -1,21 +1,31 @@
-24 16
+24 24
-0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
-0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
-0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
-0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00
+0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00
+0009 0009 0009 0009 0009 0009 0009 0009 0009 0009 0009 0009 0009 0009 0009 0009 0009 0009 0009 0009 0009 0009 0009 0009
+0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011
-0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
-0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
-0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
-0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+0053 0054 0054 0054 0054 0054 0054 0054 0053 0054 0054 0054 0054 0054 0054 0054 0054 0054 0054 0053 0054 0054 0054 0054
+0048 0049 0049 0049 0049 0049 0049 0049 0048 0049 0049 0049 0049 0049 0049 0049 0049 0049 0049 0048 0049 0049 0049 0049
+0055 0056 0056 0056 0056 0056 0056 0056 0055 0056 0056 0056 0056 0056 0056 0056 0050 005e 0051 0055 0056 0056 0056 0056
+0001 0001 0001 0001 0001 0001 0001 0001 0001 0001 0001 0001 0001 0001 0001 0002 004a 004b 004c 0000 0001 0001 0001 0001
-0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
-0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
-0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
-0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+0009 0009 0009 0009 0009 0009 0009 0009 0009 0009 0009 0009 0009 0009 0009 000a 0057 0058 0059 0008 0000 0000 0000 0000
+0030 0031 0031 0032 0000 0000 0000 0000 0030 0031 0031 0032 0000 0000 0009 000a 0057 0058 0059 0008 0000 0000 0000 0000
+0038 0039 0039 003a 0000 0000 0000 0000 0038 0039 0039 003a 0000 0000 0009 000a 0057 0058 0059 0008 0000 0000 0000 0000
+0040 0041 0041 0042 0000 0000 0000 0000 0040 0041 0041 0042 0000 0000 0009 000a 0057 0058 0059 0008 0000 0000 0000 0000
-0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
-0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
-0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
-0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+0062 0063 0064 0062 0a00 0a00 0a00 0a00 0062 0063 0064 0062 0a00 0a00 0a00 0a00 0057 0058 0059 0008 0a00 0a00 0a00 0a00
+0069 006a 006c 0069 0a00 0a00 0a00 0a00 0069 006a 006c 0069 0a00 0a00 0a00 0a00 0057 0058 0059 0008 0a00 0a00 0a00 0a00
+0070 0071 0073 0070 0a00 0a00 0a00 0a00 0070 0071 0073 0070 0a00 0a00 0a00 0a00 0057 0058 0059 0008 0a00 0a00 0a00 0a00
+0077 0078 007a 0077 0a00 0a00 0a00 0a00 0077 0078 007a 0077 0a00 0a00 0a00 0a00 0057 0058 0059 0008 0a00 0a00 0a00 0a00
+
+0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00
+0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00
+0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00
+0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00
+
+0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00
+0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00
+0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00
+0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00 0a00
diff --git a/res/font.bmp b/res/font.bmp
new file mode 100644
index 0000000..7fc1c36
--- /dev/null
+++ b/res/font.bmp
Binary files differ
diff --git a/res/font_24.bmp b/res/font_24.bmp
new file mode 100644
index 0000000..b12a8ce
--- /dev/null
+++ b/res/font_24.bmp
Binary files differ
diff --git a/res/functions.cmake b/res/functions.cmake
index 723e922..2a7e7c3 100644
--- a/res/functions.cmake
+++ b/res/functions.cmake
@@ -35,6 +35,7 @@ function(sprite)
VERBATIM)
add_custom_target(${SPRITE_NAME}_img
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${SPRITE_NAME})
+ add_dependencies(${PROJECT_NAME} ${SPRITE_NAME}_img)
add_dependencies(${SPRITE_NAME}_img tools)
endif()
endfunction()
@@ -73,6 +74,7 @@ function(sound)
VERBATIM)
add_custom_target(${SOUND_NAME}_snd
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${SOUND_NAME})
+ add_dependencies(${PROJECT_NAME} ${SOUND_NAME}_snd)
add_dependencies(${SOUND_NAME}_snd tools)
endif()
endfunction()
diff --git a/res/line_edit_left_24.bmp b/res/line_edit_left_24.bmp
new file mode 100644
index 0000000..dd977f6
--- /dev/null
+++ b/res/line_edit_left_24.bmp
Binary files differ
diff --git a/res/line_edit_mid_24.bmp b/res/line_edit_mid_24.bmp
new file mode 100644
index 0000000..ca934a0
--- /dev/null
+++ b/res/line_edit_mid_24.bmp
Binary files differ
diff --git a/res/line_edit_right_24.bmp b/res/line_edit_right_24.bmp
new file mode 100644
index 0000000..f9cf4e0
--- /dev/null
+++ b/res/line_edit_right_24.bmp
Binary files differ
diff --git a/res/sel_down_left_24.bmp b/res/sel_down_left_24.bmp
new file mode 100644
index 0000000..98caa7f
--- /dev/null
+++ b/res/sel_down_left_24.bmp
Binary files differ
diff --git a/res/sel_down_right_24.bmp b/res/sel_down_right_24.bmp
new file mode 100644
index 0000000..01db4c2
--- /dev/null
+++ b/res/sel_down_right_24.bmp
Binary files differ
diff --git a/res/sel_mid_down_24.bmp b/res/sel_mid_down_24.bmp
new file mode 100644
index 0000000..20a2f71
--- /dev/null
+++ b/res/sel_mid_down_24.bmp
Binary files differ
diff --git a/res/sel_mid_top_24.bmp b/res/sel_mid_top_24.bmp
new file mode 100644
index 0000000..79c3a5b
--- /dev/null
+++ b/res/sel_mid_top_24.bmp
Binary files differ
diff --git a/res/sel_mid_v_24.bmp b/res/sel_mid_v_24.bmp
new file mode 100644
index 0000000..e9093ae
--- /dev/null
+++ b/res/sel_mid_v_24.bmp
Binary files differ
diff --git a/res/sel_up_left_24.bmp b/res/sel_up_left_24.bmp
new file mode 100644
index 0000000..65cb7d3
--- /dev/null
+++ b/res/sel_up_left_24.bmp
Binary files differ
diff --git a/res/sel_up_right_24.bmp b/res/sel_up_right_24.bmp
new file mode 100644
index 0000000..2bdefd3
--- /dev/null
+++ b/res/sel_up_right_24.bmp
Binary files differ
diff --git a/res/unit5_24.bmp b/res/unit5_24.bmp
index 5d9225a..5447f6e 100644
--- a/res/unit5_24.bmp
+++ b/res/unit5_24.bmp
Binary files differ
diff --git a/src/building/inc/building.h b/src/building/inc/building.h
index 7c7d45f..88840f5 100644
--- a/src/building/inc/building.h
+++ b/src/building/inc/building.h
@@ -33,7 +33,7 @@ void building_set_alive_cb(void (*f)(const struct util_rect *dim, bool alive, vo
int building_render(const struct building *b, const struct camera *cam, bool sel);
const char *building_str(const struct building *b);
-extern struct sprite building_sprites[MAX_BUILDING_TYPES];
+extern struct sprite building_sprites[1];
#ifdef __cplusplus
}
diff --git a/src/building/src/building.c b/src/building/src/building.c
index 826ebe1..ee1ee84 100644
--- a/src/building/src/building.c
+++ b/src/building/src/building.c
@@ -4,7 +4,7 @@
#include <stdbool.h>
#include <stddef.h>
-struct sprite building_sprites[MAX_BUILDING_TYPES];
+struct sprite building_sprites[1];
int building_render(const struct building *const b,
const struct camera *const cam, const bool sel)
diff --git a/src/camera/inc/camera.h b/src/camera/inc/camera.h
index 27efe2e..96a64d5 100644
--- a/src/camera/inc/camera.h
+++ b/src/camera/inc/camera.h
@@ -18,7 +18,7 @@ struct camera
long w, h;
} dim;
- int x, y, x_speed, y_speed;
+ long x, y, x_speed, y_speed;
unsigned xt, yt;
bool pan;
@@ -28,6 +28,7 @@ struct camera
enum
{
CURSOR_STATE_IDLE,
+ CURSOR_STATE_HOVERING,
CURSOR_STATE_PRESSED
} state;
struct
diff --git a/src/camera/src/camera.c b/src/camera/src/camera.c
index 9d3d062..5e658a5 100644
--- a/src/camera/src/camera.c
+++ b/src/camera/src/camera.c
@@ -55,9 +55,13 @@ int cursor_render(const struct cursor *const c)
case CURSOR_STATE_IDLE:
break;
- case CURSOR_STATE_PRESSED:
+ case CURSOR_STATE_HOVERING:
s->u += CAMERA_CURSOR_WIDTH;
break;
+
+ case CURSOR_STATE_PRESSED:
+ s->u += CAMERA_CURSOR_WIDTH * 2;
+ break;
}
const int ret = sprite_sort(s);
@@ -89,23 +93,24 @@ void cursor_init(struct cursor *const c)
void camera_update_pos(struct camera *const cam)
{
- const int x = cam->x + cam->x_speed;
+ const struct camera_dim *const d = &cam->dim;
+
+ if (!d->w || !d->h)
+ return;
- cam->x = x;
+ cam->x += cam->x_speed;
if (cam->x > 0)
cam->x = 0;
- else if (cam->x < -cam->dim.w)
- cam->x = -cam->dim.w;
-
- const int y = cam->y + cam->y_speed;
+ else if (cam->x < -d->w + screen_w)
+ cam->x = -d->w + screen_w;
- cam->y = y;
+ cam->y += cam->y_speed;
if (cam->y > 0)
cam->y = 0;
- else if (cam->y < -cam->dim.h)
- cam->y = -cam->dim.h;
+ else if (cam->y < -d->h + screen_h)
+ cam->y = -d->h + screen_h;
}
bool camera_translate(const struct camera *const cam, const struct util_rect *const dim,
diff --git a/src/camera/src/mouse.c b/src/camera/src/mouse.c
index 30fedb9..e7b144b 100644
--- a/src/camera/src/mouse.c
+++ b/src/camera/src/mouse.c
@@ -13,9 +13,14 @@ static void cursor_update(struct cursor *const c, const struct mouse *const m)
c->x = m->x;
c->y = m->y;
- c->state = mouse_pressed(m, MOUSE_BUTTON_LEFT) ||
- mouse_pressed(m, MOUSE_BUTTON_RIGHT) ?
- CURSOR_STATE_PRESSED: CURSOR_STATE_IDLE;
+
+ if (mouse_pressed(m, MOUSE_BUTTON_LEFT)
+ || mouse_pressed(m, MOUSE_BUTTON_RIGHT))
+ c->state = CURSOR_STATE_PRESSED;
+ else if (m->hovering)
+ c->state = CURSOR_STATE_HOVERING;
+ else
+ c->state = CURSOR_STATE_IDLE;
}
static void update_speed(struct camera *const cam, const struct mouse *const m)
@@ -24,34 +29,55 @@ static void update_speed(struct camera *const cam, const struct mouse *const m)
{
MAX_SPEED = 10,
STEP = 1,
- THRESHOLD_X = CAMERA_CURSOR_WIDTH / 2,
- THRESHOLD_Y = CAMERA_CURSOR_HEIGHT / 2
+ T_STEP = 10,
+ THRESHOLD_X = CAMERA_CURSOR_WIDTH,
+ THRESHOLD_Y = CAMERA_CURSOR_HEIGHT
};
const struct cursor *const c = &cam->cursor;
if (c->x >= screen_w - THRESHOLD_X)
{
- if (cam->x_speed - STEP > -MAX_SPEED)
- cam->x_speed -= STEP;
+ if (++cam->xt >= T_STEP)
+ {
+ cam->xt = 0;
+
+ if (cam->x_speed - STEP > -MAX_SPEED)
+ cam->x_speed -= STEP;
+ }
}
else if (c->x < THRESHOLD_X)
{
- if (cam->x_speed + STEP < MAX_SPEED)
- cam->x_speed += STEP;
+ if (++cam->xt >= T_STEP)
+ {
+ cam->xt = 0;
+
+ if (cam->x_speed + STEP < MAX_SPEED)
+ cam->x_speed += STEP;
+ }
}
else
cam->x_speed = 0;
if (c->y >= screen_h - THRESHOLD_Y)
{
- if (cam->y_speed - STEP > -MAX_SPEED)
- cam->y_speed -= STEP;
+ if (++cam->yt >= T_STEP)
+ {
+ cam->yt = 0;
+
+ if (cam->y_speed - STEP > -MAX_SPEED)
+ cam->y_speed -= STEP;
+ }
}
else if (c->y < THRESHOLD_Y)
{
- if (cam->y_speed + STEP < MAX_SPEED)
- cam->y_speed += STEP;
+ if (++cam->yt >= T_STEP)
+ {
+ cam->yt = 0;
+
+ if (cam->y_speed + STEP < MAX_SPEED)
+ cam->y_speed += STEP;
+ }
}
else
cam->y_speed = 0;
diff --git a/src/camera/src/pad.c b/src/camera/src/pad.c
index f3af527..b5dac1a 100644
--- a/src/camera/src/pad.c
+++ b/src/camera/src/pad.c
@@ -48,7 +48,7 @@ static void update_speed(struct camera *const cam,
{
MAX_SPEED = 10,
STEP = 1,
- T_STEP = 3
+ T_STEP = 2
};
const struct cursor *const c = &cam->cursor;
diff --git a/src/game/src/res.c b/src/game/src/res.c
index dead212..acbe174 100644
--- a/src/game/src/res.c
+++ b/src/game/src/res.c
@@ -108,6 +108,102 @@ static const struct container c[] =
.path = "unit6",
.type = CONTAINER_TYPE_SPRITE,
.data.sprite = &unit_sprites[UNIT_6_SPRITE]
+ },
+
+ {
+ .path = "sel_down_left",
+ .type = CONTAINER_TYPE_SPRITE,
+ .data.sprite = &gui_rounded_rect_sprites[GUI_ROUNDED_RECT_DOWN_LEFT]
+ },
+
+ {
+ .path = "sel_down_right",
+ .type = CONTAINER_TYPE_SPRITE,
+ .data.sprite = &gui_rounded_rect_sprites[GUI_ROUNDED_RECT_DOWN_RIGHT]
+ },
+
+ {
+ .path = "sel_mid_down",
+ .type = CONTAINER_TYPE_SPRITE,
+ .data.sprite = &gui_rounded_rect_sprites[GUI_ROUNDED_RECT_MID_DOWN]
+ },
+
+ {
+ .path = "sel_mid_top",
+ .type = CONTAINER_TYPE_SPRITE,
+ .data.sprite = &gui_rounded_rect_sprites[GUI_ROUNDED_RECT_MID_TOP]
+ },
+
+ {
+ .path = "sel_mid_v",
+ .type = CONTAINER_TYPE_SPRITE,
+ .data.sprite = &gui_rounded_rect_sprites[GUI_ROUNDED_RECT_MID_VERT]
+ },
+
+ {
+ .path = "sel_up_left",
+ .type = CONTAINER_TYPE_SPRITE,
+ .data.sprite = &gui_rounded_rect_sprites[GUI_ROUNDED_RECT_UP_LEFT]
+ },
+
+ {
+ .path = "sel_up_right",
+ .type = CONTAINER_TYPE_SPRITE,
+ .data.sprite = &gui_rounded_rect_sprites[GUI_ROUNDED_RECT_UP_RIGHT]
+ },
+
+ {
+ .path = "checkbox",
+ .type = CONTAINER_TYPE_SPRITE,
+ .data.sprite = &gui_checkbox_sprite
+ },
+
+ {
+ .path = "line_edit_left",
+ .type = CONTAINER_TYPE_SPRITE,
+ .data.sprite = &gui_line_edit_sprites[GUI_LINE_EDIT_LEFT]
+ },
+
+ {
+ .path = "line_edit_mid",
+ .type = CONTAINER_TYPE_SPRITE,
+ .data.sprite = &gui_line_edit_sprites[GUI_LINE_EDIT_MID]
+ },
+
+ {
+ .path = "line_edit_right",
+ .type = CONTAINER_TYPE_SPRITE,
+ .data.sprite = &gui_line_edit_sprites[GUI_LINE_EDIT_RIGHT]
+ },
+
+ {
+ .path = "car1",
+ .type = CONTAINER_TYPE_SPRITE,
+ .data.sprite = &unit_sprites[UNIT_CAR_1_SPRITE]
+ },
+
+ {
+ .path = "pavement",
+ .type = CONTAINER_TYPE_SPRITE,
+ .data.sprite = &terrain_sprites[PAVEMENT]
+ },
+
+ {
+ .path = "car2",
+ .type = CONTAINER_TYPE_SPRITE,
+ .data.sprite = &unit_sprites[UNIT_CAR_2_SPRITE]
+ },
+
+ {
+ .path = "building1",
+ .type = CONTAINER_TYPE_SPRITE,
+ .data.sprite = &terrain_sprites[BUILDING1],
+ },
+
+ {
+ .path = "building2",
+ .type = CONTAINER_TYPE_SPRITE,
+ .data.sprite = &terrain_sprites[BUILDING2],
}
};
diff --git a/src/gui/inc/gui/rounded_rect.h b/src/gui/inc/gui/rounded_rect.h
index 13242f4..b027b67 100644
--- a/src/gui/inc/gui/rounded_rect.h
+++ b/src/gui/inc/gui/rounded_rect.h
@@ -15,6 +15,7 @@ struct gui_rounded_rect
{
struct gui_common common;
unsigned short w, h;
+ unsigned char r, g, b;
bool adjust;
};
@@ -27,13 +28,15 @@ enum
GUI_ROUNDED_RECT_MID_VERT,
GUI_ROUNDED_RECT_DOWN_LEFT,
GUI_ROUNDED_RECT_DOWN_RIGHT,
- GUI_ROUNDED_RECT_MID,
+ GUI_ROUNDED_RECT_MID_TOP,
+ GUI_ROUNDED_RECT_MID_DOWN,
MAX_GUI_ROUNDED_RECT_SPRITES
};
extern struct sprite gui_rounded_rect_sprites[MAX_GUI_ROUNDED_RECT_SPRITES];
+/* Pad one line to avoid redefinition. */
UTIL_STATIC_ASSERT(!offsetof(struct gui_rounded_rect, common),
"unexpected offset for struct gui_rounded_rect");
diff --git a/src/gui/src/rounded_rect.c b/src/gui/src/rounded_rect.c
index 4ae3780..f37dcae 100644
--- a/src/gui/src/rounded_rect.c
+++ b/src/gui/src/rounded_rect.c
@@ -134,30 +134,36 @@ static int render_rect(const struct gui_rounded_rect *const r,
rect_get_or_ret(sel, -1);
semitrans_rect_init(sel);
- const struct sprite *const mid = &refs[GUI_ROUNDED_RECT_MID],
+ const struct sprite *const mid = &refs[GUI_ROUNDED_RECT_MID_TOP],
*const vert = &refs[GUI_ROUNDED_RECT_MID_VERT];
sel->x = x + vert->w;
sel->y = y + mid->h;
sel->w = r->w - (vert->w * 2);
sel->h = r->h - (mid->h * 2);
- sel->r = 72;
- sel->g = 66;
- sel->b = 56;
+ sel->r = r->r;
+ sel->g = r->g;
+ sel->b = r->b;
rect_sort(sel);
return 0;
}
static int render_mid(const struct gui_rounded_rect *const r,
- const short x, const short y)
+ const short x, const short y, const struct sprite *const s)
{
- const short mid_w = refs[GUI_ROUNDED_RECT_MID].w,
+ const short mid_w = s->w,
top_w = refs[GUI_ROUNDED_RECT_UP_LEFT].w,
w = r->w - (top_w * 2),
rem_mid = w % mid_w,
whole_mid = w / mid_w,
n_mid = rem_mid ? whole_mid + 1 : whole_mid;
+ if (n_mid < 0)
+ {
+ fprintf(stderr, "%s: invalid dimensions\n", __func__);
+ return -1;
+ }
+
for (struct
{
size_t i;
@@ -166,7 +172,7 @@ static int render_mid(const struct gui_rounded_rect *const r,
{
sprite_get_or_ret(m, -1);
- if (sprite_clone(&refs[GUI_ROUNDED_RECT_MID], m))
+ if (sprite_clone(s, m))
return -1;
m->x = a.x;
@@ -186,13 +192,15 @@ static int render_mid(const struct gui_rounded_rect *const r,
static int render_midtop(const struct gui_rounded_rect *const r,
const short x, const short y)
{
- return render_mid(r, x, y);
+ return render_mid(r, x, y, &refs[GUI_ROUNDED_RECT_MID_TOP]);
}
static int render_middown(const struct gui_rounded_rect *const r,
const short x, const short y)
{
- return render_mid(r, x, y + r->h - refs[GUI_ROUNDED_RECT_MID].h);
+ const struct sprite *const s = &refs[GUI_ROUNDED_RECT_MID_DOWN];
+
+ return render_mid(r, x, y + r->h - s->h, s);
}
static int render(const struct gui_common *const g)
@@ -242,8 +250,8 @@ static void add_child(struct gui_common *const parent,
short w, h;
const short ref_w = refs[GUI_ROUNDED_RECT_MID_VERT].w,
- ref_h = refs[GUI_ROUNDED_RECT_MID].h,
- min_w = ref_w * 2 + refs[GUI_ROUNDED_RECT_MID].w,
+ ref_h = refs[GUI_ROUNDED_RECT_MID_TOP].h,
+ min_w = ref_w * 2 + refs[GUI_ROUNDED_RECT_MID_TOP].w,
min_h = ref_h * 2 + refs[GUI_ROUNDED_RECT_MID_VERT].h;
child->cb->get_dim(child, &w, &h);
diff --git a/src/instance/CMakeLists.txt b/src/instance/CMakeLists.txt
index 2e777a9..3651400 100644
--- a/src/instance/CMakeLists.txt
+++ b/src/instance/CMakeLists.txt
@@ -1,3 +1,3 @@
add_library(instance "src/instance.c")
target_include_directories(instance PUBLIC "inc")
-target_link_libraries(instance PUBLIC camera gfx util)
+target_link_libraries(instance PUBLIC camera gfx util PRIVATE gui)
diff --git a/src/instance/src/instance.c b/src/instance/src/instance.c
index 1e9e039..91683f5 100644
--- a/src/instance/src/instance.c
+++ b/src/instance/src/instance.c
@@ -19,47 +19,18 @@ void instance_cyclic(void)
line_g_flip ^= true;
}
-static int draw_sel(const struct instance *const i, const short x, const short y)
-{
- enum {R = 0, G = 255, B = 0};
-
- stp_4line_get_or_ret(l, -1);
- stp_4line_init(l);
- l->x = l->vertices[2].x = l->vertices[3].x = x;
- l->y = l->vertices[0].y = l->vertices[3].y = y;
- l->vertices[0].x = l->vertices[1].x = x + i->r.w;
- l->vertices[1].y = l->vertices[2].y = y + i->r.h;
- l->r = R;
- l->g = line_g;
- l->b = B >> 2;
-
- for (size_t i = 0; i < sizeof l->vertices / sizeof *l->vertices; i++)
- {
- struct stp_4line_vtx *const v = &l->vertices[i];
-
- v->r = R;
- v->b = B;
- }
-
- l->vertices[0].g = l->vertices[2].g = UCHAR_MAX - line_g;
- l->vertices[1].g = l->vertices[3].g = line_g;
- stp_4line_sort(l);
- stp_4line_get_or_ret(ll, -1);
- *ll = *l;
- ll->x = ll->vertices[2].x = ll->vertices[3].x = l->x ? l->x - 1 : 0;
- ll->y = ll->vertices[0].y = ll->vertices[3].y = l->y ? l->y - 1 : 0;
- ll->vertices[0].x = ll->vertices[1].x = l->vertices[0].x + 1;
- ll->vertices[1].y = ll->vertices[2].y = l->vertices[1].y + 1;
- stp_4line_sort(ll);
- return 0;
-}
-
-static void render_sprite(struct sprite *const s,
+static int render_sprite(struct sprite *const s,
const struct instance_render_off *const off, const short x, const short y)
{
s->x = off ? x + off->x : x;
s->y = off ? y + off->y : y;
- sprite_sort(s);
+
+ const int ret = sprite_sort(s);
+
+ if (ret)
+ fprintf(stderr, "%s: sprite_sort failed\n", __func__);
+
+ return ret;
}
static void render_quad(const struct instance_render_quad *const rq,
@@ -99,9 +70,6 @@ int instance_render(const struct instance_render_cfg *const cfg)
{
const struct instance_render_off *const off = cfg->off;
- if (cfg->sel && draw_sel(i, x, y))
- return -1;
-
switch (cfg->prim_type)
{
case INSTANCE_RENDER_CFG_SPRITE:
@@ -120,10 +88,5 @@ int instance_render(const struct instance_render_cfg *const cfg)
int instance_render_target(const struct instance *const i,
const struct camera *const cam)
{
- short x, y;
-
- if (camera_translate(cam, &i->r, &x, &y))
- return draw_sel(i, x, y);
-
- return -1;
+ return 0;
}
diff --git a/src/menu/src/gamecfg_menu.c b/src/menu/src/gamecfg_menu.c
index 85a99d2..d85e7f6 100644
--- a/src/menu/src/gamecfg_menu.c
+++ b/src/menu/src/gamecfg_menu.c
@@ -736,9 +736,10 @@ int menu_gamecfg(struct menu_common *const c, struct net_host *const h,
if (start)
{
- struct game_cfg cfg =
+ const struct game_cfg cfg =
{
- .p = &c->p
+ .p = &c->p,
+ .map = "city1.txt"
};
return game(&cfg);
diff --git a/src/menu/src/main_menu.c b/src/menu/src/main_menu.c
index a7b9e73..8beed92 100644
--- a/src/menu/src/main_menu.c
+++ b/src/menu/src/main_menu.c
@@ -4,14 +4,27 @@
#include <gui/button.h>
#include <gui/container.h>
#include <gui/rounded_rect.h>
+#include <util.h>
#include <system.h>
#include <stdbool.h>
+enum role
+{
+ CREDITS_NAME_COPYRIGHT,
+ CREDITS_ROLE_GFX,
+ CREDITS_ROLE_PROGRAMMING,
+ CREDITS_ROLE_ENGINE,
+ CREDITS_ROLE_LANGUAGE,
+
+ MAX_CREDIT_ROLES
+};
+
struct main_menu
{
bool start, settings, exit;
struct gui_button play, settings_btn, exit_btn;
struct gui_container cnt;
+ struct gui_label title, roles[MAX_CREDIT_ROLES];
};
static int update(struct menu_common *const c, void *const arg)
@@ -34,6 +47,32 @@ static int render(const struct menu_common *const c, void *const arg)
return 0;
}
+static void update_roles(struct main_menu *const m)
+{
+ static const char *const roles[] =
+ {
+ [CREDITS_NAME_COPYRIGHT] = "(C) 2024 Xavier Del Campo Romero",
+ [CREDITS_ROLE_GFX] = "Gfx: Kenney, Ivan Voirol",
+ [CREDITS_ROLE_PROGRAMMING] = "Coding: me",
+ [CREDITS_ROLE_ENGINE] = "Engine: also me lol",
+ [CREDITS_ROLE_LANGUAGE] = "Written in good old C"
+ };
+
+ UTIL_STATIC_ASSERT(sizeof roles / sizeof *roles
+ == sizeof m->roles / sizeof *m->roles,
+ "unexpected sizes");
+
+ for (size_t i = 0; i < sizeof roles / sizeof *roles; i++)
+ {
+ struct gui_label *const l = &m->roles[i];
+
+ gui_label_init(l);
+ l->common.hcentered = true;
+ l->text = roles[i];
+ gui_add_child(&m->cnt.common, &l->common);
+ }
+}
+
int menu_main(struct menu_common *const c)
{
do
@@ -51,6 +90,15 @@ int menu_main(struct menu_common *const c)
}
{
+ struct gui_label *const l = &m.title;
+
+ gui_label_init(l);
+ l->common.hcentered = true;
+ l->text = "Jancity, a city sandbox";
+ gui_add_child(&m.cnt.common, &l->common);
+ }
+
+ {
struct gui_button *const b = &m.play;
gui_button_init(b, GUI_BUTTON_TYPE_1);
@@ -87,6 +135,8 @@ int menu_main(struct menu_common *const c)
gui_add_child(&m.cnt.common, &b->common);
}
+ update_roles(&m);
+
while (!m.start && !m.settings && !c->p.common.exit)
{
if (menu_update(c, update, render, &m))
diff --git a/src/menu/src/menu.c b/src/menu/src/menu.c
index cc508e7..682c7f2 100644
--- a/src/menu/src/menu.c
+++ b/src/menu/src/menu.c
@@ -34,9 +34,15 @@ int menu_update(struct menu_common *const c,
rect_sort(r);
if (render && render(c, arg))
+ {
+ fprintf(stderr, "%s: render cb failed\n", __func__);
return -1;
+ }
else if (input_render(&c->in, &c->p))
+ {
+ fprintf(stderr, "%s: input_render failed\n", __func__);
return -1;
+ }
switch (c->p.common.type)
{
@@ -53,7 +59,10 @@ int menu_update(struct menu_common *const c,
}
if (gfx_draw())
+ {
+ fprintf(stderr, "%s: gfx_draw failed\n", __func__);
return -1;
+ }
return 0;
}
@@ -72,11 +81,16 @@ int menu(void)
peripheral_init(&cfg, &c.p);
settings_load("settings.ini", &c.s);
- const struct game_cfg gcfg =
+#if 1
+
+ struct game_cfg gcfg =
{
- .p = &c.p,
- .map = "city1.txt"
+ .map = "city1.txt",
+ .p = &c.p
};
return game(&gcfg);
+#else
+ return menu_main(&c);
+#endif
}
diff --git a/src/mouse/inc/mouse.h b/src/mouse/inc/mouse.h
index 55d0227..44c4f5c 100644
--- a/src/mouse/inc/mouse.h
+++ b/src/mouse/inc/mouse.h
@@ -18,6 +18,7 @@ struct mouse
{
short x, y, dx, dy;
int mask, oldmask;
+ bool first_clicked, hovering;
};
void mouse_init(struct mouse *m);
diff --git a/src/mouse/sdl-1.2/src/mouse.c b/src/mouse/sdl-1.2/src/mouse.c
index 35fc030..dc10b0b 100644
--- a/src/mouse/sdl-1.2/src/mouse.c
+++ b/src/mouse/sdl-1.2/src/mouse.c
@@ -3,13 +3,21 @@
#include <stdint.h>
#include <inttypes.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
+#include <time.h>
static void mouse_click(const SDL_MouseButtonEvent *const ev,
struct mouse *const m)
{
int mask;
+ if (!m->first_clicked)
+ {
+ srand(time(NULL));
+ m->first_clicked = true;
+ }
+
switch (ev->button)
{
case 1:
diff --git a/src/peripheral/inc/peripheral.h b/src/peripheral/inc/peripheral.h
index b686eba..c4156db 100644
--- a/src/peripheral/inc/peripheral.h
+++ b/src/peripheral/inc/peripheral.h
@@ -25,7 +25,7 @@ union peripheral
struct peripheral_common
{
enum peripheral_type type;
- bool exit;
+ bool init, exit;
} common;
struct peripheral_pad
diff --git a/src/player/CMakeLists.txt b/src/player/CMakeLists.txt
index 3297619..b6c645a 100644
--- a/src/player/CMakeLists.txt
+++ b/src/player/CMakeLists.txt
@@ -18,4 +18,5 @@ target_link_libraries(player
util
PRIVATE
pad
- gui)
+ gui
+ terrain)
diff --git a/src/player/inc/human_player.h b/src/player/inc/human_player.h
index 9cfd498..19c4670 100644
--- a/src/player/inc/human_player.h
+++ b/src/player/inc/human_player.h
@@ -2,6 +2,9 @@
#define HUMAN_PLAYER_H
#include <camera.h>
+#include <gui/button.h>
+#include <gui/container.h>
+#include <gui/rounded_rect.h>
#include <keyboard.h>
#include <instance.h>
#include <input.h>
@@ -34,6 +37,15 @@ struct human_player
union peripheral *periph;
struct input in;
+ struct human_player_item
+ {
+ bool show;
+ struct gui_button show_btn;
+ struct gui_rounded_rect rr;
+ struct gui_container topcnt;
+ struct gui_button add_walker, add_car, exit;
+ } item;
+
struct sel_instance
{
enum sel_type
diff --git a/src/player/inc/player.h b/src/player/inc/player.h
index cc191ca..06463f9 100644
--- a/src/player/inc/player.h
+++ b/src/player/inc/player.h
@@ -18,7 +18,7 @@ typedef unsigned player_team;
enum
{
- PLAYER_MAX_UNITS = 5,
+ PLAYER_MAX_UNITS = 10,
PLAYER_MAX_BUILDINGS = 5
};
diff --git a/src/player/src/human_player.c b/src/player/src/human_player.c
index 6083ef3..b47f4dc 100644
--- a/src/player/src/human_player.c
+++ b/src/player/src/human_player.c
@@ -279,8 +279,7 @@ static void update_selected(struct human_player *const h)
{
struct sel_instance *const si = &h->sel[i];
- if (si->d.i
- && (!si->d.i->alive || si->type == INSTANCE_TYPE_UNIT))
+ if (si->d.i && !si->d.i->alive)
{
si->d.i = NULL;
h->n_sel--;
@@ -357,10 +356,26 @@ static void update_from_touch(struct human_player *const h,
}
}
+static bool hovering_units(const struct human_player *const h)
+{
+ const struct player *const pl = &h->pl;
+
+ for (size_t i = 0; i < sizeof pl->units / sizeof *pl->units; i++)
+ {
+ const struct unit *const u = &pl->units[i];
+ const struct instance *const in = &u->instance;
+
+ if (in->alive && cursor_collision(&h->cam, &in->r))
+ return true;
+ }
+
+ return false;
+}
+
static void update_from_keyboard_mouse(struct human_player *const h,
struct player_others *const o)
{
- const struct mouse *const m = &h->periph->kbm.mouse;
+ struct mouse *const m = &h->periph->kbm.mouse;
const struct keyboard *const k = &h->periph->kbm.keyboard;
const struct input *const in = &h->in;
@@ -377,6 +392,8 @@ static void update_from_keyboard_mouse(struct human_player *const h,
}
else if (input_mouse_justreleased(in, m, MOUSE_BUTTON_RIGHT))
move_units(h, o);
+ else
+ m->hovering = hovering_units(h);
}
void human_player_update(struct human_player *const h,
diff --git a/src/player/src/human_player_gui.c b/src/player/src/human_player_gui.c
index e985d9c..ce995c1 100644
--- a/src/player/src/human_player_gui.c
+++ b/src/player/src/human_player_gui.c
@@ -10,16 +10,146 @@
#include <gui/label.h>
#include <gui/progress_bar.h>
#include <gui/rounded_rect.h>
+#include <terrain.h>
#include <inttypes.h>
#include <limits.h>
#include <stddef.h>
#include <stdio.h>
#include <stdint.h>
-enum {X_OFF = 8, Y_OFF = 8, HP_Y = 32};
+enum {X_OFF = 8, Y_OFF = 8};
+
+static void on_item_pressed(void *const arg)
+{
+ bool *const show = arg;
+
+ *show ^= true;
+}
+
+static void on_add_car(void *const arg)
+{
+ struct human_player *const h = arg;
+ struct human_player_item *const it = &h->item;
+ const struct unit_cfg cfg =
+ {
+ .type = UNIT_CFG_TYPE_CAR,
+ .x = rand() % (MAP_W - 32),
+ .y = rand() % (MAP_H - 32),
+ };
+
+ player_create_unit(&cfg, &h->pl);
+ it->show = false;
+}
+
+static void on_add_walker(void *const arg)
+{
+ struct human_player *const h = arg;
+ struct human_player_item *const it = &h->item;
+ const struct unit_cfg cfg =
+ {
+ .type = UNIT_CFG_TYPE_WALKER,
+ .x = rand() % (MAP_W - 32),
+ .y = rand() % (MAP_H - 32),
+ };
+
+ player_create_unit(&cfg, &h->pl);
+ it->show = false;
+}
+
+static void on_exit(void *const arg)
+{
+ struct human_player *const h = arg;
+
+ h->periph->common.exit = true;
+}
+
+static void update_items(struct human_player *const h)
+{
+ struct human_player_item *const it = &h->item;
+
+ {
+ struct gui_rounded_rect *const r = &it->rr;
+
+ gui_rounded_rect_init(r);
+ r->common.hcentered = r->common.vcentered = true;
+ r->adjust = true;
+ }
+
+ {
+ struct gui_container *const c = &it->topcnt;
+
+ gui_container_init(c);
+ c->common.vcentered = true;
+ c->common.hcentered = true;
+ c->mode = GUI_CONTAINER_MODE_V;
+ c->spacing = 4;
+ gui_add_child(&it->rr.common, &c->common);
+ }
+
+ {
+ struct gui_button *const b = &it->add_car;
+
+ gui_button_init(b, GUI_BUTTON_TYPE_1);
+ b->common.hcentered = true;
+ b->u.type1.w = 80;
+ b->u.type1.label.text = "Add car";
+ b->on_pressed = on_add_car;
+ b->arg = h;
+ gui_add_child(&it->topcnt.common, &b->common);
+ }
+
+ {
+ struct gui_button *const b = &it->add_walker;
+
+ gui_button_init(b, GUI_BUTTON_TYPE_1);
+ b->u.type1.w = 80;
+ b->common.hcentered = true;
+ b->u.type1.label.text = "Add walker";
+ b->on_pressed = on_add_walker;
+ b->arg = h;
+ gui_add_child(&it->topcnt.common, &b->common);
+ }
+
+ {
+ struct gui_button *const b = &it->exit;
+
+ gui_button_init(b, GUI_BUTTON_TYPE_1);
+ b->u.type1.w = 80;
+ b->common.hcentered = true;
+ b->u.type1.label.text = "Exit";
+ b->on_pressed = on_exit;
+ b->arg = h;
+ gui_add_child(&it->topcnt.common, &b->common);
+ }
+
+ struct camera cam =
+ {
+ .cursor = h->cam.cursor
+ };
+
+ gui_update(&it->rr.common, h->periph, &cam, &h->in);
+}
void human_player_gui_update(struct human_player *const h)
{
+ struct human_player_item *const it = &h->item;
+ struct gui_button *const b = &it->show_btn;
+
+ gui_button_init(b, GUI_BUTTON_TYPE_SPRITE);
+ b->on_pressed = on_item_pressed;
+ b->arg = &it->show;
+ b->u.sprite.s = &gui_button_sprites[GUI_BUTTON_SMALL];
+ b->common.x = screen_w - b->u.sprite.s->w;
+
+ if (it->show)
+ update_items(h);
+
+ struct camera cam =
+ {
+ .cursor = h->cam.cursor
+ };
+
+ gui_update(&b->common, h->periph, &cam, &h->in);
}
static int render_sel_single_building(const struct human_player *const h,
@@ -41,14 +171,13 @@ static int render_sel_single_unit(const struct human_player *const h,
const struct sel_instance *const sel, struct gui_common *const r)
{
const struct unit *const u = sel->d.u;
- enum {CARRY_X = 96, CARRY_Y = 8};
struct gui_label ul;
gui_label_init(&ul);
- ul.common.x = X_OFF;
- ul.common.y = Y_OFF;
- ul.text = unit_str(u);
+ ul.common.hcentered = true;
+ ul.common.vcentered = true;
+ ul.text = u->name;
gui_add_child(r, &ul.common);
return gui_render(r);
@@ -99,37 +228,44 @@ static int render_sel_multiple(const struct human_player *const h,
static int render_top(const struct human_player *const h)
{
- struct gui_button b;
-
- gui_button_init(&b, GUI_BUTTON_TYPE_SPRITE);
- b.on_pressed = NULL;
- b.arg = NULL;
- b.u.sprite.s = &gui_button_sprites[GUI_BUTTON_SMALL];
- b.common.x = screen_w - b.u.sprite.s->w;
-
- return gui_render(&b.common);
+ return gui_render(&h->item.show_btn.common);
}
static int render_sel(const struct human_player *const h)
{
+ const short wlim = 120;
struct gui_rounded_rect r;
+ short exp_w;
gui_rounded_rect_init(&r);
- r.common.x = 16;
- r.w = screen_w - (r.common.x * 2);
- r.h = screen_h / 4;
+ r.common.hcentered = true;
+ exp_w = screen_w - 32;
+ r.w = exp_w > wlim ? wlim : exp_w;
+ r.h = 40;
+ r.r = 10;
+ r.g = 137;
+ r.b = 225;
r.common.y = screen_h - r.h;
return h->n_sel == 1 ? render_sel_single(h, &r.common)
: render_sel_multiple(h, &r.common);
}
+static int render_items(const struct human_player *const h)
+{
+ const struct human_player_item *const it = &h->item;
+
+ return gui_render(&it->rr.common);
+}
+
int human_player_gui_render(const struct human_player *const h)
{
if (render_top(h))
return -1;
else if (h->n_sel && render_sel(h))
return -1;
+ else if (h->item.show && render_items(h))
+ return -1;
return 0;
}
diff --git a/src/player/src/player.c b/src/player/src/player.c
index 5a69763..a3b0a52 100644
--- a/src/player/src/player.c
+++ b/src/player/src/player.c
@@ -1,6 +1,7 @@
#include <player.h>
#include <building.h>
#include <unit.h>
+#include <terrain.h>
#include <stddef.h>
void player_update(struct player *const p)
@@ -61,6 +62,22 @@ int player_create_building(const struct building_cfg *const cfg, struct player *
int player_init(const struct player_cfg *const cfg, struct player *const pl)
{
+ for (size_t i = 0; i < sizeof pl->units / sizeof *pl->units; i++)
+ {
+ const struct unit_cfg ucfg =
+ {
+ .type = rand() & 1 ? UNIT_CFG_TYPE_WALKER : UNIT_CFG_TYPE_CAR,
+ .x = rand() % (MAP_W - 32),
+ .y = rand() % (MAP_H - 32),
+ };
+
+ if (player_create_unit(&ucfg, pl))
+ {
+ fprintf(stderr, "%s: player_create_unit failed\n", __func__);
+ return -1;
+ }
+ }
+
pl->alive = true;
pl->color = cfg->color;
pl->team = cfg->team;
diff --git a/src/terrain/inc/terrain.h b/src/terrain/inc/terrain.h
index 7997025..dc29883 100644
--- a/src/terrain/inc/terrain.h
+++ b/src/terrain/inc/terrain.h
@@ -13,7 +13,7 @@ extern "C"
enum
{
- MAP_TILES = 120,
+ MAP_TILES = 24,
TERRAIN_SZ = 16,
MAP_W = MAP_TILES * TERRAIN_SZ,
MAP_H = MAP_TILES * TERRAIN_SZ
@@ -39,7 +39,9 @@ enum
GRASS,
ROOF1,
ROOF2,
+ PAVEMENT,
BUILDING1,
+ BUILDING2,
MAX_TERRAIN_SPRITES
};
diff --git a/src/terrain/privinc/terrain_tiles.h b/src/terrain/privinc/terrain_tiles.h
index 962bafe..89b8457 100644
--- a/src/terrain/privinc/terrain_tiles.h
+++ b/src/terrain/privinc/terrain_tiles.h
@@ -15,7 +15,6 @@ enum
SIDEWALK_2_NW,
SIDEWALK_2_NE,
SIDEWALK_3_NW,
- SIDEWALK_3_N,
SIDEWALK_3_NE,
SIDEWALK_4_N,
@@ -25,7 +24,6 @@ enum
SIDEWALK_2_SW,
SIDEWALK_2_SE,
SIDEWALK_3_SW,
- SIDEWALK_3_S,
SIDEWALK_3_SE,
SIDEWALK_4_C,
@@ -49,7 +47,6 @@ enum
ROOF1_2_NE,
ROOF1_3_NW,
ROOF1_3_N,
- ROOF1_3_NE,
ROOF1_4_N,
ROOF1_1_W,
@@ -58,7 +55,6 @@ enum
ROOF1_2_SW,
ROOF1_2_SE,
ROOF1_3_SW,
- ROOF1_3_S,
ROOF1_3_SE,
ROOF1_4_C,
@@ -82,7 +78,6 @@ enum
ROOF2_2_NE,
ROOF2_3_NW,
ROOF2_3_N,
- ROOF2_3_NE,
ROOF2_4_N,
ROOF2_1_W,
@@ -91,7 +86,6 @@ enum
ROOF2_2_SW,
ROOF2_2_SE,
ROOF2_3_SW,
- ROOF2_3_S,
ROOF2_3_SE,
ROOF2_4_C,
@@ -105,7 +99,111 @@ enum
ROOF2_4_S,
ROOF2_START = ROOF2_1_NW,
- ROOF2_END = ROOF2_4_S
+ ROOF2_END = ROOF2_4_S,
+
+ /* PAVEMENT */
+ PAVEMENT_CW_H_MID,
+ PAVEMENT_STR_MID_H_1,
+ PAVEMENT_CW_V_LEFT,
+ PAVEMENT_CW_V_MID,
+ PAVEMENT_CW_V_RIGHT,
+ PAVEMENT_RND_NW,
+ PAVEMENT_RND_NE,
+ PAVEMENT_SP_NW,
+ PAVEMENT_SP_NE,
+ PAVEMENT_1,
+ PAVEMENT_P,
+ PAVEMENT_CW_H_TOP,
+ PAVEMENT_STR_H_TOP,
+
+ PAVEMENT_CW_H_DOWN,
+ PAVEMENT_STR_H_DOWN,
+ PAVEMENT_STR_V_LEFT,
+ PAVEMENT_STR_V_MID,
+ PAVEMENT_STR_V_RIGHT,
+ PAVEMENT_RND_SW,
+ PAVEMENT_RND_SE,
+ PAVEMENT_SP_SW,
+ PAVEMENT_SP_SE,
+ PAVEMENT_2,
+ PAVEMENT_BIKE,
+ PAVEMENT_PLUS,
+ PAVEMENT_EMPTY,
+
+ PAVEMENT_START = PAVEMENT_CW_H_MID,
+ PAVEMENT_END = PAVEMENT_EMPTY,
+
+ /* BUILDING1 */
+ BUILDING1_1_N,
+ BUILDING1_2_NW,
+ BUILDING1_2_N,
+ BUILDING1_2_NE,
+ BUILDING1_3_NW,
+ BUILDING1_3_N,
+ BUILDING1_3_NE,
+
+ BUILDING1_1_C_1,
+ BUILDING1_2_W_1,
+ BUILDING1_2_C_1,
+ BUILDING1_2_E_1,
+ BUILDING1_3_W_1,
+ BUILDING1_3_C_1,
+ BUILDING1_3_E_1,
+
+ BUILDING1_1_C_2,
+ BUILDING1_2_W_2,
+ BUILDING1_2_C_2,
+ BUILDING1_2_E_2,
+ BUILDING1_3_W_2,
+ BUILDING1_3_C_2,
+ BUILDING1_3_E_2,
+
+ BUILDING1_1_S,
+ BUILDING1_2_SW,
+ BUILDING1_2_S,
+ BUILDING1_2_SE,
+ BUILDING1_3_SW,
+ BUILDING1_3_S,
+ BUILDING1_3_SE,
+
+ BUILDING1_START = BUILDING1_1_N,
+ BUILDING1_END = BUILDING1_2_SE,
+
+ /* BUILDING2 */
+ BUILDING2_1_N,
+ BUILDING2_2_NW,
+ BUILDING2_2_N,
+ BUILDING2_2_NE,
+ BUILDING2_3_NW,
+ BUILDING2_3_N,
+ BUILDING2_3_NE,
+
+ BUILDING2_1_C_1,
+ BUILDING2_2_W_1,
+ BUILDING2_2_C_1,
+ BUILDING2_2_E_1,
+ BUILDING2_3_W_1,
+ BUILDING2_3_C_1,
+ BUILDING2_3_E_1,
+
+ BUILDING2_1_C_2,
+ BUILDING2_2_W_2,
+ BUILDING2_2_C_2,
+ BUILDING2_2_E_2,
+ BUILDING2_3_W_2,
+ BUILDING2_3_C_2,
+ BUILDING2_3_E_2,
+
+ BUILDING2_1_S,
+ BUILDING2_2_SW,
+ BUILDING2_2_S,
+ BUILDING2_2_SE,
+ BUILDING2_3_SW,
+ BUILDING2_3_S,
+ BUILDING2_3_SE,
+
+ BUILDING2_START = BUILDING2_1_N,
+ BUILDING2_END = BUILDING2_3_SE
};
enum
@@ -119,7 +217,6 @@ enum
GRASS_2_NW,
GRASS_2_NE,
GRASS_3_NW,
- GRASS_3_N,
GRASS_3_NE,
GRASS_4_N,
@@ -129,7 +226,6 @@ enum
GRASS_2_SW,
GRASS_2_SE,
GRASS_3_SW,
- GRASS_3_S,
GRASS_3_SE,
GRASS_4_C,
diff --git a/src/terrain/src/init.c b/src/terrain/src/init.c
index 88140d8..c16859c 100644
--- a/src/terrain/src/init.c
+++ b/src/terrain/src/init.c
@@ -133,6 +133,8 @@ int terrain_init(const char *const path, struct terrain_map *const map)
FILE *const f = fopen(path, "rb");
unsigned w, h;
+ *map = (const struct terrain_map){0};
+
if (!f)
{
fprintf(stderr, "%s: fopen(3): %s\n", __func__, strerror(errno));
diff --git a/src/terrain/src/render.c b/src/terrain/src/render.c
index 8b35d95..bfa1e74 100644
--- a/src/terrain/src/render.c
+++ b/src/terrain/src/render.c
@@ -22,7 +22,7 @@ struct tile
static int render_tile(const unsigned char id, const short x,
const short y, const struct tile *const tiles, const size_t n)
{
- for (size_t i = 0; i < n / n; i++)
+ for (size_t i = 0; i < n; i++)
{
const struct tile *const rt = &tiles[i];
@@ -37,7 +37,8 @@ static int render_tile(const unsigned char id, const short x,
}
const unsigned char pos = id - rt->start;
- const short tx = pos % TERRAIN_SZ, ty = pos / TERRAIN_SZ;
+ const short tx = pos % (s->w / TERRAIN_SZ),
+ ty = (pos * TERRAIN_SZ) / s->w;
s->x = x;
s->y = y;
@@ -67,7 +68,10 @@ static int render_ground(const struct terrain_tile *const t, const short x,
#define TILE(t) {.s = &terrain_sprites[t], .start = t##_START, .end = t##_END}
TILE(SIDEWALK),
TILE(ROOF1),
- TILE(ROOF2)
+ TILE(ROOF2),
+ TILE(PAVEMENT),
+ TILE(BUILDING1),
+ TILE(BUILDING2)
#undef TILE
};
diff --git a/src/unit/inc/unit.h b/src/unit/inc/unit.h
index 8d3e1bf..c9abafe 100644
--- a/src/unit/inc/unit.h
+++ b/src/unit/inc/unit.h
@@ -33,17 +33,14 @@ struct unit
{
struct instance instance;
enum unit_type type;
+ const char *name;
enum unit_dir
{
- UNIT_DIR_N,
- UNIT_DIR_NE,
- UNIT_DIR_E,
- UNIT_DIR_SE,
- UNIT_DIR_S,
- UNIT_DIR_SW,
UNIT_DIR_W,
- UNIT_DIR_NW
+ UNIT_DIR_S,
+ UNIT_DIR_N,
+ UNIT_DIR_E
} dir;
enum unit_state state;
@@ -61,7 +58,12 @@ UTIL_STATIC_ASSERT(!offsetof(struct unit, instance), "must be at offset zero");
struct unit_cfg
{
- enum unit_type type;
+ enum
+ {
+ UNIT_CFG_TYPE_WALKER,
+ UNIT_CFG_TYPE_CAR
+ } type;
+
unsigned long x, y;
};
@@ -72,7 +74,6 @@ bool unit_target_valid(const struct unit *u, const struct unit_target *t);
void unit_set_target(struct unit *u, const struct unit_target *t);
void unit_move_to(struct unit *u, unsigned long x, unsigned long y);
void unit_update(struct unit *u);
-const char *unit_str(const struct unit *u);
enum
{
@@ -82,6 +83,8 @@ enum
UNIT_4_SPRITE,
UNIT_5_SPRITE,
UNIT_6_SPRITE,
+ UNIT_CAR_1_SPRITE,
+ UNIT_CAR_2_SPRITE,
MAX_UNIT_SPRITES
};
diff --git a/src/unit/inc/unit_type.h b/src/unit/inc/unit_type.h
index f023784..ea59856 100644
--- a/src/unit/inc/unit_type.h
+++ b/src/unit/inc/unit_type.h
@@ -3,6 +3,15 @@
enum unit_type
{
+ UNIT_TYPE_1,
+ UNIT_TYPE_2,
+ UNIT_TYPE_3,
+ UNIT_TYPE_4,
+ UNIT_TYPE_5,
+ UNIT_TYPE_6,
+ UNIT_TYPE_CAR_1,
+ UNIT_TYPE_CAR_2,
+
MAX_UNIT_TYPES
};
diff --git a/src/unit/src/unit.c b/src/unit/src/unit.c
index 1bb1e0f..43dcc86 100644
--- a/src/unit/src/unit.c
+++ b/src/unit/src/unit.c
@@ -11,7 +11,7 @@
struct sprite unit_sprites[MAX_UNIT_SPRITES];
struct sound unit_sounds[MAX_UNIT_SOUNDS];
-enum {N_FRAMES = 5};
+static const unsigned char anim[] = {0, 1, 0, 2};
static void move_unit(struct unit *const u, const fix16_t sx, const fix16_t sy)
{
@@ -21,38 +21,18 @@ static void move_unit(struct unit *const u, const fix16_t sx, const fix16_t sy)
u->ry -= sy;
break;
- case UNIT_DIR_NE:
- u->rx += sx;
- u->ry -= sy;
- break;
-
case UNIT_DIR_E:
u->rx += sx;
break;
- case UNIT_DIR_SE:
- u->rx += sx;
- u->ry += sy;
- break;
-
case UNIT_DIR_S:
u->ry += sy;
break;
- case UNIT_DIR_SW:
- u->rx -= sx;
- u->ry += sy;
- break;
-
case UNIT_DIR_W:
u->rx -= sx;
break;
- case UNIT_DIR_NW:
- u->rx -= sx;
- u->ry -= sy;
- break;
-
default:
break;
}
@@ -61,17 +41,51 @@ static void move_unit(struct unit *const u, const fix16_t sx, const fix16_t sy)
static void get_speed(const struct unit *const u, fix16_t *const x,
fix16_t *const y)
{
- static const struct speed
+ struct speed
{
fix16_t x, y;
- } speed[1];
+ } s;
+
+ switch (u->type)
+ {
+ case UNIT_TYPE_1:
+ case UNIT_TYPE_2:
+ case UNIT_TYPE_3:
+ case UNIT_TYPE_4:
+ case UNIT_TYPE_5:
+ case UNIT_TYPE_6:
+ {
+ static const struct speed ref =
+ {
+ .x = FIX16_C_FROM_FLOAT(0.4),
+ .y = FIX16_C_FROM_FLOAT(0.4)
+ };
+
+ s = ref;
+ }
+ break;
+
+ case UNIT_TYPE_CAR_1:
+ case UNIT_TYPE_CAR_2:
+ {
+ static const struct speed ref =
+ {
+ .x = FIX16_C_FROM_FLOAT(1.5),
+ .y = FIX16_C_FROM_FLOAT(1.5)
+ };
+
+ s = ref;
+ }
+
+ case MAX_UNIT_TYPES:
+ break;
+ }
- const struct speed *const s = &speed[u->type];
const int dx = abs(u->rx - u->tx);
const int dy = abs(u->ry - u->ty);
- *x = dx < s->x ? dx : s->x;
- *y = dy < s->y ? dy : s->y;
+ *x = dx < s.x ? dx : s.x;
+ *y = dy < s.y ? dy : s.y;
}
static enum unit_dir get_direction(const struct unit *const u)
@@ -79,18 +93,7 @@ static enum unit_dir get_direction(const struct unit *const u)
const fix16_t x = u->rx, y = u->ry, tx = u->tx, ty = u->ty;
enum unit_dir dir = 0;
- if (x != tx && y != ty)
- {
- if (x > tx && y > ty)
- dir = UNIT_DIR_NW;
- else if (x < tx && y > ty)
- dir = UNIT_DIR_NE;
- else if (x < tx && y < ty)
- dir = UNIT_DIR_SE;
- else
- dir = UNIT_DIR_SW;
- }
- else if (x != tx)
+ if (x != tx)
{
if (x > tx)
dir = UNIT_DIR_W;
@@ -155,7 +158,7 @@ static bool must_move(const struct unit *const u)
void unit_update(struct unit *const u)
{
- const struct instance *const i = &u->instance;
+ struct instance *const i = &u->instance;
if (!i->alive)
return;
@@ -170,13 +173,13 @@ void unit_update(struct unit *const u)
get_speed(u, &x_step, &y_step);
move_unit(u, x_step, y_step);
- enum {FRAME_RATE = 6};
+ enum {FRAME_RATE = 10};
if (++u->frame.t >= FRAME_RATE)
{
u->frame.t = 0;
- if (++u->frame.i >= N_FRAMES)
+ if (++u->frame.i >= sizeof anim / sizeof *anim)
u->frame.i = 0;
}
@@ -185,8 +188,8 @@ void unit_update(struct unit *const u)
else
u->frame.i = 0;
- u->instance.r.x = fix16_to_int(u->rx);
- u->instance.r.y = fix16_to_int(u->ry);
+ i->r.x = fix16_to_int(u->rx);
+ i->r.y = fix16_to_int(u->ry);
}
void unit_set_target(struct unit *const u, const struct unit_target *const t)
@@ -209,240 +212,262 @@ void unit_move_to(struct unit *const u, const unsigned long x, const unsigned lo
u->ty = y > y_off ? fix16_from_int(y - y_off) : 0;
}
-static int get_ux(const struct unit *const u)
+static void adjust_walker(const struct unit *const u, struct sprite *const s,
+ struct instance_render_off *const off)
+{
+ s->w = u->instance.r.w;
+ s->h = u->instance.r.h;
+ s->u += u->dir * s->w;
+ s->v += anim[u->frame.i] * s->h;
+ off->x = 0;
+ off->y = -2;
+}
+
+static void adjust_car(const struct unit *const u, struct sprite *const s,
+ struct instance_render_off *const off)
{
switch (u->dir)
{
- case UNIT_DIR_N:
- return 0;
-
- case UNIT_DIR_NE:
- /* Fall through. */
- case UNIT_DIR_NW:
- return 1;
-
- case UNIT_DIR_E:
- /* Fall through. */
case UNIT_DIR_W:
- return 2;
-
- case UNIT_DIR_SE:
- /* Fall through. */
- case UNIT_DIR_SW:
- return 3;
+ s->w = s->h = 32;
+ s->u += 32;
+ off->x = -5;
+ break;
case UNIT_DIR_S:
- return 4;
+ s->w = 16;
+ s->h = 32;
+ off->x = 2;
+ break;
- default:
+ case UNIT_DIR_N:
+ s->u += 16;
+ s->w = 16;
+ s->h = 32;
+ off->x = 2;
+ break;
+
+ case UNIT_DIR_E:
+ s->w = s->h = 32;
+ s->u += 64;
+ off->x = -5;
break;
}
- return -1;
+ off->y = -10;
}
-typedef const struct
-{
- const struct sprite *s;
- char xo, x[N_FRAMES], w[N_FRAMES];
- short y;
- short h;
-} anim_dim;
-
-static anim_dim *peasant_anim(const struct unit *const u)
+static void adjust_sprite(const struct unit *const u, struct sprite *const s,
+ struct instance_render_off *const off)
{
-#if 0
- static anim_dim t[] =
+ switch (u->type)
{
- {
- .s = &unit_sprites[UNIT_SPRITE_N],
- .xo = 5,
- .x = {0, 1, 1, 2, 1},
- .w = {25, 22, 24, 22, 24},
- .y = 2,
- .h = 31
- },
-
- {
- .s = &unit_sprites[UNIT_SPRITE_NE],
- .xo = 11,
- .x = {0, -4, -1, -4, -2},
- .w = {18, 26, 22, 23, 20},
- .y = 2,
- .h = 31
- },
-
- {
- .s = &unit_sprites[UNIT_SPRITE_E],
- .xo = 10,
- .x = {0, -6, -1, -6, -3},
- .w = {14, 26, 17, 24, 19},
- .y = 2,
- .h = 33
- },
-
- {
- .s = &unit_sprites[UNIT_SPRITE_SE],
- .xo = 6,
- .x = {0, 1, 2, 0, 0},
- .w = {20, 22, 18, 21, 21},
- .y = 2,
- .h = 31
- },
-
- {
- .s = &unit_sprites[UNIT_SPRITE_S],
- .xo = 7,
- .x = {0, 1, 0, 0, 0},
- .w = {24, 23, 24, 23, 24},
- .y = 2,
- .h = 33
- }
- };
-
- const int ux = get_ux(u);
+ case UNIT_TYPE_1:
+ case UNIT_TYPE_2:
+ case UNIT_TYPE_3:
+ case UNIT_TYPE_4:
+ case UNIT_TYPE_5:
+ case UNIT_TYPE_6:
+ adjust_walker(u, s, off);
+ break;
- if (ux < 0)
- return NULL;
+ case UNIT_TYPE_CAR_1:
+ case UNIT_TYPE_CAR_2:
+ adjust_car(u, s, off);
+ break;
- return &t[ux];
-#else
- return NULL;
-#endif
+ case MAX_UNIT_TYPES:
+ break;
+ }
}
-struct render_cfg
-{
- struct instance_render_off off;
- struct instance_render_quad qcfg;
-};
-
-static anim_dim *peasant_quad(const struct unit *const u)
+int unit_render(const struct unit *const u, const struct camera *const cam,
+ const bool sel)
{
- return peasant_anim(u);
-}
+ if (!u->instance.alive)
+ return 0;
-static void adjust_quad(const struct unit *const u, anim_dim *const dim,
- struct render_cfg *const rcfg)
-{
- const unsigned char n = u->frame.i;
- short u_off = 0;
+ sprite_get_or_ret(s, -1);
- for (unsigned char i = 0; i < n; i++)
- u_off += dim->w[i];
+ struct instance_render_off off;
- struct instance_render_quad *const qcfg = &rcfg->qcfg;
+ if (sprite_clone(&unit_sprites[u->type], s))
+ {
+ fprintf(stderr, "%s: sprite_clone failed\n", __func__);
+ return -1;
+ }
- qcfg->u = u_off;
- qcfg->w = dim->w[n];
- qcfg->h = dim->h;
+ adjust_sprite(u, s, &off);
- struct instance_render_off *const off = &rcfg->off;
+ const struct instance_render_cfg cfg =
+ {
+ .i = &u->instance,
+ .prim_type = INSTANCE_RENDER_CFG_SPRITE,
+ .prim.s = s,
+ .off = &off,
+ .cam = cam,
+ .sel = sel
+ };
- off->x = dim->xo;
- off->y = dim->y;
+ return instance_render(&cfg);
+}
- switch (u->dir)
+static void get_dimensions(const enum unit_type type, short *const w,
+ short *const h)
+{
+ switch (type)
{
- case UNIT_DIR_SW:
- /* Fall through. */
- case UNIT_DIR_W:
- /* Fall through. */
- case UNIT_DIR_NW:
- qcfg->xflip = true;
- off->x += dim->x[n];
+ case UNIT_TYPE_1:
+ case UNIT_TYPE_2:
+ case UNIT_TYPE_3:
+ case UNIT_TYPE_4:
+ case UNIT_TYPE_5:
+ case UNIT_TYPE_6:
+ *w = *h = 16;
break;
- default:
- qcfg->xflip = false;
- off->x += dim->x[n];
+ case UNIT_TYPE_CAR_1:
+ case UNIT_TYPE_CAR_2:
+ *w = *h = 22;
+ break;
+
+ case MAX_UNIT_TYPES:
break;
}
}
-static int unit_quad(const struct unit *const u, struct render_cfg *const rcfg)
+static const char *get_walker_name(const enum unit_type type)
{
- struct instance_render_quad *const qcfg = &rcfg->qcfg;
-
- static anim_dim *(*const f[1])(const struct unit *);
+ enum {FEMALE, MALE} gender = 0;
- anim_dim *const dim = f[u->type](u);
-
- if (!dim)
- return -1;
+ switch (type)
+ {
+ case UNIT_TYPE_2:
+ case UNIT_TYPE_5:
+ gender = FEMALE;
+ break;
- adjust_quad(u, dim, rcfg);
+ case UNIT_TYPE_1:
+ case UNIT_TYPE_3:
+ case UNIT_TYPE_4:
+ case UNIT_TYPE_6:
+ gender = MALE;
+ break;
- if (quad_from_sprite(dim->s, qcfg->q))
- return -1;
+ default:
+ return NULL;
+ }
- return 0;
-}
+ static const char *const female[] =
+ {
+ "Amelia",
+ "Asher",
+ "Aurora",
+ "Ava",
+ "Charlotte",
+ "Dana",
+ "Ellie",
+ "Emma",
+ "Ezra",
+ "Haley",
+ "Harper",
+ "Isabella",
+ "Luna",
+ "Mire",
+ "Olivia",
+ "Sophia",
+ };
-int unit_render(const struct unit *const u, const struct camera *const cam,
- const bool sel)
-{
- if (!u->instance.alive)
- return 0;
+ static const char *const male[] =
+ {
+ "Oliver",
+ "Xavi",
+ "Benjamin",
+ "Elijah",
+ "Ethan",
+ "Jack",
+ "James",
+ "Jan",
+ "Kyte",
+ "Leo",
+ "Levi",
+ "Liam",
+ "Luca",
+ "Lucas",
+ "Michael",
+ "Noah",
+ };
- struct render_cfg rcfg;
+ switch (gender)
+ {
+ case FEMALE:
+ {
+ const size_t i = rand() % (sizeof female / sizeof *female);
- quad_get_or_ret(q, -1);
- rcfg.qcfg.q = q;
+ return female[i];
+ }
- if (unit_quad(u, &rcfg))
- return -1;
+ case MALE:
+ {
+ const size_t i = rand() % (sizeof male / sizeof *male);
- const struct instance_render_cfg cfg =
- {
- .i = &u->instance,
- .prim_type = INSTANCE_RENDER_CFG_QUAD,
- .prim = {.quad = &rcfg.qcfg},
- .cam = cam,
- .sel = sel,
- .off = &rcfg.off
- };
+ return male[i];
+ }
+ }
- return instance_render(&cfg);
+ return NULL;
}
-static void get_dimensions(const enum unit_type type, short *const w,
- short *const h)
+static const char *get_name(const enum unit_type type)
{
- static const struct dim
+ switch (type)
{
- short w, h;
- } dim[1];
+ case UNIT_TYPE_1:
+ case UNIT_TYPE_2:
+ case UNIT_TYPE_3:
+ case UNIT_TYPE_4:
+ case UNIT_TYPE_5:
+ case UNIT_TYPE_6:
+ return get_walker_name(type);
+
+ case UNIT_TYPE_CAR_1:
+ case UNIT_TYPE_CAR_2:
+ return "Car";
+
+ case MAX_UNIT_TYPES:
+ break;
+ }
- const struct dim *const d = &dim[type];
- *w = d->w;
- *h = d->h;
+ return NULL;
}
void unit_create(const struct unit_cfg *const cfg, struct unit *const u)
{
struct instance *const i = &u->instance;
+ enum unit_type type = 0;
- *u = (const struct unit)
+ switch (cfg->type)
{
- .instance =
- {
- .alive = true,
- },
+ case UNIT_CFG_TYPE_WALKER:
+ type = UNIT_TYPE_1 + (rand() % (UNIT_TYPE_6 + 1));
+ break;
- .type = cfg->type,
+ case UNIT_CFG_TYPE_CAR:
+ type = UNIT_TYPE_CAR_1 + (rand()
+ % (UNIT_TYPE_CAR_2 - UNIT_TYPE_CAR_1 + 1));
+ break;
+ }
+
+ *u = (const struct unit)
+ {
+ .instance.alive = true,
.dir = UNIT_DIR_S,
.rx = fix16_from_int(cfg->x),
- .ry = fix16_from_int(cfg->y)
+ .ry = fix16_from_int(cfg->y),
+ .type = type,
+ .name = get_name(type)
};
- get_dimensions(cfg->type, &i->r.w, &i->r.h);
+ get_dimensions(u->type, &i->r.w, &i->r.h);
unit_stop(u);
}
-
-const char *unit_str(const struct unit *const u)
-{
- static const char *const str[1];
-
- return str[u->type];
-}