Compare commits

...

8 Commits

Author SHA1 Message Date
Xavier Del Campo Romero 3cb276b19f camera: remove dependency against terrain
This will allow using camera for purposes other than showing the game
map.
2022-06-12 23:19:03 +02:00
Xavier Del Campo Romero 0f9e2d8958 Split peripheral-related logic into its own component
This has several advantages:

- `camera` no longer needs to define public functions for each
peripheral type.
- Peripheral-related is now no longer tighly coupled to human_player,
so peripheral logic can be reused elsewhere e.g.: on menus.
- Makes camera_update_touch consistent compared to equivalent functions,
since now `pan` has now been moved to `camera` (as it should be).
2022-06-12 23:18:57 +02:00
Xavier Del Campo Romero 5794dbf403 CMakeLists.txt: limit libraries linked to by ${PROJECT_NAME}
Old behaviour was linking to all components, but main.c currently only
needs a few of them.
2022-06-12 00:00:56 +02:00
Xavier Del Campo Romero a826c2364d sdl-1.2/sound.c: use SDL_WasInit 2022-06-11 23:42:30 +02:00
Xavier Del Campo Romero 3f6bf6aa1a sdl-1.2: return to original dimensions on fullscreen exit 2022-06-11 23:42:30 +02:00
Xavier Del Campo Romero a84a55aa25 Implement button component 2022-06-11 23:42:27 +02:00
Xavier Del Campo Romero 9b75ff3c2e res: add btn_{left,mid,right} 2022-06-11 23:41:56 +02:00
Xavier Del Campo Romero c8362184ee res/CMakeLists.txt: do not use transparency for sel_mid_v 2022-06-11 23:11:49 +02:00
28 changed files with 400 additions and 96 deletions

View File

