Implement touch controls
This commit is contained in:
parent
82c61e3d1d
commit
45337576df
|
@ -1,3 +1,3 @@
|
|||
add_library(camera "src/camera.c" "src/pad.c" "src/mouse.c")
|
||||
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)
|
||||
|
|
|
@ -35,6 +35,7 @@ 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);
|
||||
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);
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
#include <camera.h>
|
||||
#include <mouse.h>
|
||||
#include <camera_private.h>
|
||||
#include <gfx.h>
|
||||
|
||||
static void cursor_update(struct cursor *const c, const struct mouse *const m)
|
||||
{
|
||||
if (c->screen.last_w != screen_w
|
||||
|| c->screen.last_h != screen_h)
|
||||
cursor_init(c);
|
||||
|
||||
c->x = m->x;
|
||||
c->y = m->y;
|
||||
}
|
||||
|
||||
static bool 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))
|
||||
{
|
||||
*sx = m->dx;
|
||||
*sy = m->dy;
|
||||
|
||||
ret = *sx || *sy;
|
||||
}
|
||||
else if (*sx || *sy)
|
||||
{
|
||||
const int qx = *sx / 4;
|
||||
|
||||
if (qx)
|
||||
*sx -= qx;
|
||||
else
|
||||
*sx = 0;
|
||||
|
||||
const int qy = *sy / 4;
|
||||
|
||||
if (qy)
|
||||
*sy -= qy;
|
||||
else
|
||||
*sy = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool camera_update_touch(struct camera *const cam, const struct mouse *const m)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
cursor_update(&cam->cursor, m);
|
||||
ret = update_speed(cam, m);
|
||||
camera_update_pos(cam);
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -26,7 +26,7 @@ int game(void)
|
|||
{
|
||||
const struct human_player_cfg cfg =
|
||||
{
|
||||
.sel_periph = HUMAN_PLAYER_PERIPH_KEYBOARD_MOUSE,
|
||||
.sel_periph = HUMAN_PLAYER_PERIPH_TOUCH,
|
||||
.padn = i,
|
||||
.pl =
|
||||
{
|
||||
|
@ -86,8 +86,7 @@ int game(void)
|
|||
terrain_update(&map);
|
||||
|
||||
if (terrain_render(&map, &h->cam)
|
||||
|| human_player_render(h, &o)
|
||||
|| cursor_render(&h->cam.cursor))
|
||||
|| human_player_render(h, &o))
|
||||
goto end;
|
||||
|
||||
/* TODO: render AI players. */
|
||||
|
|
|
@ -16,12 +16,13 @@ enum mouse_button
|
|||
|
||||
struct mouse
|
||||
{
|
||||
short x, y;
|
||||
short x, y, dx, dy;
|
||||
int mask, oldmask;
|
||||
};
|
||||
|
||||
void mouse_init(struct mouse *m);
|
||||
void mouse_update(struct mouse *m);
|
||||
bool mouse_pressed(const struct mouse *m, enum mouse_button b);
|
||||
bool mouse_justpressed(const struct mouse *m, enum mouse_button b);
|
||||
bool mouse_justreleased(const struct mouse *m, enum mouse_button b);
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ static void mouse_event(const SDL_MouseMotionEvent *const ev,
|
|||
|
||||
void mouse_update(struct mouse *const m)
|
||||
{
|
||||
const short x = m->x, y = m->y;
|
||||
SDL_Event ev;
|
||||
int n;
|
||||
|
||||
|
@ -71,6 +72,9 @@ void mouse_update(struct mouse *const m)
|
|||
}
|
||||
}
|
||||
|
||||
m->dx = m->x - x;
|
||||
m->dy = m->y - y;
|
||||
|
||||
end:
|
||||
|
||||
if (n < 0)
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
#include <mouse.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
bool mouse_pressed(const struct mouse *const m, const enum mouse_button b)
|
||||
{
|
||||
return m->mask & (1 << b);
|
||||
}
|
||||
|
||||
bool mouse_justpressed(const struct mouse *const m,
|
||||
const enum mouse_button b)
|
||||
{
|
||||
|
|
|
@ -22,6 +22,7 @@ struct human_player_cfg
|
|||
enum human_player_periph
|
||||
{
|
||||
HUMAN_PLAYER_PERIPH_PAD,
|
||||
HUMAN_PLAYER_PERIPH_TOUCH,
|
||||
HUMAN_PLAYER_PERIPH_KEYBOARD_MOUSE
|
||||
} sel_periph;
|
||||
|
||||
|
@ -39,10 +40,12 @@ struct human_player
|
|||
{
|
||||
struct pad pad;
|
||||
|
||||
struct
|
||||
struct human_player_kbm
|
||||
{
|
||||
struct mouse mouse;
|
||||
struct keyboard keyboard;
|
||||
bool long_press, pan;
|
||||
unsigned int lp_t;
|
||||
} kbm;
|
||||
} periph;
|
||||
|
||||
|
|
|
@ -207,15 +207,33 @@ static bool select_resources(struct human_player *const h, const short x,
|
|||
}
|
||||
|
||||
static bool select_instances(struct human_player *const h,
|
||||
const struct player_others *const o, const bool excl)
|
||||
const struct player_others *const o, const bool excl,
|
||||
const bool same_type)
|
||||
{
|
||||
unsigned long x, y;
|
||||
|
||||
cursor_pos(&h->cam, &x, &y);
|
||||
|
||||
return select_buildings(h, x, y, excl)
|
||||
|| select_units(h, x, y, excl)
|
||||
|| select_resources(h, x, y, o, excl);
|
||||
if (!same_type || !h->n_sel)
|
||||
return select_buildings(h, x, y, excl)
|
||||
|| select_units(h, x, y, excl)
|
||||
|| select_resources(h, x, y, o, excl);
|
||||
else
|
||||
{
|
||||
switch (h->sel->type)
|
||||
{
|
||||
case INSTANCE_TYPE_UNIT:
|
||||
return select_units(h, x, y, excl);
|
||||
|
||||
case INSTANCE_TYPE_BUILDING:
|
||||
return select_buildings(h, x, y, excl);
|
||||
|
||||
case INSTANCE_TYPE_RESOURCE:
|
||||
select_resources(h, x, y, o, excl);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool instance_collision(const struct camera *const cam,
|
||||
|
@ -518,7 +536,7 @@ static bool update_from_pad(struct human_player *const h,
|
|||
|| pad_justpressed(p, PAD_KEY_EXIT))
|
||||
ret = true;
|
||||
else if (pad_justpressed(p, PAD_KEY_A))
|
||||
select_instances(h, o, false);
|
||||
select_instances(h, o, false, false);
|
||||
else if (pad_justpressed(p, PAD_KEY_B))
|
||||
move_units(h, o);
|
||||
else if (pad_justpressed(p, PAD_KEY_C))
|
||||
|
@ -529,10 +547,59 @@ static bool update_from_pad(struct human_player *const h,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static bool update_keyboard_mouse_common(const struct mouse *const m,
|
||||
const struct keyboard *const k)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if (keyboard_justreleased(k, &KEYBOARD_COMBO(KEYBOARD_KEY_EXIT)))
|
||||
ret = true;
|
||||
else if (keyboard_justreleased(k, &KEYBOARD_COMBO(KEYBOARD_KEY_F11)))
|
||||
gfx_toggle_fullscreen();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool update_from_touch(struct human_player *const h,
|
||||
struct player_others *const o)
|
||||
{
|
||||
struct mouse *const m = &h->periph.kbm.mouse;
|
||||
struct keyboard *const k = &h->periph.kbm.keyboard;
|
||||
|
||||
mouse_update(m);
|
||||
keyboard_update(k);
|
||||
|
||||
enum {DEAD_ZONE = 5};
|
||||
struct human_player_kbm *const kbm = &h->periph.kbm;
|
||||
|
||||
if (mouse_pressed(m, MOUSE_BUTTON_LEFT) && !kbm->pan)
|
||||
{
|
||||
enum {LONG_PRESS_THRESHOLD = 30};
|
||||
|
||||
if (kbm->lp_t < LONG_PRESS_THRESHOLD)
|
||||
kbm->lp_t++;
|
||||
else if (!kbm->long_press)
|
||||
{
|
||||
kbm->long_press = true;
|
||||
deselect_instances(h);
|
||||
}
|
||||
}
|
||||
else if (mouse_justreleased(m, MOUSE_BUTTON_LEFT))
|
||||
{
|
||||
if (!kbm->pan && !select_instances(h, o, false, true))
|
||||
move_units(h, o);
|
||||
|
||||
kbm->pan = false;
|
||||
kbm->long_press = false;
|
||||
kbm->lp_t = 0;
|
||||
}
|
||||
|
||||
return update_keyboard_mouse_common(m, k);
|
||||
}
|
||||
|
||||
static bool update_from_keyboard_mouse(struct human_player *const h,
|
||||
struct player_others *const o)
|
||||
{
|
||||
bool ret = false;
|
||||
struct mouse *const m = &h->periph.kbm.mouse;
|
||||
struct keyboard *const k = &h->periph.kbm.keyboard;
|
||||
|
||||
|
@ -545,17 +612,13 @@ static bool update_from_keyboard_mouse(struct human_player *const h,
|
|||
keyboard_pressed(k, &KEYBOARD_COMBO(KEYBOARD_KEY_LSHIFT))
|
||||
|| keyboard_pressed(k, &KEYBOARD_COMBO(KEYBOARD_KEY_RSHIFT));
|
||||
|
||||
if (!select_instances(h, o, !shift_pressed))
|
||||
if (!select_instances(h, o, !shift_pressed, false))
|
||||
deselect_instances(h);
|
||||
}
|
||||
else if (mouse_justreleased(m, MOUSE_BUTTON_RIGHT))
|
||||
move_units(h, o);
|
||||
else if (keyboard_justreleased(k, &KEYBOARD_COMBO(KEYBOARD_KEY_EXIT)))
|
||||
ret = true;
|
||||
else if (keyboard_justreleased(k, &KEYBOARD_COMBO(KEYBOARD_KEY_F11)))
|
||||
gfx_toggle_fullscreen();
|
||||
|
||||
return ret;
|
||||
return update_keyboard_mouse_common(m, k);
|
||||
}
|
||||
|
||||
bool human_player_update(struct human_player *const h,
|
||||
|
@ -577,6 +640,15 @@ bool human_player_update(struct human_player *const h,
|
|||
camera_update_pad(&h->cam, &h->periph.pad);
|
||||
break;
|
||||
|
||||
case HUMAN_PLAYER_PERIPH_TOUCH:
|
||||
{
|
||||
struct human_player_kbm *const kbm = &h->periph.kbm;
|
||||
|
||||
ret = update_from_touch(h, o);
|
||||
kbm->pan |= camera_update_touch(&h->cam, &kbm->mouse);
|
||||
}
|
||||
break;
|
||||
|
||||
case HUMAN_PLAYER_PERIPH_KEYBOARD_MOUSE:
|
||||
ret = update_from_keyboard_mouse(h, o);
|
||||
camera_update_mouse(&h->cam, &h->periph.kbm.mouse);
|
||||
|
@ -659,6 +731,21 @@ int human_player_render(const struct human_player *const h,
|
|||
|| gui_render(h))
|
||||
return -1;
|
||||
|
||||
switch (h->sel_periph)
|
||||
{
|
||||
case HUMAN_PLAYER_PERIPH_PAD:
|
||||
/* Fall through. */
|
||||
case HUMAN_PLAYER_PERIPH_KEYBOARD_MOUSE:
|
||||
cursor_render(&h->cam.cursor);
|
||||
break;
|
||||
|
||||
case HUMAN_PLAYER_PERIPH_TOUCH:
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -672,6 +759,8 @@ int human_player_init(const struct human_player_cfg *const cfg,
|
|||
|
||||
switch (h->sel_periph = cfg->sel_periph)
|
||||
{
|
||||
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);
|
||||
|
|
Loading…
Reference in New Issue