Skip to content

Commit 7f2a5a7

Browse files
committed
Add preliminary gamepad support
1 parent a0833a9 commit 7f2a5a7

File tree

7 files changed

+574
-287
lines changed

7 files changed

+574
-287
lines changed

Makefile.in

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
# along with this program. If not, see <http://www.gnu.org/licenses/>.
1616

1717
CFLAGS = @CFLAGS@
18-
OBJECTS = src/zatackax.o src/sound.o src/error.o src/ai.o src/broadcast.o
18+
OBJECTS = src/zatackax.o src/sound.o src/error.o src/ai.o src/broadcast.o src/input.o
1919

2020
zatackax : $(OBJECTS)
2121
@CC@ $(CFLAGS) $(shell pkg-config sdl --cflags) $^ -o $@ @LDFLAGS@ @LIBS@
@@ -32,7 +32,7 @@ verbose : devel
3232
silent : CFLAGS += -DSILENT
3333
silent : devel
3434

35-
src/zatackax.o : src/zatackax.c src/zatackax.h src/sound.h src/error.h src/ai.h src/broadcast.h src/common.h src/player.h src/weapon.h
35+
src/zatackax.o : src/zatackax.c src/zatackax.h src/sound.h src/error.h src/ai.h src/broadcast.h src/common.h src/player.h src/weapon.h src/input.h
3636
@CC@ $(CFLAGS) -c -o $@ src/zatackax.c
3737

3838
src/error.o : src/error.c src/error.h src/common.h
@@ -47,6 +47,9 @@ src/ai.o : src/ai.c src/ai.h src/common.h
4747
src/broadcast.o : src/broadcast.c src/broadcast.h src/player.h src/common.h
4848
@CC@ $(CFLAGS) -c -o $@ src/broadcast.c
4949

50+
src/input.o: src/input.c src/input.h src/common.h
51+
@CC@ $(CFLAGS) -c -o $@ src/input.c
52+
5053
.PHONY: clean
5154
clean :
5255
rm -f zatackax .zatackax $(OBJECTS)

NEWS.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.3.0 - ??.??.??
2+
* General:
3+
* Add experimental gamepad support.
4+
15
## 0.2.0 - 08.07.17
26
* General:
37
* A new weapon has been added: Chili run.

src/input.c

