ohsp

Prototype for a game with dual thruster controls.
git clone git://git.amin.space/ohsp.git
Log | Files | Refs | LICENSE

commit d412dad2a013993ae5a714107c4db327ec79d27c
parent 3fed33a8a0f682c28fcba1c3788c03aefed6b933
Author: amin <dev@aminmesbah.com>
Date:   Wed, 25 Oct 2017 03:26:50 +0000

Get controller input through SDL event API

FossilOrigin-Name: 35e4ec6f7e7d86754023244baeb87b4b4516a6259f6a4d7d20c4250285314b56
Diffstat:
MMakefile | 2+-
Msrc/game.c | 5+++--
Msrc/game.h | 11++++++++++-
Msrc/platform_sdl.c | 160+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
Msrc/platform_sdl.h | 3+++
5 files changed, 117 insertions(+), 64 deletions(-)

diff --git a/Makefile b/Makefile @@ -7,7 +7,7 @@ SDL_LDFLAGS := $(shell sdl2-config --libs) override CFLAGS += $(SDL_CFLAGS) -SRC_FILES = platform_sdl.c game.c +SRC_FILES = platform_sdl.c game.c entity.c SRC = $(addprefix src/, $(SRC_FILES)) EXE = ohsp diff --git a/src/game.c b/src/game.c @@ -1,6 +1,7 @@ #include "game.h" #include <stdbool.h> +#include <stdio.h> bool PAUSED = false; @@ -22,11 +23,11 @@ void game_init(struct GameState *game_state, int field_width, int field_height) game_state->player.size = 100; game_state->player.x = field_width / 2; game_state->player.y = field_height / 2; - game_state->player.color = 0xFFFFFF; + game_state->player.color = 0x888888; } -void game_update(struct GameState *game_state, int field_width, int field_height) +void game_update(struct GameState *game_state, struct GameControllerInput game_input, int field_width, int field_height) { if (!game_state) { diff --git a/src/game.h b/src/game.h @@ -29,6 +29,15 @@ struct GameBounds float side_length_y; }; +struct GameControllerInput +{ + uint8_t controller_index; + float left_stick_x; + float left_stick_y; + float right_stick_x; + float right_stick_y; +}; + struct GameView { float dx; @@ -52,7 +61,7 @@ struct OffscreenBuffer }; void game_init(struct GameState *game_state, int field_width, int field_height); -void game_update(struct GameState *game_state, int field_width, int field_height); +void game_update(struct GameState *game_state, struct GameControllerInput game_input, int field_width, int field_height); void game_render(struct OffscreenBuffer *buffer, float dt, struct GameState *game_state); void game_render_circle(struct OffscreenBuffer *buffer, float x, float y, float radius, uint32_t color); float game_calc_render_offset(float zoom, float delta, float pos, float center); diff --git a/src/platform_sdl.c b/src/platform_sdl.c @@ -69,8 +69,28 @@ void clear_screen(struct SDLOffscreenBuffer *buffer, uint32_t pixel_value) } -bool handle_event(SDL_Event *event) +float sdl_process_controller_axis_value(int16_t value, int16_t deadzone_threshold) { + float result = 0.0; + if (value < -deadzone_threshold) + { + result = (float)(value + deadzone_threshold) / (32768.0f - deadzone_threshold); + } + else if (value > deadzone_threshold) + { + result = (float)(value - deadzone_threshold) / (32767.0f - deadzone_threshold); + } + return result; +} + + +bool sdl_handle_event(SDL_Event *event, struct GameControllerInput *controller_input) +{ + if (!event || !controller_input) + { + return true; + } + bool should_quit = false; switch(event->type) @@ -94,6 +114,43 @@ bool handle_event(SDL_Event *event) } } } break; + + case SDL_CONTROLLERAXISMOTION: + { + // down and right are positive + float normalized_axis_value = sdl_process_controller_axis_value(event->caxis.value, DEADZONE_THRESHOLD); + + printf("SDL_CONTROLLERAXISMOTION (%d, %s, %d, %f)\n", + event->caxis.which, + SDL_GameControllerGetStringForAxis(event->caxis.axis), + event->caxis.value, + normalized_axis_value); + + switch(event->caxis.axis) + { + case SDL_CONTROLLER_AXIS_LEFTX: + { + controller_input->left_stick_x = normalized_axis_value; + } break; + case SDL_CONTROLLER_AXIS_LEFTY: + { + controller_input->left_stick_y = normalized_axis_value; + } break; + case SDL_CONTROLLER_AXIS_RIGHTX: + { + controller_input->right_stick_x = normalized_axis_value; + } break; + case SDL_CONTROLLER_AXIS_RIGHTY: + { + controller_input->right_stick_y = normalized_axis_value; + } break; + default: + { + printf("Unhandled axis input\n"); + } + } + } break; + case SDL_WINDOWEVENT: { switch(event->window.event) @@ -126,7 +183,7 @@ bool handle_event(SDL_Event *event) int main(int argc, char *argv[]) { - if (SDL_Init(SDL_INIT_VIDEO)) + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER)) { // TODO(amin): log SDL_Init error } @@ -160,12 +217,36 @@ int main(int argc, char *argv[]) srand((uint32_t)time(NULL)); #endif + int num_joysticks = SDL_NumJoysticks(); + SDL_GameController *controller_handles[MAX_CONTROLLERS]; + for (int controller_index = 0; controller_index < num_joysticks; ++controller_index) + { + if (!SDL_IsGameController(controller_index)) + { + continue; + } + + if (controller_index >= MAX_CONTROLLERS) + { + break; + } + + controller_handles[controller_index] = SDL_GameControllerOpen(controller_index); + } + uint64_t lag = 0; uint64_t previous_ms = (SDL_GetPerformanceCounter() * SECOND) / SDL_GetPerformanceFrequency(); struct GameState game_state; game_init(&game_state, dimension.width, dimension.height); + struct GameControllerInput controller_input; + controller_input.controller_index = 0; + controller_input.left_stick_x = 0; + controller_input.right_stick_y = 0; + controller_input.left_stick_x = 0; + controller_input.right_stick_y = 0; + while (running) { uint64_t current_ms = (SDL_GetPerformanceCounter() * SECOND) / SDL_GetPerformanceFrequency(); @@ -175,70 +256,14 @@ int main(int argc, char *argv[]) //printf("%" PRIu64 ", %" PRIu64 ", %f\n", elapsed_ms, lag, MS_PER_UPDATE); SDL_Event event; - while (SDL_PollEvent(&event)) { - running = !handle_event(&event); + running = !sdl_handle_event(&event, &controller_input); } - SDL_PumpEvents(); dimension = sdl_get_window_dimension(window); - const uint8_t *keystate = SDL_GetKeyboardState(0); - - // TODO: move this to a function - if (keystate[SDL_SCANCODE_A] || keystate[SDL_SCANCODE_H]) - { - game_state.player.x -= 5 / game_state.view.zoom; - } - if (keystate[SDL_SCANCODE_D] || keystate[SDL_SCANCODE_L]) - { - game_state.player.x += 5 / game_state.view.zoom; - } - if (keystate[SDL_SCANCODE_W] || keystate[SDL_SCANCODE_K]) - { - game_state.player.y -= 5 / game_state.view.zoom; - } - if (keystate[SDL_SCANCODE_S] || keystate[SDL_SCANCODE_J]) - { - game_state.player.y += 5 / game_state.view.zoom; - } - if (keystate[SDL_SCANCODE_LEFT]) - { - game_state.player.x -= 1 / game_state.view.zoom; - } - if (keystate[SDL_SCANCODE_RIGHT]) - { - game_state.player.x += 1 / game_state.view.zoom; - } - if (keystate[SDL_SCANCODE_UP]) - { - game_state.player.y -= 1 / game_state.view.zoom; - } - if (keystate[SDL_SCANCODE_DOWN]) - { - game_state.player.y += 1 / game_state.view.zoom; - } - if (keystate[SDL_SCANCODE_EQUALS]) - { - game_state.view.zoom *= 1.01; - } - if (keystate[SDL_SCANCODE_MINUS]) - { - game_state.view.zoom *= 0.99; - } - if (keystate[SDL_SCANCODE_0]) - { - game_state.view.zoom = 1; - } - if (keystate[SDL_SCANCODE_HOME]) - { - game_state.player.x = 0; - game_state.player.y = 0; - game_state.view.zoom = 1; - } - struct OffscreenBuffer buffer; // WARNING: these pointers are aliased until the end of the // loop @@ -255,7 +280,7 @@ int main(int argc, char *argv[]) { while (lag >= MS_PER_UPDATE) { - game_update(&game_state, buffer.width, buffer.height); + game_update(&game_state, controller_input, buffer.width, buffer.height); //printf("\t%" PRIu64 ", %f\n", lag, MS_PER_UPDATE); lag -= MS_PER_UPDATE; } @@ -271,6 +296,21 @@ int main(int argc, char *argv[]) } game_cleanup(&game_state); + + for (int controller_index = 0; controller_index < num_joysticks; ++controller_index) + { + if (!SDL_IsGameController(controller_index)) + { + continue; + } + + if (controller_index >= MAX_CONTROLLERS) + { + break; + } + + SDL_GameControllerClose(controller_handles[controller_index]); + } } else { diff --git a/src/platform_sdl.h b/src/platform_sdl.h @@ -2,6 +2,9 @@ #include "SDL.h" +#define MAX_CONTROLLERS 4 +#define DEADZONE_THRESHOLD 1000 + struct SDLOffscreenBuffer { // NOTE(amin): pixels are always 32-bits wide. Memory order: BB GG RR XX.