-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Add gamepad support to woodeneye-008 #14167
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,6 +15,7 @@ | |
| typedef struct { | ||
| SDL_MouseID mouse; | ||
| SDL_KeyboardID keyboard; | ||
| SDL_Gamepad *gamepad; | ||
| double pos[3]; | ||
| double vel[3]; | ||
| unsigned int yaw; | ||
|
|
@@ -60,6 +61,15 @@ static int whoseKeyboard(SDL_KeyboardID keyboard, const Player players[], int pl | |
| return -1; | ||
| } | ||
|
|
||
| static int whoseGamepad(SDL_JoystickID gamepad, const Player players[], int players_len) | ||
| { | ||
| int i; | ||
| for (i = 0; i < players_len; i++) { | ||
| if (SDL_GetGamepadID(players[i].gamepad) == gamepad) return i; | ||
| } | ||
| return -1; | ||
| } | ||
|
|
||
| static void shoot(int shooter, Player players[], int players_len) | ||
| { | ||
| int i, j; | ||
|
|
@@ -288,6 +298,7 @@ static void initPlayers(Player *players, int len) | |
| players[i].wasd = 0; | ||
| players[i].mouse = 0; | ||
| players[i].keyboard = 0; | ||
| players[i].gamepad = NULL; | ||
| players[i].color[0] = (1 << (i / 2)) & 2 ? 0 : 0xff; | ||
| players[i].color[1] = (1 << (i / 2)) & 1 ? 0 : 0xff; | ||
| players[i].color[2] = (1 << (i / 2)) & 4 ? 0 : 0xff; | ||
|
|
@@ -344,7 +355,7 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) | |
| *appstate = as; | ||
| } | ||
|
|
||
| if (!SDL_Init(SDL_INIT_VIDEO)) { | ||
| if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) { | ||
| return SDL_APP_FAILURE; | ||
| } | ||
| if (!SDL_CreateWindowAndRenderer("examples/demo/woodeneye-008", 640, 480, 0, &as->window, &as->renderer)) { | ||
|
|
@@ -386,6 +397,25 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) | |
| } | ||
| } | ||
| break; | ||
| case SDL_EVENT_GAMEPAD_REMOVED: | ||
| for (i = 0; i < player_count; i++) { | ||
| if (players[i].gamepad && (SDL_GetGamepadID(players[i].gamepad) == event->gdevice.which)) { | ||
| SDL_CloseGamepad(players[i].gamepad); | ||
| players[i].gamepad = NULL; | ||
| } | ||
| } | ||
| break; | ||
| case SDL_EVENT_GAMEPAD_ADDED: | ||
| for (i = 0; i < player_count; i++) { | ||
| if (players[i].gamepad == NULL) { | ||
| players[i].gamepad = SDL_OpenGamepad(event->gdevice.which); | ||
| if (!players[i].gamepad) | ||
| SDL_Log("Failed to open gamepad ID %u: %s", (unsigned int) event->gdevice.which, SDL_GetError()); | ||
| else | ||
| as->player_count = SDL_max(as->player_count, i + 1); | ||
| } | ||
| } | ||
| break; | ||
| case SDL_EVENT_MOUSE_MOTION: { | ||
| SDL_MouseID id = event->motion.which; | ||
| int index = whoseMouse(id, players, player_count); | ||
|
|
@@ -446,6 +476,44 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) | |
| } | ||
| break; | ||
| } | ||
| case SDL_EVENT_GAMEPAD_AXIS_MOTION: { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I understand correctly, this event is fired only when the axis value changes. This implementation results in the camera only rotation when you wiggle the thumbstick, instead of the thumbstick controlling the velocity of camera rotation. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's correct. If you want to have control based on state you should just query the axis value instead of responding to an axis change event. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also I’m pretty sure the convention is to use the right stick for camera controls rather than left. It’d be a little bit awkward having both movement and aim on the left side of the controller. |
||
| SDL_JoystickID id = event->gaxis.which; | ||
| int index = whoseGamepad(id, players, player_count); | ||
| if (index >= 0) { | ||
| if (event->gaxis.axis == SDL_GAMEPAD_AXIS_LEFTX) | ||
| players[index].yaw -= ((int)event->gaxis.value) * 0x00000800; | ||
| if (event->gaxis.axis == SDL_GAMEPAD_AXIS_LEFTY) | ||
| players[index].pitch = SDL_max(-0x40000000, SDL_min(0x40000000, players[index].pitch - ((int)event->gaxis.value) * 0x00000800)); | ||
| } | ||
| break; | ||
| } | ||
| case SDL_EVENT_GAMEPAD_BUTTON_DOWN: { | ||
| Uint8 button = event->gbutton.button; | ||
| SDL_JoystickID id = event->gbutton.which; | ||
| int index = whoseGamepad(id, players, player_count); | ||
| if (index >= 0) { | ||
| if (button == SDL_GAMEPAD_BUTTON_DPAD_UP) players[index].wasd |= 1; | ||
| if (button == SDL_GAMEPAD_BUTTON_DPAD_LEFT) players[index].wasd |= 2; | ||
| if (button == SDL_GAMEPAD_BUTTON_DPAD_DOWN) players[index].wasd |= 4; | ||
| if (button == SDL_GAMEPAD_BUTTON_DPAD_RIGHT) players[index].wasd |= 8; | ||
| if (button == SDL_GAMEPAD_BUTTON_SOUTH) players[index].wasd |= 16; | ||
| if (button == SDL_GAMEPAD_BUTTON_EAST) shoot(index, players, player_count); | ||
| } | ||
| break; | ||
| } | ||
| case SDL_EVENT_GAMEPAD_BUTTON_UP: { | ||
| Uint8 button = event->gbutton.button; | ||
| SDL_JoystickID id = event->gbutton.which; | ||
| int index = whoseGamepad(id, players, player_count); | ||
| if (index >= 0) { | ||
| if (button == SDL_GAMEPAD_BUTTON_DPAD_UP) players[index].wasd &= 30; | ||
| if (button == SDL_GAMEPAD_BUTTON_DPAD_LEFT) players[index].wasd &= 29; | ||
| if (button == SDL_GAMEPAD_BUTTON_DPAD_DOWN) players[index].wasd &= 27; | ||
| if (button == SDL_GAMEPAD_BUTTON_DPAD_RIGHT) players[index].wasd &= 23; | ||
| if (button == SDL_GAMEPAD_BUTTON_SOUTH) players[index].wasd &= 15; | ||
| } | ||
| break; | ||
| } | ||
| } | ||
| return SDL_APP_CONTINUE; | ||
| } | ||
|
|
@@ -476,5 +544,13 @@ SDL_AppResult SDL_AppIterate(void *appstate) | |
|
|
||
| void SDL_AppQuit(void *appstate, SDL_AppResult result) | ||
| { | ||
| AppState *as = appstate; | ||
| Player *players = as->players; | ||
| int player_count = as->player_count; | ||
| int i; | ||
| for (i = 0; i < player_count; i++) { | ||
| if (players[i].gamepad) | ||
| SDL_CloseGamepad(players[i].gamepad); | ||
| } | ||
| SDL_free(appstate); // just free the memory, SDL will clean up the window/renderer for us. | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the comment is about not always using curly braces, and indentation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, for example, here the code would be: