Version 1.2.0 with new build/configure system
[tennix.git] / src / input.cc
blob3eb9d022b37a25d97afc5d3931641599f61382cf
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.h"
34 static InputDevice devices[MAX_INPUT_DEVICES];
35 static int devices_count;
37 #ifdef HAVE_PYTHON
38 #include "tennixpy.h"
39 #endif
41 void init_input(TennixArchive& tnxar)
43 int n, x;
45 SDL_JoystickEventState(SDL_ENABLE);
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++;
71 /* keyboard presets */
72 devices[devices_count].type = INPUT_TYPE_KEYBOARD;
73 devices[devices_count].up_key = SDLK_UP;
74 devices[devices_count].down_key = SDLK_DOWN;
75 devices[devices_count].input_keys[INPUT_KEY_HIT]= SDLK_SPACE;
76 devices[devices_count].input_keys[INPUT_KEY_TOPSPIN] = SDLK_LCTRL;
77 devices[devices_count].input_keys[INPUT_KEY_SMASH] = SDLK_LALT;
78 devices[devices_count].icon = GR_INPUT_KEYBOARD_ARROWS;
79 strcpy(devices[devices_count].name, "Keyboard (arrows)");
80 devices_count++;
82 /* mouse */
83 devices[devices_count].type = INPUT_TYPE_MOUSE;
84 devices[devices_count].input_keys[INPUT_KEY_HIT]= SDL_BUTTON(1);
85 devices[devices_count].input_keys[INPUT_KEY_TOPSPIN] = SDL_BUTTON(2);
86 devices[devices_count].input_keys[INPUT_KEY_SMASH] = SDL_BUTTON(3);
87 devices[devices_count].icon = GR_INPUT_MOUSE;
88 strcpy(devices[devices_count].name, "Mouse");
89 devices_count++;
91 /* network peer */
92 devices[devices_count].type = INPUT_TYPE_NETWORK;
93 devices[devices_count].icon = GR_INPUT_AI; /* FIXME - network icon! */
94 strcpy(devices[devices_count].name, "Network player");
95 devices_count++;
97 /* joysticks */
98 n = SDL_NumJoysticks();
99 for (x=0; x<n && devices_count<MAX_INPUT_DEVICES; x++) {
100 strcpy(devices[devices_count].name, SDL_JoystickName(x));
101 devices[devices_count].type = INPUT_TYPE_JOYSTICK;
102 devices[devices_count].joystick = SDL_JoystickOpen(x);
103 devices[devices_count].x_axis = 0;
104 devices[devices_count].y_axis = 0;
105 devices[devices_count].input_keys[INPUT_KEY_HIT]= 0;
106 devices[devices_count].input_keys[INPUT_KEY_TOPSPIN] = 1;
107 devices[devices_count].input_keys[INPUT_KEY_SMASH] = 2;
108 devices[devices_count].icon = GR_INPUT_GAMEPAD;
109 devices_count++;
112 #ifdef HAVE_PYTHON
113 /* This will init Python and load all available bots */
114 tennixpy_init(tnxar);
115 #endif
119 void uninit_input()
121 int i;
122 SDL_JoystickEventState(SDL_IGNORE);
124 for (i=0; i<devices_count; i++) {
125 if (devices[i].type == INPUT_TYPE_JOYSTICK) {
126 SDL_JoystickClose(devices[i].joystick);
127 #ifdef HAVE_PYTHON
128 } else if (devices[i].type == INPUT_TYPE_AI_PYTHON) {
129 tennixpy_unregister_bot(&(devices[i]));
130 #endif
134 #ifdef HAVE_PYTHON
135 tennixpy_uninit();
136 #endif
138 devices_count = 0;
141 Uint8
142 input_pack_axis(float v)
144 static const float min = -1.2;
145 static const float max = 1.2;
146 tnx_assert(v >= min && v < max);
147 return (Uint8)((1U<<7) * (v-min) / (max-min));
150 float
151 input_unpack_axis(Uint8 v)
153 static const float min = -1.2;
154 static const float max = 1.2;
155 tnx_assert(v < (1U<<7));
156 return v * (max-min) / (1U<<7) + min;
160 InputDevice* find_input_devices(unsigned int* count)
162 *count = devices_count;
163 return devices;
166 void input_device_join_game(InputDevice* device, void* gamestate, int player_id)
168 if (device == NULL) {
169 /* player is a c-style bot with no device attached */
170 return;
172 fprintf(stderr, "Input Device %s joins the game\n", device->name);
173 #ifdef HAVE_PYTHON
174 if (device->type == INPUT_TYPE_AI_PYTHON) {
175 tennixpy_create_bot(device, (GameState*)gamestate, player_id);
177 #endif
180 void input_device_part_game(InputDevice* device)
182 if (device == NULL) {
183 /* player is a c-style bot with no device attached */
184 return;
186 #ifdef HAVE_PYTHON
187 if (device->type == INPUT_TYPE_AI_PYTHON) {
188 tennixpy_destroy_bot(device);
190 #endif
191 fprintf(stderr, "Input Device %s leaves the game\n", device->name);
194 const char* input_device_get_name(InputDevice* d)
196 return d->name;
199 float input_device_get_axis(InputDevice* d, unsigned const char axis) {
200 Uint8 *keystate;
201 //Uint8 mb;
202 Uint8 net_value;
203 float result = 0.0;
205 SDL_PumpEvents();
207 if (d->type == INPUT_TYPE_KEYBOARD) {
208 keystate = SDL_GetKeyState(NULL);
209 if (axis == INPUT_AXIS_X) {
210 result = 1.0*keystate[d->right_key] + -1.0*keystate[d->left_key];
211 } else {
212 result = 1.0*keystate[d->down_key] + -1.0*keystate[d->up_key];
214 } else if (d->type == INPUT_TYPE_JOYSTICK) {
215 if (axis == INPUT_AXIS_X) {
216 result = JOYSTICK_PERCENTIZE(SDL_JoystickGetAxis(d->joystick, d->x_axis*2));
217 } else {
218 result = JOYSTICK_PERCENTIZE(SDL_JoystickGetAxis(d->joystick, 1+d->y_axis*2));
220 } else if (d->type == INPUT_TYPE_MOUSE) {
221 //mb = SDL_GetMouseState(&d->mx, &d->my);
222 if (axis == INPUT_AXIS_X) {
223 /* Not x-movement yet (PLAYER_MOVE_X is not defined!) */
224 /*if (fabsf(d->mx - d->player_x) > PLAYER_MOVE_X) {
225 if (d->mx > d->player_x) {
226 return 1.0;
227 } else if (d->mx < d->player_x) {
228 return -1.0;
231 } else {
232 if (fabsf(d->my - d->player_y) > PLAYER_MOVE_Y) {
233 if (d->my > d->player_y) {
234 result = 1.0;
235 } else if (d->my < d->player_y) {
236 result = -1.0;
240 #ifdef HAVE_PYTHON
241 } else if (d->type == INPUT_TYPE_AI_PYTHON) {
242 result = tennixpy_bot_get_axis(d, axis);
243 #endif
244 } else if (d->type == INPUT_TYPE_NETWORK) {
245 if (axis == INPUT_AXIS_X) {
246 result = input_unpack_axis(d->net.x);
247 } else if (axis == INPUT_AXIS_Y) {
248 result = input_unpack_axis(d->net.y);
250 } else {
251 tnx_assert(0/*unimplemented*/);
254 net_value = input_pack_axis(result);
255 if (axis == INPUT_AXIS_X) {
256 d->net.x = net_value;
257 } else if (axis == INPUT_AXIS_Y) {
258 d->net.y = net_value;
261 return result;
264 char input_device_get_key(InputDevice* d, unsigned const char key) {
265 Uint8 mb;
266 char result = 0;
267 SDL_PumpEvents();
269 if (d->type == INPUT_TYPE_KEYBOARD) {
270 result = SDL_GetKeyState(NULL)[d->input_keys[key]];
271 } else if (d->type == INPUT_TYPE_JOYSTICK) {
272 result = SDL_JoystickGetButton(d->joystick, d->input_keys[key]);
273 } else if (d->type == INPUT_TYPE_MOUSE) {
274 mb = SDL_GetMouseState(NULL, NULL);
275 result = (mb & d->input_keys[key]) != 0;
276 #ifdef HAVE_PYTHON
277 } else if (d->type == INPUT_TYPE_AI_PYTHON) {
278 result = tennixpy_bot_get_key(d, key);
279 #endif
280 } else if (d->type == INPUT_TYPE_NETWORK) {
281 result = (d->net.keys & (1<<key));
282 } else {
283 tnx_assert(0/*unimplemented*/);
286 /* Update the input device's NetworkInputData struct */
287 if(result) {
288 d->net.keys |= (1<<key);
289 } else {
290 d->net.keys &= ~(1<<key);
293 return result;
297 InputDevice *
298 input_add_device()
300 tnx_assert(devices_count < MAX_INPUT_DEVICES);
301 return &(devices[devices_count++]);