@ -43,6 +43,7 @@ add_subdirectory("res")
set(components
building
button
camera
container
font
@ -54,6 +55,7 @@ set(components
keyboard
mouse
pad
peripheral
player
resource
sfx
@ -68,11 +70,12 @@ set(interfaces
)
target_compile_options(${PROJECT_NAME} PUBLIC ${cflags})
# Dependencies for main.c
target_link_libraries(${PROJECT_NAME} PRIVATE system game)
foreach(c ${components})
add_subdirectory("src/${c}")
target_compile_options(${c} PUBLIC ${cflags})
target_link_libraries(${PROJECT_NAME} PRIVATE ${c})
endforeach()
foreach(i ${interfaces})

View File

@ -242,7 +242,7 @@ sprite(NAME sel_mid_v
BPP 4
CX 368
CY 499
TRANSPARENT TRUE)
TRANSPARENT FALSE)
sprite(NAME font
X 472
@ -268,6 +268,30 @@ sprite(NAME tree
CY 496
TRANSPARENT TRUE)
sprite(NAME btn_left
X 376
Y 80
BPP 4
CX 368
CY 495
TRANSPARENT TRUE)
sprite(NAME btn_right
X 376
Y 106
BPP 4
CX 368
CY 494
TRANSPARENT TRUE)
sprite(NAME btn_mid
X 368
Y 122
BPP 4
CX 368
CY 493
TRANSPARENT FALSE)
sound(NAME acknowledge_01)
sound(NAME acknowledge_02)
sound(NAME selected_01)
@ -275,6 +299,9 @@ sound(NAME selected_01)
container(NAME rts
SPRITES
barracks
btn_left
btn_mid
btn_right
worker_n
worker_ne
worker_e

View File

@ -45,6 +45,12 @@ sel_down_right.bmp:
sel_down_right_24.bmp:
sel_mid.bmp:
sel_mid_24.bmp:
btn_left.bmp:
btn_left_24.bmp:
btn_mid.bmp:
btn_mid_24.bmp:
btn_right.bmp:
btn_right_24.bmp:
Derived works from ui_sheet.png
font.bmp:

BIN
res/btn_left.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 558 B

BIN
res/btn_left_24.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
res/btn_mid.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 546 B

BIN
res/btn_mid_24.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
res/btn_right.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 558 B

BIN
res/btn_right_24.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1,3 @@
add_library(button "src/button.c")
target_include_directories(button PUBLIC "inc")
target_link_libraries(button PUBLIC gfx PRIVATE font)

36
src/button/inc/button.h Normal file
View File

@ -0,0 +1,36 @@
#ifndef BUTTON_H
#define BUTTON_H
#include <gfx.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C"
{
#endif
enum
{
BUTTON_LEFT,
BUTTON_MID,
BUTTON_RIGHT,
MAX_BUTTON_SPRITES
};
struct button
{
const char *text;
short x, y, w;
};
bool button_is_pressed(const struct button *b);
int button_render(const struct button *b);
extern struct sprite button_sprites[MAX_BUTTON_SPRITES];
#ifdef __cplusplus
}
#endif
#endif /* BUTTON_H */

100
src/button/src/button.c Normal file
View File

@ -0,0 +1,100 @@
#include <button.h>
#include <font.h>
#include <gfx.h>
struct sprite button_sprites[MAX_BUTTON_SPRITES];
bool button_is_pressed(const struct button *const b)
{
return false;
}
static int render_left(const struct button *const b, short *const x)
{
sprite_get_or_ret(s, -1);
if (sprite_clone(&button_sprites[BUTTON_LEFT], s))
return -1;
s->x = b->x;
s->y = b->y;
sprite_sort(s);
*x = s->x + s->w;
return 0;
}
static int render_mid(const struct button *const b, short *const x)
{
const short mid_w = button_sprites[BUTTON_MID].w;
const short lw = button_sprites[BUTTON_LEFT].w;
const short rw = button_sprites[BUTTON_RIGHT].w;
const short w = b->w - lw - rw;
if (w > 0)
{
const short rem_mid = w > 0 ? w % mid_w : 0;
const short whole_mid = w / mid_w;
const short n_mid = rem_mid ? whole_mid + 1 : whole_mid;
for (struct
{
size_t i;
short x;
} a = {.i = 0, .x = lw};
a.i < n_mid;
a.i++, a.x += mid_w)
{
sprite_get_or_ret(m, -1);
if (sprite_clone(&button_sprites[BUTTON_MID], m))
return -1;
m->x = *x;
m->y = b->y;
if (rem_mid && a.i + 1 == n_mid)
m->w = rem_mid;
else
m->w = mid_w;
sprite_sort(m);
*x += m->w;
}
}
return 0;
}
static int render_right(const struct button *const b, const short *const x)
{
sprite_get_or_ret(s, -1);
if (sprite_clone(&button_sprites[BUTTON_RIGHT], s))
return -1;
s->x = *x;
s->y = b->y;
sprite_sort(s);
return 0;
}
static int render_text(const struct button *const b)
{
const short x = b->x + button_sprites[BUTTON_LEFT].w,
y = b->y + (button_sprites[BUTTON_MID].h >> 2);
return font_printf(FONT, x, y, "%s", b->text) < 0;
}
int button_render(const struct button *const b)
{
short x;
if (render_left(b, &x)
|| render_mid(b, &x)
|| render_right(b, &x)
|| render_text(b))
return -1;
return 0;
}

View File

@ -1,3 +1,3 @@
add_library(camera "src/camera.c" "src/pad.c" "src/mouse.c" "src/touch.c")
target_include_directories(camera PUBLIC "inc" PRIVATE "privinc")
target_link_libraries(camera PUBLIC container mouse pad terrain util PRIVATE gfx)
target_link_libraries(camera PUBLIC container mouse pad peripheral util PRIVATE gfx)

View File

@ -3,6 +3,7 @@
#include <mouse.h>
#include <pad.h>
#include <peripheral.h>
#include <util.h>
#include <stdbool.h>
@ -13,8 +14,14 @@ extern "C"
struct camera
{
struct camera_dim
{
long w, h;
} dim;
int x, y, x_speed, y_speed;
unsigned int xt, yt;
bool pan;
struct cursor
{
@ -33,9 +40,7 @@ struct camera
extern struct sprite cursor_sprite;
void camera_update_pad(struct camera *cam, const struct pad *p);
void camera_update_mouse(struct camera *cam, const struct mouse *m);
bool camera_update_touch(struct camera *cam, const struct mouse *m);
void camera_update(struct camera *cam, const union peripheral *p);
bool camera_translate(const struct camera *cam, const struct util_rect *dim, short *x, short *y);
void cursor_init(struct cursor *c);
bool cursor_collision(const struct camera *cam, const struct util_rect *d);

View File

@ -15,6 +15,9 @@ enum
};
void camera_update_pos(struct camera *cam);
void camera_update_pad(struct camera *cam, const struct pad *p);
void camera_update_mouse(struct camera *cam, const struct mouse *m);
void camera_update_touch(struct camera *cam, const struct mouse *m);
#ifdef __cplusplus
}

View File

@ -3,7 +3,6 @@
#include <gfx.h>
#include <mouse.h>
#include <pad.h>
#include <terrain.h>
#include <util.h>
#include <limits.h>
#include <stdbool.h>
@ -78,8 +77,8 @@ void camera_update_pos(struct camera *const cam)
if (cam->x > 0)
cam->x = 0;
else if (cam->x < -MAP_W)
cam->x = -MAP_W;
else if (cam->x < -cam->dim.w)
cam->x = -cam->dim.w;
const int y = cam->y + cam->y_speed;
@ -87,8 +86,8 @@ void camera_update_pos(struct camera *const cam)
if (cam->y > 0)
cam->y = 0;
else if (cam->y < -MAP_H)
cam->y = -MAP_H;
else if (cam->y < -cam->dim.h)
cam->y = -cam->dim.h;
}
bool camera_translate(const struct camera *const cam, const struct util_rect *const dim,
@ -103,3 +102,21 @@ bool camera_translate(const struct camera *const cam, const struct util_rect *co
*y = ty;
return true;
}
void camera_update(struct camera *const cam, const union peripheral *const p)
{
switch (p->common.type)
{
case PERIPHERAL_TYPE_PAD:
camera_update_pad(cam, &p->pad.pad);
break;
case PERIPHERAL_TYPE_KEYBOARD_MOUSE:
camera_update_mouse(cam, &p->kbm.mouse);
break;
case PERIPHERAL_TYPE_TOUCH:
camera_update_touch(cam, &p->kbm.mouse);
break;
}
}

View File

@ -1,7 +1,8 @@
#include <camera.h>
#include <camera_private.h>
#include <pad.h>
#include <terrain.h>
#include <peripheral.h>
#include <gfx.h>
#include <util.h>
#include <stdbool.h>
@ -20,7 +21,7 @@ static void cursor_update(struct camera *const cam, const struct pad *const p)
c->x -= STEP;
else if (pad_pressed(p, PAD_KEY_RIGHT)
&& (c->x + STEP < screen_w)
&& (c->x != c->x_init || cam->x <= -MAP_W))
&& (c->x != c->x_init || cam->x <= -cam->dim.w))
c->x += STEP;
if (pad_pressed(p, PAD_KEY_UP)
@ -29,7 +30,7 @@ static void cursor_update(struct camera *const cam, const struct pad *const p)
c->y -= STEP;
else if (pad_pressed(p, PAD_KEY_DOWN)
&& (c->y + STEP < screen_h)
&& (c->y != c->y_init || cam->y <= -MAP_H))
&& (c->y != c->y_init || cam->y <= -cam->dim.h))
c->y += STEP;
c->state = pad_pressed(p, PAD_KEY_A) || pad_pressed(p, PAD_KEY_B) ?

View File

@ -13,9 +13,8 @@ static void cursor_update(struct cursor *const c, const struct mouse *const m)
c->y = m->y;
}
static bool update_speed(struct camera *const cam, const struct mouse *const m)
static void update_speed(struct camera *const cam, const struct mouse *const m)
{
bool ret = false;
int *const sx = &cam->x_speed, *const sy = &cam->y_speed;
if (mouse_pressed(m, MOUSE_BUTTON_LEFT))
@ -23,7 +22,7 @@ static bool update_speed(struct camera *const cam, const struct mouse *const m)
*sx = m->dx;
*sy = m->dy;
ret = *sx || *sy;
cam->pan = *sx || *sy;
}
else if (*sx || *sy)
{
@ -41,17 +40,11 @@ static bool update_speed(struct camera *const cam, const struct mouse *const m)
else
*sy = 0;
}
return ret;
}
bool camera_update_touch(struct camera *const cam, const struct mouse *const m)
void camera_update_touch(struct camera *const cam, const struct mouse *const m)
{
bool ret;
cursor_update(&cam->cursor, m);
ret = update_speed(cam, m);
update_speed(cam, m);
camera_update_pos(cam);
return ret;
}

