pass LDFLAGS to compiler at link time
[tennix.git] / input.c
blobef2c1757821e64a717df3b279d241b13ae9b8bb9
2 /**
4 * Tennix! SDL Port
5 * Copyright (C) 2003, 2007, 2008, 2009 Thomas Perl <thp@thpinfo.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20 * MA 02110-1301, USA.
22 **/
24 #include <string.h>
26 #include "tennix.h"
27 #include "graphics.h"
28 #include "game.h"
29 #include "input.h"
30 #include "util.h"
31 #include "archive.hh"
33 static InputDevice devices[MAX_INPUT_DEVICES];
34 static int devices_count;
36 #ifdef TENNIX_PYTHON
37 #include "tennixpy.h"
38 #endif
40 void init_input(TennixArchive& tnxar)
42 int n, x;
44 SDL_JoystickEventState(SDL_ENABLE);
46 #ifndef MAEMO
47 /* keyboard presets */
48 devices[devices_count].type = INPUT_TYPE_KEYBOARD;
49 devices[devices_count].up_key = 'w';
50 devices[devices_count].down_key = 's';
51 devices[devices_count].input_keys[INPUT_KEY_HIT]= 'd';
52 devices[devices_count].input_keys[INPUT_KEY_TOPSPIN] = 'e';
53 devices[devices_count].input_keys[INPUT_KEY_SMASH] = 'f';
54 devices[devices_count].icon = GR_INPUT_KEYBOARD_WS;
55 devices[devices_count].exclusive_to_player = 1;
56 strcpy(devices[devices_count].name, "Keyboard (WS/DEF)");
57 devices_count++;
59 /* keyboard presets */
60 devices[devices_count].type = INPUT_TYPE_KEYBOARD;
61 devices[devices_count].up_key = 'o';
62 devices[devices_count].down_key = 'l';
63 devices[devices_count].input_keys[INPUT_KEY_HIT]= 'k';
64 devices[devices_count].input_keys[INPUT_KEY_TOPSPIN] = 'i';
65 devices[devices_count].input_keys[INPUT_KEY_SMASH] = 'j';
66 devices[devices_count].icon = GR_INPUT_KEYBOARD_OL;
67 devices[devices_count].exclusive_to_player = 2;
68 strcpy(devices[devices_count].name, "Keyboard (OL/KIJ)");
69 devices_count++;
70 #endif
72 /* keyboard presets */
73 devices[devices_count].type = INPUT_TYPE_KEYBOARD;
74 devices[devices_count].up_key = SDLK_UP;
75 devices[devices_count].down_key = SDLK_DOWN;
76 devices[devices_count].input_keys[INPUT_KEY_HIT]= SDLK_SPACE;
77 devices[devices_count].input_keys[INPUT_KEY_TOPSPIN] = SDLK_LCTRL;
78 devices[devices_count].input_keys[INPUT_KEY_SMASH] = SDLK_LALT;
79 #ifdef MAEMO
80 devices[devices_count].icon = GR_INPUT_MAEMO_DPAD;
81 strcpy(devices[devices_count].name, "D-Pad");
82 devices[devices_count].input_keys[INPUT_KEY_HIT]= SDLK_RETURN;
83 /* FIXME: No TOPSPIN and SMASH keys on Maemo yet with d-pad */
84 #else
85 devices[devices_count].icon = GR_INPUT_KEYBOARD_ARROWS;
86 strcpy(devices[devices_count].name, "Keyboard (arrows)");
87 #endif
88 devices_count++;
90 /* mouse */
91 devices[devices_count].type = INPUT_TYPE_MOUSE;
92 devices[devices_count].input_keys[INPUT_KEY_HIT]= SDL_BUTTON(1);
93 devices[devices_count].input_keys[INPUT_KEY_TOPSPIN] = SDL_BUTTON(2);
94 devices[devices_count].input_keys[INPUT_KEY_SMASH] = SDL_BUTTON(3);
95 #ifdef MAEMO
96 devices[devices_count].icon = GR_INPUT_TOUCHSCREEN;
97 strcpy(devices[devices_count].name, "Touchscreen");
98 #else
99 devices[devices_count].icon = GR_INPUT_MOUSE;
100 strcpy(devices[devices_count].name, "Mouse");
101 #endif
102 devices_count++;
104 /* network peer */
105 devices[devices_count].type = INPUT_TYPE_NETWORK;
106 devices[devices_count].icon = GR_INPUT_AI; /* FIXME - network icon! */
107 strcpy(devices[devices_count].name, "Network player");
108 devices_count++;
110 /* joysticks */
111 n = SDL_NumJoysticks();
112 for (x=0; x<n && devices_count<MAX_INPUT_DEVICES; x++) {
113 strcpy(devices[devices_count].name, SDL_JoystickName(x));
114 devices[devices_count].type = INPUT_TYPE_JOYSTICK;
115 devices[devices_count].joystick = SDL_JoystickOpen(x);
116 devices[devices_count].x_axis = 0;
117 devices[devices_count].y_axis = 0;
118 devices[devices_count].input_keys[INPUT_KEY_HIT]= 0;
119 devices[devices_count].input_keys[INPUT_KEY_TOPSPIN] = 1;
120 devices[devices_count].input_keys[INPUT_KEY_SMASH] = 2;
121 devices[devices_count].icon = GR_INPUT_GAMEPAD;
122 devices_count++;
125 #ifdef TENNIX_PYTHON
126 /* This will init Python and load all available bots */
127 tennixpy_init(tnxar);
128 #endif
132 void uninit_input()
134 int i;
135 SDL_JoystickEventState(SDL_IGNORE);
137 for (i=0; i<devices_count; i++) {
138 if (devices[i].type == INPUT_TYPE_JOYSTICK) {
139 SDL_JoystickClose(devices[i].joystick);
140 #ifdef TENNIX_PYTHON
141 } else if (devices[i].type == INPUT_TYPE_AI_PYTHON) {
142 tennixpy_unregister_bot(devices[i].py_bot_class);
143 #endif
147 #ifdef TENNIX_PYTHON
148 tennixpy_uninit();
149 #endif
151 devices_count = 0;
154 Uint8
155 input_pack_axis(float v)
157 static const float min = -1.2;
158 static const float max = 1.2;
159 assert(v >= min && v < max);
160 return (Uint8)((1U<<7) * (v-min) / (max-min));
163 float
164 input_unpack_axis(Uint8 v)
166 static const float min = -1.2;
167 static const float max = 1.2;
168 assert(v < (1U<<7));
169 return v * (max-min) / (1U<<7) + min;
173 InputDevice* find_input_devices(unsigned int* count)
175 *count = devices_count;
176 return devices;
179 void input_device_join_game(InputDevice* device, void* gamestate, int player_id)
181 if (device == NULL) {
182 /* player is a c-style bot with no device attached */
183 return;
185 fprintf(stderr, "Input Device %s joins the game\n", device->name);
186 #ifdef TENNIX_PYTHON
187 if (device->type == INPUT_TYPE_AI_PYTHON) {
188 device->py_bot = tennixpy_create_bot(device->py_bot_class, (GameState*)gamestate, player_id);
190 #endif
193 void input_device_part_game(InputDevice* device)
195 if (device == NULL) {
196 /* player is a c-style bot with no device attached */
197 return;
199 #ifdef TENNIX_PYTHON
200 if (device->type == INPUT_TYPE_AI_PYTHON) {
201 tennixpy_destroy_bot(device->py_bot);
202 device->py_bot = NULL;
204 #endif
205 fprintf(stderr, "Input Device %s leaves the game\n", device->name);
208 const char* input_device_get_name(InputDevice* d)
210 return d->name;
213 float input_device_get_axis(InputDevice* d, unsigned const char axis) {
214 Uint8 *keystate;
215 Uint8 mb;
216 Uint8 net_value;
217 float result = 0.0;
219 SDL_PumpEvents();
221 if (d->type == INPUT_TYPE_KEYBOARD) {
222 keystate = SDL_GetKeyState(NULL);
223 if (axis == INPUT_AXIS_X) {
224 result = 1.0*keystate[d->right_key] + -1.0*keystate[d->left_key];
225 } else {
226 result = 1.0*keystate[d->down_key] + -1.0*keystate[d->up_key];
228 } else if (d->type == INPUT_TYPE_JOYSTICK) {
229 if (axis == INPUT_AXIS_X) {
230 result = JOYSTICK_PERCENTIZE(SDL_JoystickGetAxis(d->joystick, d->x_axis*2));
231 } else {
232 result = JOYSTICK_PERCENTIZE(SDL_JoystickGetAxis(d->joystick, 1+d->y_axis*2));
234 } else if (d->type == INPUT_TYPE_MOUSE) {
235 mb = SDL_GetMouseState(&d->mx, &d->my);
236 if (axis == INPUT_AXIS_X) {
237 /* Not x-movement yet (PLAYER_MOVE_X is not defined!) */
238 /*if (fabsf(d->mx - d->player_x) > PLAYER_MOVE_X) {
239 if (d->mx > d->player_x) {
240 return 1.0;
241 } else if (d->mx < d->player_x) {
242 return -1.0;
245 } else {
246 if (fabsf(d->my - d->player_y) > PLAYER_MOVE_Y) {
247 if (d->my > d->player_y) {
248 result = 1.0;
249 } else if (d->my < d->player_y) {
250 result = -1.0;
254 #ifdef TENNIX_PYTHON
255 } else if (d->type == INPUT_TYPE_AI_PYTHON) {
256 result = tennixpy_bot_get_axis(d->py_bot, axis);
257 #endif
258 } else if (d->type == INPUT_TYPE_NETWORK) {
259 if (axis == INPUT_AXIS_X) {
260 result = input_unpack_axis(d->net.x);
261 } else if (axis == INPUT_AXIS_Y) {
262 result = input_unpack_axis(d->net.y);
264 } else {
265 assert(0/*unimplemented*/);
268 net_value = input_pack_axis(result);
269 if (axis == INPUT_AXIS_X) {
270 d->net.x = net_value;
271 } else if (axis == INPUT_AXIS_Y) {
272 d->net.y = net_value;
275 return result;
278 char input_device_get_key(InputDevice* d, unsigned const char key) {
279 Uint8 mb;
280 char result = 0;
281 SDL_PumpEvents();
283 if (d->type == INPUT_TYPE_KEYBOARD) {
284 result = SDL_GetKeyState(NULL)[d->input_keys[key]];
285 } else if (d->type == INPUT_TYPE_JOYSTICK) {
286 result = SDL_JoystickGetButton(d->joystick, d->input_keys[key]);
287 } else if (d->type == INPUT_TYPE_MOUSE) {
288 mb = SDL_GetMouseState(NULL, NULL);
289 result = (mb & d->input_keys[key]) != 0;
290 #ifdef TENNIX_PYTHON
291 } else if (d->type == INPUT_TYPE_AI_PYTHON) {
292 result = tennixpy_bot_get_key(d->py_bot, key);
293 #endif
294 } else if (d->type == INPUT_TYPE_NETWORK) {
295 result = (d->net.keys & (1<<key));
296 } else {
297 assert(0/*unimplemented*/);
300 /* Update the input device's NetworkInputData struct */
301 if(result) {
302 d->net.keys |= (1<<key);
303 } else {
304 d->net.keys &= ~(1<<key);
307 return result;
311 #ifdef TENNIX_PYTHON
313 void input_add_python_bot(PyObject* bot_class)
315 if (devices_count < MAX_INPUT_DEVICES) {
316 devices[devices_count].type = INPUT_TYPE_AI_PYTHON;
317 devices[devices_count].icon = GR_INPUT_AI;
318 devices[devices_count].py_bot_class = bot_class;
319 tennixpy_get_bot_name(bot_class, devices[devices_count].name, INPUT_DEVICE_NAME_MAX);
320 fprintf(stderr, " %s", devices[devices_count].name);
321 devices_count++;
322 } else {
323 fprintf(stderr, "Warning: Cannot add any more Python bots.\n");
324 /* We carry a ref of bot_class, so give it up here */
325 tennixpy_unregister_bot(bot_class);
329 #endif