diff --git a/src/fencer.c b/src/fencer.c index c46c394..b796d8a 100644 --- a/src/fencer.c +++ b/src/fencer.c @@ -17,7 +17,7 @@ static Player* player = NULL; static Level* level = NULL; static -void toggle_info_key(int down) { +void toggle_info_key(void* null, int down) { if(down) { g_debug_log_lvl = (g_debug_log_lvl + 1) % 4; } @@ -25,7 +25,7 @@ void toggle_info_key(int down) { static void play() { - input_add_key_action(SDL_SCANCODE_F1, &toggle_info_key); + input_add_key_action(NULL, InputDelegate(toggle_info_key), SDL_SCANCODE_F1); g_camera.fov = 40; player = player_new(); diff --git a/src/input.c b/src/input.c index e9694b6..5d8e71d 100644 --- a/src/input.c +++ b/src/input.c @@ -1,46 +1,38 @@ #include "input.h" #include "debug.h" +#include "list.h" #include typedef struct InputAction { const uint8_t* positive; const uint8_t* negative; int last; + void* object_arg; InputActionDelegate delegate; } InputAction; -static InputAction* _actions = NULL; -static size_t _actions_len = 0; -static size_t _actions_cap = 0; +static List _actions; static const uint8_t* _keys; void input_init() { - _actions = malloc(8 * sizeof(InputAction)); - if(_actions == NULL) { - LOG_ERROR("Failed to allocate memory for input actions array"); - return; - } - _actions_cap = 8; - + _actions = list_from_type(InputAction); _keys = SDL_GetKeyboardState(NULL); } void input_clean() { - free(_actions); - _actions_len = 0; - _actions_cap = 0; + list_empty(&_actions); } static void _key_changed_event(SDL_Event evt) { const uint8_t* keyptr = _keys + evt.key.keysym.scancode; - for(InputAction* action = _actions; action < _actions + _actions_len; ++action) { + list_foreach(InputAction, action, &_actions) { if(keyptr == action->positive || keyptr == action->negative) { int val = *action->positive - *action->negative; if(val != action->last) { action->last = val; - action->delegate(val); + action->delegate(action->object_arg, val); } } } @@ -56,60 +48,28 @@ void input_handle_event(SDL_Event event) { } } -static -void _resize_actions_if_needed(size_t needed_amount) { - if(_actions_cap > needed_amount) - return; - - size_t next_amount = _actions_cap; - while(next_amount <= needed_amount) { - next_amount *= 2; - } - - InputAction* new = realloc(_actions, next_amount); - if(new == NULL) { - LOG_ERROR("Failed to allocate enough space for adding a new input actions"); - return; - } - _actions = new; - _actions_cap = next_amount; -} - -void input_add_axis_action(SDL_Scancode negative, SDL_Scancode positive, InputActionDelegate delegate) { - _resize_actions_if_needed(_actions_len + 1); - _actions[_actions_len] = (InputAction){ +void input_add_axis_action(void* object, InputActionDelegate delegate, SDL_Scancode negative, SDL_Scancode positive) { + list_add(&_actions, &(InputAction){ .negative = _keys + negative, .positive = _keys + positive, - .delegate = delegate - }; - ++_actions_len; + .delegate = delegate, + .object_arg = object, + }); } -void input_add_key_action(SDL_Scancode key, InputActionDelegate delegate) { - _resize_actions_if_needed(_actions_len + 1); - _actions[_actions_len] = (InputAction) { +void input_add_key_action(void* object, InputActionDelegate delegate, SDL_Scancode key) { + list_add(&_actions, &(InputAction) { .negative = _keys + SDL_SCANCODE_UNKNOWN, .positive = _keys + key, - .delegate = delegate - }; - ++_actions_len; + .delegate = delegate, + .object_arg = object, + }); } -static -void _remove_element(InputAction* item) { - InputAction* next = item + 1; - - if(next < _actions + _actions_len) { - memmove(item, next, (_actions + _actions_len) - next); - } - - --_actions_len; -} - -void input_remove_actions(InputActionDelegate delegate) { - for(InputAction* action = _actions; action < _actions + _actions_len; ++action) { - if(action->delegate == delegate) { - _remove_element(action); +void input_remove_actions(void* object) { + for(size_t i = 0; i < _actions.len; ++i) { + if(list_at_as(InputAction, &_actions, i)->object_arg == object) { + list_erase(&_actions, i); } } } diff --git a/src/input.h b/src/input.h index c550526..0b7443e 100644 --- a/src/input.h +++ b/src/input.h @@ -5,15 +5,23 @@ #include #include -typedef void (*InputActionDelegate)(int value); +// input listener +typedef void (*InputActionDelegate)(void* object, int value); extern void input_init(); extern void input_clean(); +// handle an input event extern void input_handle_event(SDL_Event event); -extern void input_add_axis_action(SDL_Scancode negative, SDL_Scancode positive, InputActionDelegate delegate); -extern void input_add_key_action(SDL_Scancode key, InputActionDelegate delegate); -extern void input_remove_actions(InputActionDelegate delegate); +// create a new axis action triggering on a change of either 'negative' or 'positive' and invoking 'delegate' with first argument 'object' +extern void input_add_axis_action(void* object, InputActionDelegate delegate, SDL_Scancode negative, SDL_Scancode positive); +// create a new key action triggering on 'key' change invoking 'delegate' on 'object'. +extern void input_add_key_action(void* object, InputActionDelegate delegate, SDL_Scancode key); +// remove all actions related to 'object'. +extern void input_remove_actions(void* object); + +#define InputDelegate(__Listener)\ + ((InputActionDelegate)&__Listener) #endif // !_fencer_input_h diff --git a/src/player.c b/src/player.c index 95093b9..4f96d06 100644 --- a/src/player.c +++ b/src/player.c @@ -8,23 +8,18 @@ #include "physics_world.h" #include "game_world.h" -static Vector _directional = ZeroVector; -static Spritesheet* spr_player_standing = NULL; - static -void player_input_h(int val) { - _directional.x = val * 10.f; +void player_input_h(Player* self, int val) { + self->directional.x = val * 10.f; } static -void player_input_v(int val) { - _directional.y = -val * 10.f; +void player_input_v(Player* self, int val) { + self->directional.y = -val * 10.f; } Player* player_new() { - input_add_axis_action(SDL_SCANCODE_A, SDL_SCANCODE_D, &player_input_h); - input_add_axis_action(SDL_SCANCODE_S, SDL_SCANCODE_W, &player_input_v); - spr_player_standing = spritesheet_load("assets/sprites/player.png", (IVector){128, 128}); + Spritesheet* spr_player_standing = spritesheet_load("assets/sprites/player.png", (IVector){128, 128}); float ex_w = 0.1f; float h = .75f; @@ -45,6 +40,8 @@ Player* player_new() { rigidbody_set_mass(self->rigidbody, 10.f); physics_world_add_entity(Player_as_PhysicsEntity(self)); sprite_set_origin(self->sprite, (Vector){0.25f, 1.f}); + input_add_axis_action(self, InputDelegate(player_input_h), SDL_SCANCODE_A, SDL_SCANCODE_D); + input_add_axis_action(self, InputDelegate(player_input_v), SDL_SCANCODE_S, SDL_SCANCODE_W); return self; } @@ -61,9 +58,9 @@ void player_start(Player* self) {} void player_update(Player* self, float dt) { Vector velocity = rigidbody_get_velocity(self->rigidbody); - Vector velocity_target = {self->is_grounded ? _directional.x : velocity.x, velocity.y}; - if(_directional.y < 0 && self->is_grounded) { - _directional.y = 0; + Vector velocity_target = {self->is_grounded ? self->directional.x : velocity.x, velocity.y}; + if(self->directional.y < 0 && self->is_grounded) { + self->directional.y = 0; velocity.y = -30.f; rigidbody_set_velocity(self->rigidbody, velocity); } @@ -80,6 +77,7 @@ void player_free(Player* self) { rigidbody_destroy(self->rigidbody); shape_destroy(self->shape); sprite_destroy(self->sprite); + input_remove_actions(self); free(self); } diff --git a/src/player.h b/src/player.h index 5ff7c34..c45cabe 100644 --- a/src/player.h +++ b/src/player.h @@ -14,6 +14,8 @@ typedef struct Player { RigidBody* rigidbody; Shape* shape; + Vector directional; + Sprite* sprite; int is_grounded; } Player;