View File

@ -2,6 +2,7 @@ add_library(game "src/game.c" "src/res.c")
target_include_directories(game PUBLIC "inc" PRIVATE "privinc")
target_link_libraries(game PRIVATE
building
button
container
font
gfx

View File

@ -26,8 +26,14 @@ int game(void)
{
const struct human_player_cfg cfg =
{
.sel_periph = HUMAN_PLAYER_PERIPH_TOUCH,
.sel_periph = PERIPHERAL_TYPE_KEYBOARD_MOUSE,
.padn = i,
.dim =
{
.w = MAP_W,
.h = MAP_H,
},
.pl =
{
.team = PLAYER_COLOR_BLUE,

View File

@ -1,5 +1,6 @@
#include <game_private.h>
#include <building.h>
#include <button.h>
#include <container.h>
#include <font.h>
#include <gfx.h>
@ -216,7 +217,34 @@ static const struct container c[] =
{
.sound = &unit_sounds[UNIT_SOUND_SELECTED]
}
}
},
{
.path = "btn_left",
.type = CONTAINER_TYPE_SPRITE,
.data =
{
.sprite = &button_sprites[BUTTON_LEFT]
}
},
{
.path = "btn_mid",
.type = CONTAINER_TYPE_SPRITE,
.data =
{
.sprite = &button_sprites[BUTTON_MID]
}
},
{
.path = "btn_right",
.type = CONTAINER_TYPE_SPRITE,
.data =
{
.sprite = &button_sprites[BUTTON_RIGHT]
}
},
};
static bool init;

View File

@ -23,7 +23,7 @@ void gfx_deinit(void)
static struct
{
int w, h;
} display;
} display, windowed;
void gfx_register_sprite(struct sprite *const s)
{
@ -60,6 +60,11 @@ static int resize_screen(int w, int h, const bool full_screen)
w = display.w;
h = display.h;
}
else
{
windowed.w = w;
windowed.h = h;
}
int bpp = info->vfmt->BitsPerPixel;
@ -149,8 +154,8 @@ int gfx_toggle_fullscreen(void)
{
fullscreen ^= true;
const int w = fullscreen ? display.w : screen_w;
const int h = fullscreen ? display.h : screen_h;
const int w = fullscreen ? display.w : windowed.w;
const int h = fullscreen ? display.h : windowed.h;
if ((resize_screen(w, h, fullscreen)))
return -1;

View File

@ -0,0 +1,3 @@
add_library(peripheral "src/peripheral.c")
target_include_directories(peripheral PUBLIC "inc")
target_link_libraries(peripheral PUBLIC pad mouse keyboard util)

View File

@ -0,0 +1,64 @@
#ifndef PERIPHERAL_H
#define PERIPHERAL_H
#include <pad.h>
#include <keyboard.h>
#include <mouse.h>
#include <util.h>
#include <stddef.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C"
{
#endif
enum peripheral_type
{
PERIPHERAL_TYPE_PAD,
PERIPHERAL_TYPE_TOUCH,
PERIPHERAL_TYPE_KEYBOARD_MOUSE
};
union peripheral
{
struct peripheral_common
{
enum peripheral_type type;
} common;
struct peripheral_pad
{
struct peripheral_common common;
struct pad pad;
} pad;
struct peripheral_kbm
{
struct peripheral_common common;
struct mouse mouse;
struct keyboard keyboard;
bool long_press;
unsigned int lp_t;
} kbm;
};
struct peripheral_cfg
{
enum peripheral_type type;
int padn;
};
UTIL_STATIC_ASSERT(!offsetof(struct peripheral_pad, common),
"unexpected offsetof for struct peripheral_pad");
UTIL_STATIC_ASSERT(!offsetof(struct peripheral_kbm, common),
"unexpected offsetof for struct peripheral_kbm");
void peripheral_init(const struct peripheral_cfg *cfg, union peripheral *p);
void peripheral_update(union peripheral *p);
#ifdef __cplusplus
}
#endif
#endif /* PERIPHERAL_H */

View File

@ -0,0 +1,41 @@
#include <peripheral.h>
#include <keyboard.h>
#include <mouse.h>
#include <pad.h>
void peripheral_update(union peripheral *const p)
{
switch (p->common.type)
{
case PERIPHERAL_TYPE_TOUCH:
/* Fall through. */
case PERIPHERAL_TYPE_KEYBOARD_MOUSE:
mouse_update(&p->kbm.mouse);
keyboard_update(&p->kbm.keyboard);
break;
case PERIPHERAL_TYPE_PAD:
pad_update(&p->pad.pad);
break;
}
}
void peripheral_init(const struct peripheral_cfg *const cfg,
union peripheral *const p)
{
*p = (const union peripheral){0};
switch (p->common.type = cfg->type)
{
case PERIPHERAL_TYPE_TOUCH:
/* Fall through. */
case PERIPHERAL_TYPE_KEYBOARD_MOUSE:
mouse_init(&p->kbm.mouse);
keyboard_init(&p->kbm.keyboard);
break;
case PERIPHERAL_TYPE_PAD:
pad_init(cfg->padn, &p->pad.pad);
break;
}
}

View File

@ -6,6 +6,7 @@
#include <instance.h>
#include <mouse.h>
#include <pad.h>
#include <peripheral.h>
#include <player.h>
#include <stdbool.h>
#include <stddef.h>
@ -19,35 +20,17 @@ enum {MAX_SELECTED_INSTANCES = 4};
struct human_player_cfg
{
enum human_player_periph
{
HUMAN_PLAYER_PERIPH_PAD,
HUMAN_PLAYER_PERIPH_TOUCH,
HUMAN_PLAYER_PERIPH_KEYBOARD_MOUSE
} sel_periph;
enum peripheral_type sel_periph;
struct player_cfg pl;
int padn;
struct camera_dim dim;
};
struct human_player
{
struct player pl;
struct camera cam;
enum human_player_periph sel_periph;
union
{
struct pad pad;
struct human_player_kbm
{
struct mouse mouse;
struct keyboard keyboard;
bool long_press, pan;
unsigned int lp_t;
} kbm;
} periph;
union peripheral periph;
struct sel_instance
{

View File

@ -528,9 +528,7 @@ static bool update_from_pad(struct human_player *const h,
struct player_others *const o)
{
bool ret = false;
struct pad *const p = &h->periph.pad;
pad_update(p);
struct pad *const p = &h->periph.pad.pad;
if (pad_justpressed(p, PAD_KEY_OPTIONS)
|| pad_justpressed(p, PAD_KEY_EXIT))
@ -565,13 +563,10 @@ static bool update_from_touch(struct human_player *const h,
{
struct mouse *const m = &h->periph.kbm.mouse;
struct keyboard *const k = &h->periph.kbm.keyboard;
struct peripheral_kbm *const kbm = &h->periph.kbm;
bool *const pan = &h->cam.pan;
mouse_update(m);
keyboard_update(k);
struct human_player_kbm *const kbm = &h->periph.kbm;
if (mouse_pressed(m, MOUSE_BUTTON_LEFT) && !kbm->pan)
if (mouse_pressed(m, MOUSE_BUTTON_LEFT) && !*pan)
{
enum {LONG_PRESS_THRESHOLD = 30};
@ -585,10 +580,10 @@ static bool update_from_touch(struct human_player *const h,
}
else if (mouse_justreleased(m, MOUSE_BUTTON_LEFT))
{
if (!kbm->pan && !select_instances(h, o, false, true))
if (!*pan && !select_instances(h, o, false, true))
move_units(h, o);
kbm->pan = false;
*pan = false;
kbm->long_press = false;
kbm->lp_t = 0;
}
@ -602,9 +597,6 @@ static bool update_from_keyboard_mouse(struct human_player *const h,
struct mouse *const m = &h->periph.kbm.mouse;
struct keyboard *const k = &h->periph.kbm.keyboard;
mouse_update(m);
keyboard_update(k);
if (mouse_justreleased(m, MOUSE_BUTTON_LEFT))
{
const bool shift_pressed =
@ -631,29 +623,24 @@ bool human_player_update(struct human_player *const h,
gui_update(h);
update_selected(h);
update_target(h);
peripheral_update(&h->periph);
switch (h->sel_periph)
switch (h->periph.common.type)
{
case HUMAN_PLAYER_PERIPH_PAD:
case PERIPHERAL_TYPE_PAD:
ret = update_from_pad(h, o);
camera_update_pad(&h->cam, &h->periph.pad);
break;
case HUMAN_PLAYER_PERIPH_TOUCH:
{
struct human_player_kbm *const kbm = &h->periph.kbm;
case PERIPHERAL_TYPE_TOUCH:
ret = update_from_touch(h, o);
kbm->pan |= camera_update_touch(&h->cam, &kbm->mouse);
}
break;
case HUMAN_PLAYER_PERIPH_KEYBOARD_MOUSE:
case PERIPHERAL_TYPE_KEYBOARD_MOUSE:
ret = update_from_keyboard_mouse(h, o);
camera_update_mouse(&h->cam, &h->periph.kbm.mouse);
break;
}
camera_update(&h->cam, &h->periph);
player_update(p);
}
@ -730,15 +717,15 @@ int human_player_render(const struct human_player *const h,
|| gui_render(h))
return -1;
switch (h->sel_periph)
switch (h->periph.common.type)
{
case HUMAN_PLAYER_PERIPH_PAD:
case PERIPHERAL_TYPE_PAD:
/* Fall through. */
case HUMAN_PLAYER_PERIPH_KEYBOARD_MOUSE:
case PERIPHERAL_TYPE_KEYBOARD_MOUSE:
cursor_render(&h->cam.cursor);
break;
case HUMAN_PLAYER_PERIPH_TOUCH:
case PERIPHERAL_TYPE_TOUCH:
break;
default:
@ -756,21 +743,15 @@ int human_player_init(const struct human_player_cfg *const cfg,
if (player_init(&cfg->pl, &h->pl))
return -1;
switch (h->sel_periph = cfg->sel_periph)
const struct peripheral_cfg p_cfg =
{
case HUMAN_PLAYER_PERIPH_TOUCH:
/* Fall through. */
case HUMAN_PLAYER_PERIPH_KEYBOARD_MOUSE:
mouse_init(&h->periph.kbm.mouse);
keyboard_init(&h->periph.kbm.keyboard);
break;
case HUMAN_PLAYER_PERIPH_PAD:
pad_init(cfg->padn, &h->periph.pad);
break;
}
.type = cfg->sel_periph,
.padn = cfg->padn
};
peripheral_init(&p_cfg, &h->periph);
cursor_init(&h->cam.cursor);
h->cam.dim = cfg->dim;
h->top_gui = true;
memmove(h->gui_res, h->pl.resources, sizeof h->gui_res);
return 0;

View File

@ -7,7 +7,7 @@
#include <stddef.h>
#include <stdio.h>
static bool subsystem_init, mixer_init;
static bool mixer_init;
void sfx_free(struct sound *const s)
{
@ -73,7 +73,7 @@ void sfx_deinit(void)
if (mixer_init)
Mix_CloseAudio();
if (subsystem_init)
if (SDL_WasInit(SDL_INIT_AUDIO) & SDL_INIT_AUDIO)
SDL_QuitSubSystem(SDL_INIT_AUDIO);
}
@ -87,8 +87,6 @@ int sfx_init(void)
fprintf(stderr, "SDL_InitSubSystem: %s\n", SDL_GetError());
goto failure;
}
else
subsystem_init = true;
if (Mix_OpenAudio(MIX_DEFAULT_FREQUENCY,
MIX_DEFAULT_FORMAT, MIX_DEFAULT_CHANNELS, CHUNK_SZ))