Add support for keyboard and mouse

This commit is contained in:
Xavier Del Campo Romero 2022-02-24 17:55:57 +01:00
parent 18717569ac
commit 9eee43d3bb
28 changed files with 870 additions and 254 deletions

View File

@ -106,6 +106,8 @@ set(components
gui
header
instance
keyboard
mouse
pad
player
resource

View File

@ -22,12 +22,19 @@ function(sprite)
BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/${SPRITE_NAME})
add_dependencies(iso ${SPRITE_NAME}_img)
elseif(SDL1_2_BUILD)
add_custom_target(${SPRITE_NAME}_img ALL
cp ${SPRITE_NAME}.bmp ${CMAKE_CURRENT_BINARY_DIR}/${SPRITE_NAME}
if(${SPRITE_TRANSPARENT})
set(trans "transparent=1")
else()
set(trans "transparent=0")
endif()
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${SPRITE_NAME}
COMMAND add-header ${trans} ${SPRITE_NAME}_24.bmp ${CMAKE_CURRENT_BINARY_DIR}/${SPRITE_NAME}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS ${SPRITE_NAME}.bmp
BYPRODUCTS ${SPRITE_NAME})
add_dependencies(${PROJECT_NAME} ${SPRITE_NAME}_img)
DEPENDS ${SPRITE_NAME}_24.bmp
VERBATIM)
add_custom_target(${SPRITE_NAME}_img
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${SPRITE_NAME})
endif()
endfunction()
@ -51,16 +58,20 @@ function(sound)
BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/${SOUND_NAME})
add_dependencies(iso ${SOUND_NAME}_snd)
elseif(SDL1_2_BUILD)
add_custom_target(${SOUND_NAME}_snd ALL
#ffmpeg -y -i ${SOUND_NAME}.wav
# -loglevel error
# -c:a libvorbis
# ${CMAKE_CURRENT_BINARY_DIR}/${SOUND_NAME}
cp ${SOUND_NAME}.wav ${CMAKE_CURRENT_BINARY_DIR}/${SOUND_NAME}
if(${SOUND_LOOP})
set(loop "loop=1")
else()
set(loop "loop=0")
endif()
# Reference: https://gist.github.com/socantre/7ee63133a0a3a08f3990
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${SOUND_NAME}
COMMAND add-header ${loop} ${SOUND_NAME}.wav ${CMAKE_CURRENT_BINARY_DIR}/${SOUND_NAME}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS ${SOUND_NAME}.wav
BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/${SOUND_NAME})
add_dependencies(${PROJECT_NAME} ${SOUND_NAME}_snd)
VERBATIM)
add_custom_target(${SOUND_NAME}_snd
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${SOUND_NAME})
endif()
endfunction()
@ -71,11 +82,15 @@ function(container)
cmake_parse_arguments(CONTAINER "${options}" "${oneValueArgs}"
"${multiValueArgs}" ${ARGN})
add_custom_target(${CONTAINER_NAME}_container ALL
container ${CONTAINER_SPRITES} ${CONTAINER_SOUNDS}
add_custom_command(OUTPUT ${cdroot}/${CONTAINER_NAME}.cnt
COMMAND container ${CONTAINER_SPRITES} ${CONTAINER_SOUNDS}
${cdroot}/${CONTAINER_NAME}.cnt
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
BYPRODUCTS ${cdroot}/${CONTAINER_NAME}.cnt)
VERBATIM)
add_custom_target(${CONTAINER_NAME}_container
DEPENDS ${cdroot}/${CONTAINER_NAME}.cnt)
add_dependencies(${PROJECT_NAME} ${CONTAINER_NAME}_container)
foreach(sprite ${CONTAINER_SPRITES})
add_dependencies(${CONTAINER_NAME}_container ${sprite}_img)
@ -168,7 +183,7 @@ sprite(NAME gui_bar_mid
BPP 4
CX 368
CY 506
TRANSPARENT TRUE)
TRANSPARENT FALSE)
sprite(NAME gui_bar_right
X 376

View File

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

View File

@ -1,6 +1,7 @@
#ifndef CAMERA_H
#define CAMERA_H
#include <mouse.h>
#include <pad.h>
#include <util.h>
#include <stdbool.h>
@ -32,7 +33,8 @@ struct camera
extern struct sprite cursor_sprite;
void camera_update(struct camera *cam, const struct pad *p);
void camera_update_pad(struct camera *cam, const struct pad *p);
void camera_update_mouse(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);

View File

@ -0,0 +1,17 @@
#ifndef CAMERA_PRIVATE_H
#define CAMERA_PRIVATE_H
#include <camera.h>
#ifdef __cplusplus
extern "C"
{
#endif
void camera_update_pos(struct camera *cam);
#ifdef __cplusplus
}
#endif
#endif /* CAMERA_PRIVATE_H */

View File

@ -1,5 +1,7 @@
#include <camera.h>
#include <camera_private.h>
#include <gfx.h>
#include <mouse.h>
#include <pad.h>
#include <terrain.h>
#include <util.h>
@ -40,37 +42,6 @@ void cursor_pos(const struct camera *const cam, unsigned long *const x,
*y = c->y - cam->y;
}
static void cursor_update(struct camera *const cam, const struct pad *const p)
{
struct cursor *const c = &cam->cursor;
enum {STEP = 4};
if (c->screen.last_w != screen_w
|| c->screen.last_h != screen_h)
cursor_init(c);
if (pad_pressed(p, PAD_KEY_LEFT)
&& (c->x - STEP)
&& (!cam->x || c->x != c->x_init))
c->x -= STEP;
else if (pad_pressed(p, PAD_KEY_RIGHT)
&& (c->x + STEP < screen_w)
&& (c->x != c->x_init || cam->x <= -MAP_X))
c->x += STEP;
if (pad_pressed(p, PAD_KEY_UP)
&& (c->y - STEP)
&& (c->y != c->y_init || !cam->y))
c->y -= STEP;
else if (pad_pressed(p, PAD_KEY_DOWN)
&& (c->y + STEP < screen_h)
&& (c->y != c->y_init || cam->y <= -MAP_Y))
c->y += STEP;
c->state = pad_pressed(p, PAD_KEY_A) || pad_pressed(p, PAD_KEY_B) ?
CURSOR_STATE_PRESSED: CURSOR_STATE_IDLE;
}
int cursor_render(const struct cursor *const c)
{
sprite_get_or_ret(s, -1);
@ -105,69 +76,7 @@ void cursor_init(struct cursor *const c)
c->screen.last_h = screen_h;
}
static void update_speed(struct camera *const cam, const struct pad *const p)
{
enum
{
MAX_SPEED = 10,
STEP = 1,
T_STEP = 3
};
const struct cursor *const c = &cam->cursor;
if (c->x == c->x_init
&& (!cam->x_speed || ++cam->xt >= T_STEP))
{
if (pad_pressed(p, PAD_KEY_RIGHT))
{
if (cam->x_speed > 0)
cam->x_speed = -STEP;
else if (cam->x_speed - STEP >= -MAX_SPEED)
cam->x_speed -= STEP;
}
else if (pad_pressed(p, PAD_KEY_LEFT))
{
if (cam->x_speed < 0)
cam->x_speed = STEP;
else if (cam->x_speed + STEP <= MAX_SPEED)
cam->x_speed += STEP;
}
else
cam->x_speed = 0;
cam->xt = 0;
}
else if (c->x != c->x_init)
cam->x_speed = 0;
if (c->y == c->y_init
&& (!cam->y_speed || ++cam->yt >= T_STEP))
{
if (pad_pressed(p, PAD_KEY_DOWN))
{
if (cam->y_speed > 0)
cam->y_speed = STEP;
else if (cam->y_speed - STEP >= -MAX_SPEED)
cam->y_speed -= STEP;
}
else if (pad_pressed(p, PAD_KEY_UP))
{
if (cam->y_speed < 0)
cam->y_speed = -STEP;
else if (cam->y_speed + STEP <= MAX_SPEED)
cam->y_speed += STEP;
}
else
cam->y_speed = 0;
cam->yt = 0;
}
else if (c->y != c->y_init)
cam->y_speed = 0;
}
static void update_pos(struct camera *const cam)
void camera_update_pos(struct camera *const cam)
{
const int x = cam->x + cam->x_speed;
@ -188,13 +97,6 @@ static void update_pos(struct camera *const cam)
cam->y = -MAP_Y;
}
void camera_update(struct camera *const cam, const struct pad *const p)
{
cursor_update(cam, p);
update_speed(cam, p);
update_pos(cam);
}
bool camera_translate(const struct camera *const cam, const struct util_rect *const dim,
short *const x, short *const y)
{

37
src/camera/src/mouse.c Normal file
View File

@ -0,0 +1,37 @@
#include <camera.h>
#include <camera_private.h>
#include <gfx.h>
#include <mouse.h>
#include <util.h>
#include <stdbool.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 void update_speed(struct camera *const cam, const struct mouse *const m)
{
enum
{
MAX_SPEED = 10,
STEP = 1,
T_STEP = 3
};
struct cursor *const c = &cam->cursor;
}
void camera_update_mouse(struct camera *const cam, const struct mouse *const m)
{
cursor_update(&cam->cursor, m);
update_speed(cam, m);
camera_update_pos(cam);
}

106
src/camera/src/pad.c Normal file
View File

@ -0,0 +1,106 @@
#include <camera.h>
#include <camera_private.h>
#include <pad.h>
#include <terrain.h>
#include <util.h>
#include <stdbool.h>
static void cursor_update(struct camera *const cam, const struct pad *const p)
{
struct cursor *const c = &cam->cursor;
enum {STEP = 4};
if (c->screen.last_w != screen_w
|| c->screen.last_h != screen_h)
cursor_init(c);
if (pad_pressed(p, PAD_KEY_LEFT)
&& (c->x - STEP)
&& (!cam->x || c->x != c->x_init))
c->x -= STEP;
else if (pad_pressed(p, PAD_KEY_RIGHT)
&& (c->x + STEP < screen_w)
&& (c->x != c->x_init || cam->x <= -MAP_X))
c->x += STEP;
if (pad_pressed(p, PAD_KEY_UP)
&& (c->y - STEP)
&& (c->y != c->y_init || !cam->y))
c->y -= STEP;
else if (pad_pressed(p, PAD_KEY_DOWN)
&& (c->y + STEP < screen_h)
&& (c->y != c->y_init || cam->y <= -MAP_Y))
c->y += STEP;
c->state = pad_pressed(p, PAD_KEY_A) || pad_pressed(p, PAD_KEY_B) ?
CURSOR_STATE_PRESSED: CURSOR_STATE_IDLE;
}
static void update_speed(struct camera *const cam, const struct pad *const p)
{
enum
{
MAX_SPEED = 10,
STEP = 1,
T_STEP = 3
};
const struct cursor *const c = &cam->cursor;
if (c->x == c->x_init
&& (!cam->x_speed || ++cam->xt >= T_STEP))
{
if (pad_pressed(p, PAD_KEY_RIGHT))
{
if (cam->x_speed > 0)
cam->x_speed = -STEP;
else if (cam->x_speed - STEP >= -MAX_SPEED)
cam->x_speed -= STEP;
}
else if (pad_pressed(p, PAD_KEY_LEFT))
{
if (cam->x_speed < 0)
cam->x_speed = STEP;
else if (cam->x_speed + STEP <= MAX_SPEED)
cam->x_speed += STEP;
}
else
cam->x_speed = 0;
cam->xt = 0;
}
else if (c->x != c->x_init)
cam->x_speed = 0;
if (c->y == c->y_init
&& (!cam->y_speed || ++cam->yt >= T_STEP))
{
if (pad_pressed(p, PAD_KEY_DOWN))
{
if (cam->y_speed > 0)
cam->y_speed = STEP;
else if (cam->y_speed - STEP >= -MAX_SPEED)
cam->y_speed -= STEP;
}
else if (pad_pressed(p, PAD_KEY_UP))
{
if (cam->y_speed < 0)
cam->y_speed = -STEP;
else if (cam->y_speed + STEP <= MAX_SPEED)
cam->y_speed += STEP;
}
else
cam->y_speed = 0;
cam->yt = 0;
}
else if (c->y != c->y_init)
cam->y_speed = 0;
}
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);
}

