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:
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", */