polyadvent

A game engine from scratch in C
git clone git://jb55.com/polyadvent
Log | Files | Refs | README

commit 4b9272c4f291493e3d4bbd94eb1217a88475e88f
parent d0b952b2cdbb7ceff03c2c9a87b3eb95341a6535
Author: William Casarin <jb55@jb55.com>
Date:   Mon, 27 Apr 2020 01:10:48 -0700

input: initial controller support

Signed-off-by: William Casarin <jb55@jb55.com>

Diffstat:
Msrc/game.c | 63+++++++++++++++++++++++++++++++++++++++++++++++++--------------
Msrc/game.h | 3++-
Msrc/input.c | 43+++++++++++++++++++++++++++++++++++++++----
Msrc/input.h | 14++++++--------
Msrc/update.c | 9+++++----
5 files changed, 101 insertions(+), 31 deletions(-)

diff --git a/src/game.c b/src/game.c @@ -25,10 +25,16 @@ mat4 *cam_init = (float[16]){ -71.766136, -47.881512, -44.216671, 1.000000 }; -int was_key_pressed_this_frame(struct game *game, int scancode) { +bool was_key_pressed_this_frame(struct game *game, int scancode) +{ return is_key_down_on_frame(&game->input, scancode, game->frame); } +bool was_button_pressed_this_frame(struct game *game, SDL_GameControllerButton button) +{ + return is_button_down_on_frame(&game->input, button, game->frame); +} + static void camera_update(struct node *node) { mat4 *persp = (float*)node->custom_update_data; mat4 *mat = (float*)node->mat; @@ -58,7 +64,7 @@ static void init_user_settings(struct user_settings *settings) { static void init_sdl(SDL_Window **window, int width, int height) { - /* SDL_Init( SDL_INIT_VIDEO ); */ + SDL_Init( SDL_INIT_JOYSTICK ); /* SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); */ @@ -73,18 +79,8 @@ void quit_game(struct game *game) game->quit = 1; } -void game_init(struct game *game, int width, int height) { - init_sdl(&game->window, width, height); - init_gl(&game->test_resources, width, height); - init_entity_system(); - init_geometry_manager(); - init_model_manager(); - init_node_manager(); - init_user_settings(&game->user_settings); - check_gl(); - - game->wireframe = 0; - +// TODO: cleanup +void init_misc(struct game *game, int width, int height) { struct resources *res = &game->test_resources; mat4 *mvp = res->test_mvp; @@ -209,3 +205,42 @@ void game_init(struct game *game, int width, int height) { // TEXTURES // END TEXTURES } + +void init_controller(struct input *input) { + SDL_GameControllerAddMappingsFromFile("data/gamecontrollerdb.txt"); + + int joysticks = SDL_NumJoysticks(); + SDL_GameController *controller = NULL; + + printf("Found %d joysticks\n", joysticks); + + for (int i = 0; i < joysticks; i++) { + if (SDL_IsGameController(i)) { + controller = SDL_GameControllerOpen(i); + if (controller) { + printf("Found a game controller\n"); + input->controller = controller; + break; + } + } else { + printf("Could not open game controller %d: %s\n", i, SDL_GetError()); + } + } +} + +void game_init(struct game *game, int width, int height) { + init_sdl(&game->window, width, height); + init_gl(&game->test_resources, width, height); + init_entity_system(); + init_geometry_manager(); + init_model_manager(); + init_node_manager(); + init_user_settings(&game->user_settings); + + check_gl(); + + game->wireframe = 0; + + init_controller(&game->input); + init_misc(game, width, height); +} diff --git a/src/game.h b/src/game.h @@ -103,7 +103,8 @@ struct entity *get_terrain_entity(struct terrain *); void game_init(struct game *game, int width, int height); void quit_game(struct game *game); void should_update(struct game *game); -int was_key_pressed_this_frame(struct game *game, int scancode); +bool was_key_pressed_this_frame(struct game *game, int scancode); +bool was_button_pressed_this_frame(struct game *game, SDL_GameControllerButton button); int is_free_camera(struct game *game); #endif /* PA_GAME_H */ diff --git a/src/input.c b/src/input.c @@ -7,7 +7,7 @@ static void key_down(struct input *input, int scancode, u64 current_frame) { input->modifiers = SDL_GetModState(); - struct key_edge *edge = &input->key_edge_states[scancode]; + struct input_edge *edge = &input->key_edge_states[scancode]; if (edge->is_down) return; @@ -20,12 +20,35 @@ static void key_down(struct input *input, int scancode, u64 current_frame) { } static void key_up(struct input *input, int scancode, u64 current_frame) { - struct key_edge *edge = &input->key_edge_states[scancode]; + struct input_edge *edge = &input->key_edge_states[scancode]; edge->up_frame = current_frame; edge->is_down = 0; } +static void button_up(struct input *input, SDL_JoyButtonEvent *event, u64 current_frame) +{ + if (event->button >= SDL_CONTROLLER_BUTTON_MAX) return; + /* printf("button up %d\n", event->button); */ + struct input_edge *edge = &input->button_edge_states[event->button]; + + edge->up_frame = current_frame; + edge->is_down = 0; +} + +static void button_down(struct input *input, SDL_JoyButtonEvent *event, u64 current_frame) +{ + if (event->button >= SDL_CONTROLLER_BUTTON_MAX) return; + /* printf("button down %d\n", event->button); */ + + struct input_edge *edge = &input->button_edge_states[event->button]; + + if (edge->is_down) + return; + + edge->down_frame = current_frame; + edge->is_down = 1; +} void process_events(struct input *input, u64 current_frame) { SDL_Event event; @@ -47,6 +70,12 @@ void process_events(struct input *input, u64 current_frame) { case SDL_KEYUP: key_up(input, event.key.keysym.scancode, current_frame); break; + case SDL_JOYBUTTONUP: + button_up(input, &event.jbutton, current_frame); + break; + case SDL_JOYBUTTONDOWN: + button_down(input, &event.jbutton, current_frame); + break; case SDL_MOUSEBUTTONDOWN: if (event.button.button <= MOUSE_BUTTONS) input->mbuttons[event.button.button-1] = 1; @@ -106,13 +135,19 @@ void input_init(struct input *input) { assert(input->keystates); } -int is_key_down_on_frame(struct input *input, u8 scancode, u64 frame) { - struct key_edge *edge = &input->key_edge_states[scancode]; +bool is_key_down_on_frame(struct input *input, u8 scancode, u64 frame) { + struct input_edge *edge = &input->key_edge_states[scancode]; // is_down is implied, but do it for good measure return edge->down_frame == frame && edge->is_down; } +bool is_button_down_on_frame(struct input *input, SDL_GameControllerButton button, u64 frame) +{ + struct input_edge *edge = &input->button_edge_states[button]; + return edge->down_frame == frame && edge->is_down; +} + void input_reset(struct input *input) { input->mdx = 0; diff --git a/src/input.h b/src/input.h @@ -19,12 +19,7 @@ #define FLAG_KEY_DOWN (1<<0) #define FLAG_KEY_UP (1<<1) -enum key_edge_state { - EDGE_KEY_DOWN = 1 << 0, - EDGE_KEY_UP = 1 << 1, -}; - -struct key_edge { +struct input_edge { int is_down; u64 down_frame; u64 up_frame; @@ -34,6 +29,7 @@ struct input { /* enum key_state keys[0x7F-0x1F]; */ u8 const *keystates; SDL_Keymod modifiers; + SDL_GameController *controller; int mx, my, last_mx, last_my; int mdx, mdy; float wheel_x, wheel_y; @@ -46,12 +42,14 @@ struct input { /* u64 up_key_frames[KEY_BUFFER_SIZE]; */ /* u8 frame_down_keys[KEY_BUFFER_SIZE]; */ /* u8 frame_up_keys[KEY_BUFFER_SIZE]; */ - struct key_edge key_edge_states[SDL_NUM_SCANCODES]; + struct input_edge key_edge_states[SDL_NUM_SCANCODES]; + struct input_edge button_edge_states[SDL_CONTROLLER_BUTTON_MAX]; }; int input_is_dragging(struct input *input, int mouse_button); -int is_key_down_on_frame(struct input *input, u8 scancode, u64 frame); +bool is_key_down_on_frame(struct input *input, u8 scancode, u64 frame); +bool is_button_down_on_frame(struct input *input, SDL_GameControllerButton button, u64 frame); void input_init(struct input *input); diff --git a/src/update.c b/src/update.c @@ -348,12 +348,12 @@ static void camera_keep_above_ground(struct terrain *terrain, } } -static void entity_jump(struct entity *ent) +static void entity_jump(struct entity *ent, float amount) { float dir[3]; debug("jumping\n"); vec3_normalize(ent->velocity, dir); - vec3_add(dir, V3(0,0,1.0), dir); + vec3_add(dir, V3(0, 0, amount), dir); vec3_add(ent->velocity, dir, ent->velocity); } @@ -409,8 +409,9 @@ static void player_update(struct game *game, struct entity *player) } if (player->flags & ENT_ON_GROUND && - was_key_pressed_this_frame(game, SDL_SCANCODE_SPACE)) { - entity_jump(player); + (was_key_pressed_this_frame(game, SDL_SCANCODE_SPACE) || + was_button_pressed_this_frame(game, SDL_CONTROLLER_BUTTON_X))) { + entity_jump(player, 0.5); } /* debug("player velocity %f %f %f\n", */