Lines changed: 354 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,354 @@
1+
/* input -- keyboard, mouse and joystick/gamepad handling.
2+
* Copyright (C) 2010-2017 The Zatacka X development team
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
#include "input.h"
19+
20+
const int BUTTON_NAME_MAX_LEN = 10;
21+
22+
/*
23+
* The joystick button that is treated as an enter button in the
24+
* menus.
25+
*/
26+
const Uint8 JOY_ENTER_BUTTON = 1;
27+
28+
// 322 is the number of possible SDL keys (see SDL_keysym.h).
29+
bool keyDown[322];
30+
31+
/*
32+
* A separate map is kept for each possible joystick (0-7). See the
33+
* `button` type below for details about how buttons and axes are
34+
* represented.
35+
*/
36+
bool joyButtonDown[MAX_PLAYERS][128];
37+
38+
unsigned int numJoys = 0;
39+
40+
SDL_Joystick *joys[MAX_PLAYERS];
41+
42+
/**
43+
* Open all connected joysticks for interaction.
44+
*/
45+
void openJoysticks(void)
46+
{
47+
numJoys = SDL_NumJoysticks();
48+
49+
for (unsigned int i = 0; i < numJoys; i++) {
50+
joys[i] = SDL_JoystickOpen(i);
51+
}
52+
}
53+
54+
/**
55+
* Close all open joysticks.
56+
*/
57+
void closeJoysticks(void)
58+
{
59+
for (unsigned int i = 0; i < numJoys; i++) {
60+
SDL_JoystickClose(joys[i]);
61+
}
62+
}
63+
64+
/**
65+
* Return true if button `b` belongs to a joystick.
66+
*/
67+
bool isJoyButton(button b)
68+
{
69+
return ((b >> 9) > 0) && ((b & 0xf0) == 0);
70+
}
71+
72+
/**
73+
* Return true if button `b` represents a joystick axis.
74+
*/
75+
bool isJoyAxis(button b)
76+
{
77+
return ((b >> 9) > 0) && ((b & 0xf0) > 0);
78+
}
79+
80+
/**
81+
* Return the joystick device index for button `b`, or -1 if none.
82+
*/
83+
int joyIndex(button b)
84+
{
85+
if (isJoyButton(b) || isJoyAxis(b)) {
86+
return (b >> 9) - 1;
87+
}
88+
89+
return -1;
90+
}
91+
92+
/**
93+
* Return the button number for joystick button `b`.
94+
*/
95+
int joyButtonNumber(button b)
96+
{
97+
return b & 0x7f;
98+
}
99+
100+
/**
101+
* Return the axis direction for joystick button `b`.
102+
*/
103+
enum joyDir joyAxisDir(button b)
104+
{
105+
return (b & 0x70) >> 4;
106+
}
107+
108+
/**
109+
* Return the axis number corresponding to axis event `e`.
110+
*/
111+
int axisNumber(SDL_JoyAxisEvent e)
112+
{
113+
if (e.axis) {
114+
return e.value < 0 ? JOY_DIR_UP : JOY_DIR_DOWN;
115+
}
116+
117+
return e.value < 0 ? JOY_DIR_LEFT : JOY_DIR_RIGHT;
118+
}
119+
120+
/**
121+
* Return true if one of the enter buttons are currently down.
122+
*/
123+
bool enterButtonDown(void)
124+
{
125+
if (keyDown[SDLK_SPACE] || keyDown[SDLK_RETURN]) {
126+
return true;
127+
}
128+
129+
for (unsigned int i = 0; i < numJoys; i++) {
130+
if (joyButtonDown[i][JOY_ENTER_BUTTON]) {
131+
return true;
132+
}
133+
}
134+
135+
return false;
136+
}
137+
138+
/**
139+
* Mark all enter buttons as not down.
140+
*/
141+
void clearEnterButtons(void)
142+
{
143+
keyDown[SDLK_RETURN] = false;
144+
keyDown[SDLK_SPACE] = false;
145+
146+
for (unsigned int i = 0; i < numJoys; i++) {
147+
joyButtonDown[i][JOY_ENTER_BUTTON] = false;
148+
}
149+
}
150+
151+
/**
152+
* Return true if button `b` is currently down.
153+
*/
154+
bool buttonDown(button b)
155+
{
156+
if (isJoyButton(b) || isJoyAxis(b)) {
157+
return joyButtonDown[joyIndex(b)][joyButtonNumber(b)];
158+
}
159+
160+
return keyDown[b];
161+
}
162+
163+
/**
164+
* Mark button `b` as not down anymore.
165+
*/
166+
void clearButton(button b)
167+
{
168+
if (isJoyButton(b) || isJoyAxis(b)) {
169+
joyButtonDown[joyIndex(b)][joyButtonNumber(b)] = false;
170+
}
171+
else {
172+
keyDown[b] = false;
173+
}
174+
}
175+
176+
/**
177+
* Return true if one of the generic left buttons are down, and reset
178+
* it in such case.
179+
*/
180+
bool menuButtonQuery(enum keySymbol ks)
181+
{
182+
SDLKey lkeys[4][3] =
183+
{{SDLK_UP, SDLK_k, SDLK_p},
184+
{SDLK_RIGHT, SDLK_l, SDLK_f},
185+
{SDLK_DOWN, SDLK_j, SDLK_n},
186+
{SDLK_LEFT, SDLK_h, SDLK_b}};
187+
188+
for (int i = 0; i < 3; i++) {
189+
if (keyDown[lkeys[ks][i]]) {
190+
keyDown[lkeys[ks][i]] = false;
191+
return true;
192+
}
193+
}
194+
195+
for (unsigned int i = 0; i < numJoys; i++) {
196+
if (ks == KEY_UP && joyButtonDown[i][JOY_DIR_UP << 4]) {
197+
joyButtonDown[i][JOY_DIR_UP << 4] = false;
198+
return true;
199+
}
200+
if (ks == KEY_RIGHT && joyButtonDown[i][JOY_DIR_RIGHT << 4]) {
201+
joyButtonDown[i][JOY_DIR_RIGHT << 4] = false;
202+
return true;
203+
}
204+
if (ks == KEY_DOWN && joyButtonDown[i][JOY_DIR_DOWN << 4]) {
205+
joyButtonDown[i][JOY_DIR_DOWN << 4] = false;
206+
return true;
207+
}
208+
if (ks == KEY_LEFT && joyButtonDown[i][JOY_DIR_LEFT << 4]) {
209+
joyButtonDown[i][JOY_DIR_LEFT << 4] = false;
210+
return true;
211+
}
212+
}
213+
214+
return false;
215+
}
216+
217+
/**
218+
* Return an appropriate name for button `b`. Return '\0' if the
219+
* button could not be named.
220+
*/
221+
char *buttonName(button b)
222+
{
223+
char *keyname = calloc(BUTTON_NAME_MAX_LEN, sizeof(char));
224+
225+
if (isJoyButton(b)) {
226+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "joy-%d",
227+
joyButtonNumber(b) + 1);
228+
}
229+
else if (isJoyAxis(b)) {
230+
int axisNumber = joyAxisDir(b);
231+
char *axisName;
232+
233+
switch (axisNumber) {
234+
case JOY_DIR_UP:
235+
axisName = "up"; break;
236+
case JOY_DIR_RIGHT:
237+
axisName = "right"; break;
238+
case JOY_DIR_DOWN:
239+
axisName = "down"; break;
240+
case JOY_DIR_LEFT:
241+
axisName = "left"; break;
242+
}
243+
244+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "joy-%s", axisName);
245+
}
246+
else if ((b >= SDLK_a && b <= SDLK_z)
247+
|| (b >= SDLK_0 && b <= SDLK_9)) {
248+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "%c", b);
249+
}
250+
else if (b >= SDLK_F1 && b <= SDLK_F15) {
251+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "F%d", b - SDLK_F1 + 1);
252+
}
253+
else {
254+
switch (b) {
255+
case SDLK_UNKNOWN:
256+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "none"); break;
257+
case SDLK_LEFT:
258+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "left"); break;
259+
case SDLK_RIGHT:
260+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "right"); break;
261+
case SDLK_UP:
262+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "up"); break;
263+
case SDLK_DOWN:
264+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "down"); break;
265+
case SDLK_PAUSE:
266+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "pause"); break;
267+
case SDLK_DELETE:
268+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "del"); break;
269+
case SDLK_INSERT:
270+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "ins"); break;
271+
case SDLK_HOME:
272+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "home"); break;
273+
case SDLK_END:
274+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "end"); break;
275+
case SDLK_MENU:
276+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "menu"); break;
277+
case SDLK_PRINT:
278+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "prt-sc"); break;
279+
case SDLK_PAGEUP:
280+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "pg up"); break;
281+
case SDLK_PAGEDOWN:
282+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "pg dn"); break;
283+
case SDLK_RSHIFT:
284+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "r-shift"); break;
285+
case SDLK_LSHIFT:
286+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "l-shift"); break;
287+
case SDLK_RCTRL:
288+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "r-ctrl"); break;
289+
case SDLK_LCTRL:
290+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "l-ctrl"); break;
291+
case SDLK_RALT:
292+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "r-alt"); break;
293+
case SDLK_LALT:
294+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "l-alt"); break;
295+
case SDLK_MODE:
296+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "alt gr"); break;
297+
case SDLK_RSUPER:
298+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "r-super"); break;
299+
case SDLK_LSUPER:
300+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "l-super"); break;
301+
case SDLK_TAB:
302+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "tab"); break;
303+
case SDLK_PERIOD:
304+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "."); break;
305+
case SDLK_COMMA:
306+
snprintf(keyname, BUTTON_NAME_MAX_LEN, ","); break;
307+
case SDLK_SEMICOLON:
308+
snprintf(keyname, BUTTON_NAME_MAX_LEN, ";"); break;
309+
case SDLK_MINUS:
310+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "-"); break;
311+
case SDLK_QUOTE:
312+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "'"); break;
313+
case SDLK_BACKQUOTE:
314+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "`"); break;
315+
case SDLK_PLUS:
316+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "+"); break;
317+
case SDLK_EQUALS:
318+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "="); break;
319+
case SDLK_COMPOSE:
320+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "^"); break;
321+
case SDLK_SLASH:
322+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "/"); break;
323+
case SDLK_BACKSLASH:
324+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "\\"); break;
325+
case SDLK_LESS:
326+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "<"); break;
327+
case SDLK_LEFTBRACKET:
328+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "["); break;
329+
case SDLK_RIGHTBRACKET:
330+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "]"); break;
331+
case SDLK_BACKSPACE:
332+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "b-space"); break;
333+
case SDLK_RETURN:
334+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "enter"); break;
335+
case SDLK_SPACE:
336+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "space"); break;
337+
case SDL_BUTTON_LEFT:
338+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "l-mouse"); break;
339+
case SDL_BUTTON_MIDDLE:
340+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "m-mouse"); break;
341+
case SDL_BUTTON_RIGHT:
342+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "r-mouse"); break;
343+
case SDLK_WORLD_70:
344+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "æ"); break;
345+
case SDLK_WORLD_88:
346+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "ø"); break;
347+
case SDLK_WORLD_69:
348+
snprintf(keyname, BUTTON_NAME_MAX_LEN, "å"); break;
349+
default:
350+
break;
351+
}
352+
}
353+
return keyname;
354+
}

0 commit comments

Comments
 (0)