camera: implement fixed cursor movement

On platforms with PERIPHERAL_TYPE_PAD, navigating through menus and
options can be cumbersome if moving the cursor freely around the
screen.

Therefore, this commit instead defines a list of (X, Y) coordinates that
the cursor can jump to. The implementation also attempts to guess which
direction the cursor should jump to for the previous/next point, and
hence determine which button should be pressed by the user.
This commit is contained in:
Xavier Del Campo Romero 2022-06-24 17:45:50 +02:00
parent 8ddea5eef5
commit 9da37c198e
3 changed files with 77 additions and 3 deletions

View File

@ -35,6 +35,16 @@ struct camera
{
int last_w, last_h;
} screen;
struct cursor_pos_rt
{
const struct cursor_pos
{
unsigned x, y;
} *list;
size_t i, n;
} rt;
} cursor;
};
@ -45,6 +55,7 @@ bool camera_translate(const struct camera *cam, const struct util_rect *dim, sho
void cursor_init(struct cursor *c);
bool cursor_collision(const struct camera *cam, const struct util_rect *d);
void cursor_pos(const struct camera *cam, unsigned long *x, unsigned long *y);
void cursor_set_pos_list(struct cursor *c, const struct cursor_pos *pos, size_t n);
int cursor_render(const struct cursor *c);
#ifdef __cplusplus

View File

@ -114,6 +114,16 @@ bool camera_translate(const struct camera *const cam, const struct util_rect *co
return true;
}
void cursor_set_pos_list(struct cursor *const c,
const struct cursor_pos *const pos, const size_t n)
{
c->rt = (const struct cursor_pos_rt)
{
.list = pos,
.n = n
};
}
void camera_update(struct camera *const cam, const union peripheral *const p)
{
switch (p->common.type)

View File

@ -5,6 +5,7 @@
#include <gfx.h>
#include <util.h>
#include <stdbool.h>
#include <stdlib.h>
static void cursor_update(struct camera *const cam, const struct pad *const p)
{
@ -99,9 +100,61 @@ static void update_speed(struct camera *const cam, const struct pad *const p)
cam->y_speed = 0;
}
static enum pad_key get_ref_key(struct cursor_pos_rt *const rt,
const size_t ref)
{
enum pad_key key;
const struct cursor_pos *const cur = &rt->list[rt->i],
*const next = &rt->list[ref];
const short nx = next->x - cur->x,
ny = next->y - cur->y;
if (abs(nx) > abs(ny))
key = nx > 0 ? PAD_KEY_RIGHT : PAD_KEY_LEFT;
else
key = ny > 0 ? PAD_KEY_DOWN : PAD_KEY_UP;
return key;
}
static void cursor_update_fixed(struct camera *const cam,
const struct pad *const p)
{
struct cursor *const c = &cam->cursor;
struct cursor_pos_rt *const rt = &c->rt;
const size_t next = rt->i + 1;
if (next < rt->n)
{
const enum pad_key key = get_ref_key(rt, next);
if (pad_justpressed(p, key))
rt->i = next;
}
else if (rt->i)
{
const size_t prev = rt->i - 1;
const enum pad_key key = get_ref_key(rt, prev);
if (pad_justpressed(p, key))
rt->i = prev;
}
const struct cursor_pos *const cur = &rt->list[rt->i];
c->x = cur->x;
c->y = cur->y;
}
void camera_update_pad(struct camera *const cam, const struct pad *const p)
{
cursor_update(cam, p);
update_speed(cam, p);
camera_update_pos(cam);
if (cam->cursor.rt.list)
cursor_update_fixed(cam, p);
else
{
cursor_update(cam, p);
update_speed(cam, p);
camera_update_pos(cam);
}
}