~jb55/polyadvent

4b9272c4f291493e3d4bbd94eb1217a88475e88f — William Casarin 1 year, 7 months ago d0b952b
input: initial controller support

Signed-off-by: William Casarin <jb55@jb55.com>
5 files changed, 101 insertions(+), 31 deletions(-)

M src/game.c
M src/game.h
M src/input.c
M src/input.h
M src/update.c
M src/game.c => src/game.c +49 -14
@@ 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);
}

M src/game.h => src/game.h +2 -1
@@ 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 */

M src/input.c => src/input.c +39 -4
@@ 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;

M src/input.h => src/input.h +6 -8
@@ 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);


M src/update.c => src/update.c +5 -4
@@ 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", */