View File

@ -22,6 +22,7 @@ int game(void)
{
const struct human_player_cfg cfg =
{
.sel_periph = HUMAN_PLAYER_PERIPH_KEYBOARD_MOUSE,
.padn = i,
.pl =
{

View File

@ -2,6 +2,7 @@
#define GFX_SDL_H
#include <SDL/SDL.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C"
@ -13,6 +14,7 @@ struct sprite
SDL_Surface *s;
short x, y, w, h;
unsigned char u, v;
bool transparent;
};
struct quad
@ -22,6 +24,7 @@ struct quad
short y0, y1, y2, y3;
unsigned char u0, u1, u2, u3;
unsigned char v0, v1, v2, v3;
bool transparent;
SDL_Surface *s;
};
@ -29,6 +32,7 @@ struct rect
{
unsigned char r, g, b;
short x, y, w, h;
bool stp;
};
struct stp_4line

View File

@ -0,0 +1,13 @@
set(src "src/keyboard.c")
set(inc "inc")
if(PS1_BUILD)
set(src ${src} "ps1/src/keyboard.c")
elseif(SDL1_2_BUILD)
set(src ${src} "sdl-1.2/src/keyboard.c")
set(deps ${deps} SDL)
endif()
add_library(keyboard ${src})
target_include_directories(keyboard PUBLIC ${inc})
target_link_libraries(keyboard PUBLIC ${deps} PRIVATE ${privdeps})

View File

@ -0,0 +1,38 @@
#ifndef KEYBOARD_H
#define KEYBOARD_H
#include <keyboard_key.h>
#include <stdbool.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C"
{
#endif
#define KEYBOARD_COMBO(...) (const struct keyboard_combo){.keys = {__VA_ARGS__}}
enum {KEYBOARD_MAX_COMBO_KEYS = 3};
struct keyboard
{
struct keyboard_combo
{
enum keyboard_key keys[KEYBOARD_MAX_COMBO_KEYS];
} combo, oldcombo;
size_t i;
};
void keyboard_init(struct keyboard *k);
void keyboard_update(struct keyboard *k);
bool keyboard_justpressed(const struct keyboard *k, const struct keyboard_combo *c);
bool keyboard_pressed(const struct keyboard *k, const struct keyboard_combo *c);
bool keyboard_justreleased(const struct keyboard *k, const struct keyboard_combo *c);
const char *keyboard_key_str(enum keyboard_key k);
#ifdef __cplusplus
}
#endif
#endif /* KEYBOARD_H */

View File

@ -0,0 +1,70 @@
#ifndef KEYBOARD_KEYS_H
#define KEYBOARD_KEYS_H
#ifdef __cplusplus
extern "C"
{
#endif
#define KEYBOARD_KEYS \
X(KEYBOARD_KEY_NONE) \
X(KEYBOARD_KEY_A) \
X(KEYBOARD_KEY_B) \
X(KEYBOARD_KEY_C) \
X(KEYBOARD_KEY_D) \
X(KEYBOARD_KEY_E) \
X(KEYBOARD_KEY_F) \
X(KEYBOARD_KEY_G) \
X(KEYBOARD_KEY_H) \
X(KEYBOARD_KEY_I) \
X(KEYBOARD_KEY_J) \
X(KEYBOARD_KEY_K) \
X(KEYBOARD_KEY_L) \
X(KEYBOARD_KEY_M) \
X(KEYBOARD_KEY_N) \
X(KEYBOARD_KEY_O) \
X(KEYBOARD_KEY_P) \
X(KEYBOARD_KEY_Q) \
X(KEYBOARD_KEY_R) \
X(KEYBOARD_KEY_S) \
X(KEYBOARD_KEY_T) \
X(KEYBOARD_KEY_U) \
X(KEYBOARD_KEY_V) \
X(KEYBOARD_KEY_W) \
X(KEYBOARD_KEY_X) \
X(KEYBOARD_KEY_Y) \
X(KEYBOARD_KEY_Z) \
X(KEYBOARD_KEY_0) \
X(KEYBOARD_KEY_1) \
X(KEYBOARD_KEY_2) \
X(KEYBOARD_KEY_3) \
X(KEYBOARD_KEY_4) \
X(KEYBOARD_KEY_5) \
X(KEYBOARD_KEY_6) \
X(KEYBOARD_KEY_7) \
X(KEYBOARD_KEY_8) \
X(KEYBOARD_KEY_9) \
X(KEYBOARD_KEY_LSHIFT) \
X(KEYBOARD_KEY_RSHIFT) \
X(KEYBOARD_KEY_LCTRL) \
X(KEYBOARD_KEY_RCTRL) \
X(KEYBOARD_KEY_F11) \
X(KEYBOARD_KEY_ESC) \
X(KEYBOARD_KEY_LEFT) \
X(KEYBOARD_KEY_RIGHT) \
X(KEYBOARD_KEY_UP) \
X(KEYBOARD_KEY_DOWN) \
X(KEYBOARD_KEY_EXIT)
enum keyboard_key
{
#define X(x) x,
KEYBOARD_KEYS
#undef X
};
#ifdef __cplusplus
}
#endif
#endif /* KEYBOARD_KEYS_H */

View File

@ -0,0 +1,5 @@
#include <keyboard.h>
void keyboard_update(struct keyboard *const k)
{
}

View File

@ -0,0 +1,109 @@
#include <keyboard.h>
#include <keyboard_key.h>
#include <SDL/SDL.h>
#include <stdio.h>
static void append_key(const enum keyboard_key key, struct keyboard *const k)
{
struct keyboard_combo *const c = &k->combo;
for (size_t i = 0; i < sizeof c->keys / sizeof *c->keys; i++)
{
enum keyboard_key *const sel = &c->keys[i];
if (*sel == KEYBOARD_KEY_NONE)
{
*sel = key;
break;
}
}
}
static void remove_key(const enum keyboard_key key, struct keyboard *const k)
{
struct keyboard_combo *const c = &k->combo;
for (size_t i = 0; i < sizeof c->keys / sizeof *c->keys; i++)
{
enum keyboard_key *const sel = &c->keys[i];
if (*sel == key)
*sel = KEYBOARD_KEY_NONE;
}
}
static void key_event(const SDL_KeyboardEvent *const ev,
struct keyboard *const k)
{
static const struct keymap
{
enum keyboard_key key;
SDLKey sdl_key;
} keymap[] =
{
{.key = KEYBOARD_KEY_LEFT, .sdl_key = SDLK_LEFT},
{.key = KEYBOARD_KEY_RIGHT, .sdl_key = SDLK_RIGHT},
{.key = KEYBOARD_KEY_UP, .sdl_key = SDLK_UP},
{.key = KEYBOARD_KEY_DOWN, .sdl_key = SDLK_DOWN},
{.key = KEYBOARD_KEY_LCTRL, .sdl_key = SDLK_LCTRL},
{.key = KEYBOARD_KEY_RCTRL, .sdl_key = SDLK_RCTRL},
{.key = KEYBOARD_KEY_LSHIFT, .sdl_key = SDLK_LSHIFT},
{.key = KEYBOARD_KEY_RSHIFT, .sdl_key = SDLK_RSHIFT},
{.key = KEYBOARD_KEY_EXIT, .sdl_key = SDLK_ESCAPE},
{.key = KEYBOARD_KEY_F11, .sdl_key = SDLK_F11},
{.key = KEYBOARD_KEY_W, .sdl_key = SDLK_w},
{.key = KEYBOARD_KEY_A, .sdl_key = SDLK_a},
{.key = KEYBOARD_KEY_S, .sdl_key = SDLK_s},
{.key = KEYBOARD_KEY_D, .sdl_key = SDLK_d}
};
for (size_t i = 0; i < sizeof keymap / sizeof *keymap; i++)
{
const struct keymap *const km = &keymap[i];
if (ev->keysym.sym == km->sdl_key)
{
if (ev->state == SDL_PRESSED)
append_key(km->key, k);
else
remove_key(km->key, k);
}
}
}
void keyboard_update(struct keyboard *const k)
{
SDL_Event ev;
int n;
k->oldcombo = k->combo;
while ((n = SDL_PeepEvents(&ev, 1, SDL_GETEVENT,
SDL_KEYEVENTMASK | SDL_QUITMASK)) > 0)
{
switch (ev.type)
{
case SDL_KEYDOWN:
/* Fall through. */
case SDL_KEYUP:
key_event(&ev.key, k);
break;
case SDL_QUIT:
append_key(KEYBOARD_KEY_EXIT, k);
break;
default:
fprintf(stderr, "%s: unexpected SDL_Event %d\n",
__func__, ev.type);
break;
}
}
if (n < 0)
{
fprintf(stderr, "%s: SDL_PeepEvents: %s\n",
__func__, SDL_GetError());
return;
}
}

View File

@ -0,0 +1,69 @@
#include <keyboard.h>
#include <keyboard_key.h>
#include <stdbool.h>
#include <string.h>
static bool combo_pressed(const struct keyboard_combo *const ref,
const struct keyboard_combo *const c)
{
bool ret = false;
for (size_t i = 0; i < sizeof c->keys / sizeof *c->keys; i++)
{
const enum keyboard_key key = c->keys[i];
if (key != KEYBOARD_KEY_NONE)
{
bool success = false;
for (size_t i = 0; i < sizeof ref->keys / sizeof *ref->keys; i++)
{
if (key == ref->keys[i])
{
success = true;
break;
}
}
if (!(ret = success))
break;
}
}
return ret;
}
bool keyboard_pressed(const struct keyboard *const k,
const struct keyboard_combo *const c)
{
return combo_pressed(&k->combo, c);
}
bool keyboard_justreleased(const struct keyboard *const k,
const struct keyboard_combo *const c)
{
return !combo_pressed(&k->combo, c) && combo_pressed(&k->oldcombo, c);
}
bool keyboard_justpressed(const struct keyboard *const k,
const struct keyboard_combo *const c)
{
return combo_pressed(&k->combo, c) && !combo_pressed(&k->oldcombo, c);
}
void keyboard_init(struct keyboard *const k)
{
memset(k, 0, sizeof *k);
}
const char *keyboard_key_str(const enum keyboard_key k)
{
static const char *const s[] =
{
#define X(x) [x] = #x,
KEYBOARD_KEYS
#undef X
};
return s[k];
}

13
src/mouse/CMakeLists.txt Normal file
View File

@ -0,0 +1,13 @@
set(src "src/mouse.c")
set(inc "inc")
if(PS1_BUILD)
set(src ${src} "ps1/src/mouse.c")
elseif(SDL1_2_BUILD)
set(src ${src} "sdl-1.2/src/mouse.c")
set(deps ${deps} SDL)
endif()
add_library(mouse ${src})
target_include_directories(mouse PUBLIC ${inc})
target_link_libraries(mouse PUBLIC ${deps} PRIVATE ${privdeps})

32
src/mouse/inc/mouse.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef MOUSE_H
#define MOUSE_H
#include <stdbool.h>
#ifdef __cplusplus
extern "C"
{
#endif
enum mouse_button
{
MOUSE_BUTTON_LEFT,
MOUSE_BUTTON_RIGHT
};
struct mouse
{
short x, y;
int mask, oldmask;
};
void mouse_init(struct mouse *m);
void mouse_update(struct mouse *m);
bool mouse_justpressed(const struct mouse *m, enum mouse_button b);
bool mouse_justreleased(const struct mouse *m, enum mouse_button b);
#ifdef __cplusplus
}
#endif
#endif /* MOUSE_H */

View File

@ -0,0 +1,9 @@
#include <mouse.h>
void mouse_update(struct mouse *const m)
{
}
void mouse_init(struct mouse *const m)
{
}

View File

@ -0,0 +1,80 @@
#include <mouse.h>
#include <SDL/SDL.h>
#include <stdint.h>
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
static void mouse_click(const SDL_MouseButtonEvent *const ev,
struct mouse *const m)
{
int mask;
switch (ev->button)
{
case 1:
mask = 1 << MOUSE_BUTTON_LEFT;
break;
case 3:
mask = 1 << MOUSE_BUTTON_RIGHT;
break;
default:
return;
}
if (ev->state == SDL_PRESSED)
m->mask |= mask;
else
m->mask &= ~mask;
}
static void mouse_event(const SDL_MouseMotionEvent *const ev,
struct mouse *const m)
{
m->x = ev->x;
m->y = ev->y;
}
void mouse_update(struct mouse *const m)
{
SDL_Event ev;
int n;
m->oldmask = m->mask;
while ((n = SDL_PeepEvents(&ev, 1, SDL_GETEVENT, SDL_MOUSEMOTIONMASK
| SDL_MOUSEBUTTONDOWNMASK | SDL_MOUSEBUTTONUPMASK)) > 0)
{
switch (ev.type)
{
case SDL_MOUSEBUTTONDOWN:
/* Fall through. */
case SDL_MOUSEBUTTONUP:
mouse_click(&ev.button, m);
break;
case SDL_MOUSEMOTION:
mouse_event(&ev.motion, m);
break;
default:
fprintf(stderr, "%s: unexpected SDL_Event %d\n",
__func__, ev.type);
break;
}
}
if (n < 0)
{
fprintf(stderr, "%s: SDL_PeepEvents: %s\n",
__func__, SDL_GetError());
return;
}
}
void mouse_init(struct mouse *const m)
{
memset(m, 0, sizeof *m);
}

14
src/mouse/src/mouse.c Normal file
View File

@ -0,0 +1,14 @@
#include <mouse.h>
#include <stdbool.h>
bool mouse_justpressed(const struct mouse *const m,
const enum mouse_button b)
{
return m->mask & (1 << b) && !(m->oldmask & (1 << b));
}
bool mouse_justreleased(const struct mouse *const m,
const enum mouse_button b)
{
return !(m->mask & (1 << b)) && m->oldmask & (1 << b);
}

View File

@ -1,10 +1,15 @@
add_library(pad "src/pad.c")
target_include_directories(pad PUBLIC "inc" PRIVATE "privinc")
set(inc "inc")
set(privinc "privinc")
set(src "src/pad.c")
if(PS1_BUILD)
target_include_directories(pad PUBLIC "ps1/inc")
target_sources(pad PRIVATE "ps1/src/pad.c")
set(src ${src} "ps1/src/pad.c")
set(inc ${inc} "ps1/inc")
elseif(SDL1_2_BUILD)
target_include_directories(pad PUBLIC "sdl-1.2/inc")
target_sources(pad PRIVATE "sdl-1.2/src/pad.c")
set(src ${src} "sdl-1.2/src/pad.c")
set(inc ${inc} "sdl-1.2/inc")
set(deps ${deps} SDL)
endif()
add_library(pad ${src})
target_include_directories(pad PUBLIC ${inc} PRIVATE ${privinc})

View File

@ -19,13 +19,17 @@ extern "C"
X(PAD_KEY_C) \
X(PAD_KEY_D) \
X(PAD_KEY_E) \
X(PAD_KEY_OPTIONS)
X(PAD_KEY_OPTIONS) \
X(PAD_KEY_FULL_SCREEN) \
X(PAD_KEY_EXIT)
enum pad_key
{
#define X(x) x,
PAD_KEYS
#undef X
MAX_PAD_KEYS
};
struct pad

View File

@ -1,8 +1,6 @@
#ifndef PAD_SDL_1_2_H
#define PAD_SDL_1_2_H
#include <stdbool.h>
#ifdef __cplusplus
extern "C"
{
@ -10,7 +8,7 @@ extern "C"
struct pad_port
{
bool exit;
int dummy;
};
#ifdef __cplusplus

View File

@ -2,77 +2,8 @@
#include <SDL/SDL.h>
#include <stdio.h>
static void key_event(const SDL_KeyboardEvent *const key, struct pad *const p)
{
static const int keys[] =
{
[PAD_KEY_LEFT] = SDLK_LEFT,
[PAD_KEY_RIGHT] = SDLK_RIGHT,
[PAD_KEY_UP] = SDLK_UP,
[PAD_KEY_DOWN] = SDLK_DOWN,
[PAD_KEY_A] = SDLK_x,
[PAD_KEY_B] = SDLK_d,
[PAD_KEY_C] = SDLK_w,
[PAD_KEY_D] = SDLK_a,
[PAD_KEY_E] = SDLK_q,
[PAD_KEY_OPTIONS] = SDLK_ESCAPE
};
for (size_t i = 0; i < sizeof keys / sizeof *keys; i++)
{
const SDLKey k = key->keysym.sym;
if (k == keys[i])
{
const int mask = 1 << i;
if (key->type == SDL_KEYDOWN)
{
printf("%s pressed\n", pad_str(i));
p->mask |= mask;
}
else
{
printf("%s released\n", pad_str(i));
p->mask &= ~mask;
}
}
}
}
void pad_port_update(struct pad *const p)
{
SDL_Event ev;
static const int masks[] = {SDL_KEYEVENTMASK};
int n;
while ((n = SDL_PeepEvents(&ev, 1, SDL_GETEVENT,
masks[p->player] | SDL_QUITMASK)) > 0)
{
switch (ev.type)
{
case SDL_KEYDOWN:
/* Fall through. */
case SDL_KEYUP:
key_event(&ev.key, p);
break;
case SDL_QUIT:
p->port.exit = true;
break;
default:
fprintf(stderr, "%s: unexpected SDL_Event %d\n",
__func__, ev.type);
break;
}
}
if (n < 0)
{
fprintf(stderr, "%s: SDL_PeepEvents: %s\n", __func__, SDL_GetError());
return;
}
}
void pad_init(const int player, struct pad *const p)

View File

@ -5,7 +5,9 @@ target_link_libraries(player
building
camera
gfx
keyboard
instance
mouse
pad
resource
tech

View File

@ -2,7 +2,9 @@
#define HUMAN_PLAYER_H
#include <camera.h>
#include <keyboard.h>
#include <instance.h>
#include <mouse.h>
#include <pad.h>
#include <player.h>
#include <stdbool.h>
@ -15,11 +17,34 @@ extern "C"
enum {MAX_SELECTED_INSTANCES = 4};
struct human_player_cfg
{
enum human_player_periph
{
HUMAN_PLAYER_PERIPH_PAD,
HUMAN_PLAYER_PERIPH_KEYBOARD_MOUSE
} sel_periph;
struct player_cfg pl;
int padn;
};
struct human_player
{
struct player pl;
struct camera cam;
struct pad pad;
enum human_player_periph sel_periph;
union
{
struct pad pad;
struct
{
struct mouse mouse;
struct keyboard keyboard;
} kbm;
} periph;
struct sel_instance
{
@ -52,12 +77,6 @@ struct human_player
unsigned long gui_res[MAX_RESOURCE_TYPES];
};
struct human_player_cfg
{
struct player_cfg pl;
int padn;
};
int human_player_init(const struct human_player_cfg *cfg, struct human_player *h);
bool human_player_update(struct human_player *h, struct player_others *o);
int human_player_render(const struct human_player *h, const struct player_others *o);

View File

@ -2,8 +2,10 @@
#include <player.h>
#include <building.h>
#include <camera.h>
#include <gfx.h>
#include <gui.h>
#include <instance.h>
#include <keyboard.h>
#include <pad.h>
#include <resource.h>
#include <unit.h>
@ -29,7 +31,7 @@ static bool instance_selected(const struct human_player *const h,
}
static bool select_units(struct human_player *const h, const short x,
const short y)
const short y, const bool excl)
{
struct player *const pl = &h->pl;
@ -50,19 +52,37 @@ static bool select_units(struct human_player *const h, const short x,
&& cursor_collision(&h->cam, &in->r)
&& h->n_sel < sizeof h->sel / sizeof *h->sel)
{
for (size_t i = 0; i < sizeof h->sel / sizeof *h->sel; i++)
{
struct sel_instance *const sel = &h->sel[i];
struct sel_instance *sel = NULL;
if (!sel->d.u)
if (excl)
{
sel = h->sel;
h->n_sel = 1;
}
else
{
for (size_t i = 0; i < sizeof h->sel / sizeof *h->sel; i++)
{
sel->type = INSTANCE_TYPE_UNIT;
sel->d.u = u;
h->n_sel++;
sfx_play(&unit_sounds[UNIT_SOUND_SELECTED]);
return true;
struct sel_instance *const s = &h->sel[i];
if (!s->d.u)
{
sel = s;
h->n_sel++;
break;
}
}
}
if (sel)
{
sel->type = INSTANCE_TYPE_UNIT;
sel->d.u = u;
sfx_play(&unit_sounds[UNIT_SOUND_SELECTED]);
return true;
}
return false;
}
}
break;
@ -79,7 +99,7 @@ static bool select_units(struct human_player *const h, const short x,
}
static bool select_buildings(struct human_player *const h, const short x,
const short y)
const short y, const bool excl)
{
struct player *const pl = &h->pl;
@ -96,18 +116,36 @@ static bool select_buildings(struct human_player *const h, const short x,
&& cursor_collision(&h->cam, &in->r)
&& h->n_sel < sizeof h->sel / sizeof *h->sel)
{
for (size_t i = 0; i < sizeof h->sel / sizeof *h->sel; i++)
{
struct sel_instance *const sel = &h->sel[i];
struct sel_instance *sel = NULL;
if (!sel->d.b)
if (excl)
{
sel = h->sel;
h->n_sel = 1;
}
else
{
for (size_t i = 0; i < sizeof h->sel / sizeof *h->sel; i++)
{
sel->type = INSTANCE_TYPE_BUILDING;
sel->d.b = b;
h->n_sel++;
return true;
struct sel_instance *const s = &h->sel[i];
if (!s->d.b)
{
sel = s;
h->n_sel++;
break;
}
}
}
if (sel)
{
sel->type = INSTANCE_TYPE_BUILDING;
sel->d.b = b;
return true;
}
return false;
}
}
}
@ -116,7 +154,7 @@ static bool select_buildings(struct human_player *const h, const short x,
}
static bool select_resources(struct human_player *const h, const short x,
const short y, const struct player_others *const o)
const short y, const struct player_others *const o, const bool excl)
{
for (size_t i = 0; i < o->n_res; i++)
{
@ -131,18 +169,36 @@ static bool select_resources(struct human_player *const h, const short x,
&& cursor_collision(&h->cam, &in->r)
&& h->n_sel < sizeof h->sel / sizeof *h->sel)
{
for (size_t i = 0; i < sizeof h->sel / sizeof *h->sel; i++)
{
struct sel_instance *const sel = &h->sel[i];
struct sel_instance *sel = NULL;
if (!sel->d.r)
if (excl)
{
sel = h->sel;
h->n_sel = 1;
}
else
{
for (size_t i = 0; i < sizeof h->sel / sizeof *h->sel; i++)
{
sel->type = INSTANCE_TYPE_RESOURCE;
sel->d.r = r;
h->n_sel++;
return true;
struct sel_instance *const s = &h->sel[i];
if (!s->d.r)
{
sel = s;
h->n_sel++;
break;
}
}
}
if (sel)
{
sel->type = INSTANCE_TYPE_RESOURCE;
sel->d.r = r;
return true;
}
return false;
}
}
}
@ -150,16 +206,16 @@ static bool select_resources(struct human_player *const h, const short x,
return false;
}
static void select_instances(struct human_player *const h,
const struct player_others *const o)
static bool select_instances(struct human_player *const h,
const struct player_others *const o, const bool excl)
{
unsigned long x, y;
cursor_pos(&h->cam, &x, &y);
if (!select_buildings(h, x, y)
&& !select_units(h, x, y))
select_resources(h, x, y, o);
return select_buildings(h, x, y, excl)
|| select_units(h, x, y, excl)
|| select_resources(h, x, y, o, excl);
}
static bool instance_collision(const struct camera *const cam,
@ -450,6 +506,58 @@ static void update_target(struct human_player *const h)
}
}
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);
if (pad_justpressed(p, PAD_KEY_OPTIONS)
|| pad_justpressed(p, PAD_KEY_EXIT))
ret = true;
else if (pad_justpressed(p, PAD_KEY_A))
select_instances(h, o, false);
else if (pad_justpressed(p, PAD_KEY_B))
move_units(h, o);
else if (pad_justpressed(p, PAD_KEY_C))
deselect_instances(h);
else if (pad_justpressed(p, PAD_KEY_E))
h->top_gui ^= true;
return ret;
}
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;
mouse_update(m);
keyboard_update(k);
if (mouse_justreleased(m, MOUSE_BUTTON_LEFT))
{
const bool shift_pressed =
keyboard_pressed(k, &KEYBOARD_COMBO(KEYBOARD_KEY_LSHIFT))
|| keyboard_pressed(k, &KEYBOARD_COMBO(KEYBOARD_KEY_RSHIFT));
if (!select_instances(h, o, !shift_pressed))
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;
}
bool human_player_update(struct human_player *const h,
struct player_others *const o)
{
@ -459,22 +567,22 @@ bool human_player_update(struct human_player *const h,
if (p->alive)
{
gui_update(h);
pad_update(&h->pad);
update_selected(h);
update_target(h);
if (pad_justpressed(&h->pad, PAD_KEY_OPTIONS))
ret = true;
else if (pad_justpressed(&h->pad, PAD_KEY_A))
select_instances(h, o);
else if (pad_justpressed(&h->pad, PAD_KEY_B))
move_units(h, o);
else if (pad_justpressed(&h->pad, PAD_KEY_C))
deselect_instances(h);
else if (pad_justpressed(&h->pad, PAD_KEY_E))
h->top_gui ^= true;
switch (h->sel_periph)
{
case HUMAN_PLAYER_PERIPH_PAD:
ret = update_from_pad(h, o);
camera_update_pad(&h->cam, &h->periph.pad);
break;
case HUMAN_PLAYER_PERIPH_KEYBOARD_MOUSE:
ret = update_from_keyboard_mouse(h, o);
camera_update_mouse(&h->cam, &h->periph.kbm.mouse);
break;
}
camera_update(&h->cam, &h->pad);
player_update(p);
}
@ -562,7 +670,18 @@ int human_player_init(const struct human_player_cfg *const cfg,
if (player_init(&cfg->pl, &h->pl))
return -1;
pad_init(cfg->padn, &h->pad);
switch (h->sel_periph = cfg->sel_periph)
{
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;
}
cursor_init(&h->cam.cursor);
h->top_gui = true;
memmove(h->gui_res, h->pl.resources, sizeof h->gui_res);