Subversion Repositories battle

[/] [trunk/] [Battle/] [GameInput.cpp] - Blame information for rev 116

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 114 bert
#include "SDL/SDL.h"
2 bert
 
3 bert
#include <iostream>
4 bert
 
5 bert
#include "Main.h"
6 bert
 
7 bert
#include "GameInput.h"
8 bert
 
9 bert
// The value where we make the difference between a press and a non-press
10 bert
const int GameInput::JOYSTICK_AXIS_THRESHOLD = 0x3fff;
11 bert
 
12 bert
// Input handling for keyboard and joystick
13 bert
GameInput::GameInput() {
14 bert
        joystick = NULL;
15 bert
 
16 bert
        reset();
17 bert
 
18 bert
        delay = 0;
19 bert
        interval = 0;
20 bert
 
21 bert
        keyboard_enabled = true;
22 bert
        joystick_enabled = false;
23 bert
 
24 bert
        keybinds = new std::vector<GameInputKeyBind>();
25 bert
        joybuttonbinds = new std::vector<GameInputJoyButtonBind>();
26 bert
        joyaxisbinds = new std::vector<GameInputJoyAxisBind>();
27 bert
        joyhatbinds = new std::vector<GameInputJoyHatBind>();
28 bert
}
29 bert
 
30 bert
GameInput::~GameInput() {
31 bert
        if(joystick != NULL)
32 bert
                SDL_JoystickClose(joystick);
33 bert
 
34 bert
        delete keybinds;
35 bert
        delete joybuttonbinds;
36 bert
        delete joyaxisbinds;
37 bert
        delete joyhatbinds;
38 bert
}
39 bert
 
40 115 bert
GameInput * GameInput::clone(bool clone_binds) {
41 bert
        GameInput * gi = new GameInput();
42 bert
 
43 bert
        gi->enable_keyboard(keyboard_enabled);
44 bert
        gi->enable_joystick(joystick_enabled);
45 bert
        gi->open_joystick(get_joystick_idx());
46 bert
 
47 bert
        if(clone_binds) {
48 bert
                for(unsigned int i = 0; i < keybinds->size(); i++) {
49 bert
                        gi->bind_key(keybinds->at(i).key, keybinds->at(i).action);
50 bert
                }
51 bert
 
52 bert
                for(unsigned int i = 0; i < joybuttonbinds->size(); i++) {
53 bert
                        gi->bind_joybutton(joybuttonbinds->at(i).button, joybuttonbinds->at(i).action);
54 bert
                }
55 bert
 
56 bert
                for(unsigned int i = 0; i < joyaxisbinds->size(); i++) {
57 bert
                        gi->bind_joyaxis(joyaxisbinds->at(i).axis, joyaxisbinds->at(i).threshold, joyaxisbinds->at(i).action);
58 bert
                }
59 bert
 
60 bert
                for(unsigned int i = 0; i < joyhatbinds->size(); i++) {
61 bert
                        gi->bind_joyhat(joyhatbinds->at(i).hat, joyhatbinds->at(i).direction, joyhatbinds->at(i).action);
62 bert
                }
63 bert
        }
64 bert
 
65 bert
        return gi;
66 bert
}
67 bert
 
68 bert
void GameInput::copy_from(GameInput * gi) {
69 bert
        enable_keyboard(gi->keyboard_enabled);
70 bert
        enable_joystick(gi->joystick_enabled);
71 bert
        open_joystick(gi->get_joystick_idx());
72 bert
 
73 bert
        flush_keybinds();
74 116 bert
        flush_joybuttons();
75 bert
        flush_joyaxes();
76 bert
        flush_joyhats();
77 115 bert
 
78 bert
        for(unsigned int i = 0; i < gi->keybinds->size(); i++) {
79 bert
                bind_key(gi->keybinds->at(i).key, gi->keybinds->at(i).action);
80 bert
        }
81 bert
 
82 bert
        for(unsigned int i = 0; i < gi->joybuttonbinds->size(); i++) {
83 bert
                bind_joybutton(gi->joybuttonbinds->at(i).button, gi->joybuttonbinds->at(i).action);
84 bert
        }
85 bert
 
86 bert
        for(unsigned int i = 0; i < gi->joyaxisbinds->size(); i++) {
87 bert
                bind_joyaxis(gi->joyaxisbinds->at(i).axis, gi->joyaxisbinds->at(i).threshold, gi->joyaxisbinds->at(i).action);
88 bert
        }
89 bert
 
90 bert
        for(unsigned int i = 0; i < gi->joyhatbinds->size(); i++) {
91 bert
                bind_joyhat(gi->joyhatbinds->at(i).hat, gi->joyhatbinds->at(i).direction, gi->joyhatbinds->at(i).action);
92 bert
        }
93 bert
}
94 bert
 
95 114 bert
// Enable keyboard
96 bert
void GameInput::enable_keyboard(bool enable) {
97 bert
        keyboard_enabled = enable;
98 bert
}
99 bert
 
100 bert
// Enable joystick
101 bert
void GameInput::enable_joystick(bool enable) {
102 bert
        joystick_enabled = enable;
103 bert
}
104 bert
 
105 bert
// Open a joystick
106 bert
bool GameInput::open_joystick(int index) {
107 bert
        if(joystick != NULL) {
108 bert
                SDL_JoystickClose(joystick);
109 bert
        }
110 bert
 
111 bert
        joystick = SDL_JoystickOpen(index);
112 bert
 
113 bert
        if(joystick == NULL)
114 bert
                return false;
115 bert
 
116 bert
        joystick_idx = index;
117 bert
        joystick_enabled = true;
118 bert
 
119 bert
        return true;
120 bert
}
121 bert
 
122 115 bert
int GameInput::get_joystick_idx() {
123 bert
        return joystick_idx;
124 bert
}
125 bert
 
126 116 bert
int GameInput::num_buttons() {
127 bert
        return SDL_JoystickNumButtons(joystick);
128 bert
}
129 bert
 
130 bert
int GameInput::num_axes() {
131 bert
        return SDL_JoystickNumAxes(joystick);
132 bert
}
133 bert
 
134 bert
int GameInput::num_hats() {
135 bert
        return SDL_JoystickNumHats(joystick);
136 bert
}
137 bert
 
138 114 bert
// Bind a keyboard key to an action
139 bert
void GameInput::bind_key(int key, int action) {
140 bert
        GameInputKeyBind bind;
141 bert
        bind.key = key;
142 bert
        bind.action = action;
143 bert
        keybinds->push_back(bind);
144 bert
}
145 bert
 
146 bert
// Bind a joystick button to an action
147 bert
void GameInput::bind_joybutton(int button, int action) {
148 bert
        GameInputJoyButtonBind bind;
149 bert
        bind.button = button;
150 bert
        bind.action = action;
151 bert
        joybuttonbinds->push_back(bind);
152 bert
}
153 bert
 
154 bert
// Bind an joystick axis button to an action
155 bert
void GameInput::bind_joyaxis(int axis, bool positive, int action) {
156 bert
        int threshold;
157 bert
        threshold = positive ? JOYSTICK_AXIS_THRESHOLD : -JOYSTICK_AXIS_THRESHOLD;
158 bert
        bind_joyaxis(axis, threshold, action);
159 bert
}
160 bert
 
161 bert
// Bind an joystick axis button to an action
162 bert
void GameInput::bind_joyaxis(int axis, int threshold, int action) {
163 bert
        GameInputJoyAxisBind bind;
164 bert
        bind.axis = axis;
165 bert
        bind.threshold = threshold;
166 bert
        bind.action = action;
167 bert
        joyaxisbinds->push_back(bind);
168 bert
}
169 bert
 
170 bert
// Bind a joystick POV-hat button to an action
171 bert
void GameInput::bind_joyhat(int hat, int direction, int action) {
172 bert
        GameInputJoyHatBind bind;
173 bert
        bind.hat = hat;
174 bert
        bind.direction = direction;
175 bert
        bind.action = action;
176 bert
        joyhatbinds->push_back(bind);
177 bert
}
178 bert
 
179 bert
// Check if a binded button for an action is pressed
180 bert
bool GameInput::is_pressed(int action) {
181 bert
        if(delay == 0)
182 bert
                return pressed[action];
183 bert
 
184 bert
        if(!pressed[action])
185 bert
                return false;
186 bert
 
187 bert
        int frames;
188 bert
 
189 bert
        frames = Main::frame - press_start[action];
190 bert
 
191 bert
        if(frames == 0)
192 bert
                return true;
193 bert
 
194 bert
        if(frames < delay)
195 bert
                return false;
196 bert
 
197 bert
        frames -= delay;
198 bert
        frames = frames % interval;
199 bert
 
200 bert
        if(frames == 0)
201 bert
                return true;
202 bert
        else
203 bert
                return false;
204 bert
}
205 bert
 
206 bert
void GameInput::reset() {
207 bert
        for(int i = 0; i < ACTION_COUNT; i++) {
208 bert
                pressed[i] = false;
209 bert
        }
210 bert
}
211 bert
 
212 bert
void GameInput::set_delay(int d, int i) {
213 bert
        delay = d;
214 bert
        interval = i;
215 bert
}
216 bert
 
217 bert
void GameInput::unset_delay() {
218 bert
        delay = 0;
219 bert
        interval = 0;
220 bert
}
221 bert
 
222 bert
void GameInput::handle_event(SDL_Event *event) {
223 bert
        unsigned int idx;
224 bert
 
225 bert
        if(keyboard_enabled) {
226 bert
                // Keyboard button
227 bert
                if(event->type == SDL_KEYDOWN || event->type == SDL_KEYUP) {
228 bert
                        GameInputKeyBind bind;
229 bert
 
230 bert
                        for(idx = 0; idx < keybinds->size(); idx++) {
231 bert
                                bind = keybinds->at(idx);
232 bert
                                if(bind.key == event->key.keysym.sym) {
233 bert
                                        if(event->type == SDL_KEYDOWN && !pressed[bind.action]) {
234 bert
                                                pressed[bind.action] = true;
235 bert
                                                press_start[bind.action] = Main::frame;
236 bert
                                        }
237 bert
                                        if(event->type == SDL_KEYUP && pressed[bind.action]) {
238 bert
                                                pressed[bind.action] = false;
239 bert
                                                press_start[bind.action] = 0;
240 bert
                                        }
241 bert
                                }
242 bert
                        }
243 bert
                }
244 bert
        }
245 bert
 
246 bert
        if(joystick_enabled) {
247 bert
                // Joystick button
248 bert
                if(event->type == SDL_JOYBUTTONDOWN || event->type == SDL_JOYBUTTONUP) {
249 bert
                        GameInputJoyButtonBind bind;
250 bert
 
251 bert
                        if(event->jbutton.which != joystick_idx)
252 bert
                                return;
253 bert
 
254 bert
                        for(idx = 0; idx < joybuttonbinds->size(); idx++) {
255 bert
                                bind = joybuttonbinds->at(idx);
256 bert
                                if(bind.button == event->jbutton.button) {
257 bert
                                        if(event->type == SDL_JOYBUTTONDOWN && !pressed[bind.action]) {
258 bert
                                                pressed[bind.action] = true;
259 bert
                                                press_start[bind.action] = Main::frame;
260 bert
                                        }
261 bert
                                        if(event->type == SDL_JOYBUTTONUP && pressed[bind.action]) {
262 bert
                                                pressed[bind.action] = false;
263 bert
                                                press_start[bind.action] = 0;
264 bert
                                        }
265 bert
                                }
266 bert
                        }
267 bert
                }
268 bert
 
269 bert
                // Joystick axis
270 bert
                if(event->type == SDL_JOYAXISMOTION) {
271 bert
                        GameInputJoyAxisBind bind;
272 bert
 
273 bert
                        if(event->jaxis.which != joystick_idx)
274 bert
                                return;
275 bert
 
276 bert
                        for(idx = 0; idx < joyaxisbinds->size(); idx++) {
277 bert
                                bind = joyaxisbinds->at(idx);
278 bert
                                if(bind.axis == event->jaxis.axis) {
279 bert
                                        if(!pressed[bind.action]) {
280 bert
                                                if(bind.threshold < 0 && bind.threshold > event->jaxis.value) {
281 bert
                                                        pressed[bind.action] = true;
282 bert
                                                        press_start[bind.action] = Main::frame;
283 bert
                                                }
284 bert
                                                else if(bind.threshold >= 0 && bind.threshold < event->jaxis.value) {
285 bert
                                                        pressed[bind.action] = true;
286 bert
                                                        press_start[bind.action] = Main::frame;
287 bert
                                                }
288 bert
                                        }
289 bert
                                        else {
290 bert
                                                if(bind.threshold < 0 && bind.threshold < event->jaxis.value) {
291 bert
                                                        pressed[bind.action] = false;
292 bert
                                                        press_start[bind.action] = 0;
293 bert
                                                }
294 bert
                                                if(bind.threshold >= 0 && bind.threshold > event->jaxis.value) {
295 bert
                                                        pressed[bind.action] = false;
296 bert
                                                        press_start[bind.action] = 0;
297 bert
                                                }
298 bert
                                        }
299 bert
                                }
300 bert
                        }
301 bert
                }
302 bert
 
303 bert
                // Joystick hat
304 bert
                if(event->type == SDL_JOYHATMOTION) {
305 bert
                        GameInputJoyHatBind bind;
306 bert
 
307 bert
                        if(event->jhat.which != joystick_idx)
308 bert
                                return;
309 bert
 
310 115 bert
                        for(idx = 0; idx < joyhatbinds->size(); idx++) {
311 114 bert
                                bind = joyhatbinds->at(idx);
312 bert
 
313 bert
                                if(bind.hat == event->jhat.hat) {
314 bert
                                        if((event->jhat.value & bind.direction) == bind.direction && !pressed[bind.action]) {
315 bert
                                                pressed[bind.action] = true;
316 bert
                                                press_start[bind.action] = Main::frame;
317 bert
                                        }
318 bert
                                        if((event->jhat.value & bind.direction) == 0 && pressed[bind.action]) {
319 bert
                                                pressed[bind.action] = false;
320 bert
                                                press_start[bind.action] = 0;
321 bert
                                        }
322 bert
                                }
323 bert
                        }
324 bert
                }
325 bert
        }
326 bert
}
327 bert
 
328 bert
// Get the current position of a joystick axis
329 bert
int GameInput::get_joyaxis(int axis) {
330 bert
        if(joystick_enabled || joystick != NULL) {
331 bert
                SDL_JoystickUpdate();
332 bert
                return SDL_JoystickGetAxis(joystick, axis);
333 bert
        }
334 bert
        else {
335 bert
                return 0;
336 bert
        }
337 bert
}
338 bert
 
339 bert
// Wait until a key is pressed
340 bert
int GameInput::keyboard_wait_event() {
341 bert
        SDL_Event event;
342 bert
        int retval;
343 bert
 
344 bert
        retval = 0;
345 bert
        while(Main::instance->running) {
346 bert
                SDL_WaitEvent(&event);
347 bert
 
348 bert
                Main::instance->handle_event(&event);
349 bert
 
350 bert
                if(event.type == SDL_KEYDOWN) {
351 bert
                        retval = event.key.keysym.sym;
352 bert
                        break;
353 bert
                }
354 bert
        }
355 bert
 
356 bert
        return retval;
357 bert
}
358 bert
 
359 bert
// Wait until a button has been pressed on the joystick
360 bert
void GameInput::joystick_wait_event(GameInputJoystickEvent * event) {
361 bert
        SDL_Event sdlevent;
362 bert
        int old_state;
363 bert
        int jindex;
364 bert
 
365 bert
        event->type = event->NONE;
366 bert
        event->button = 0;
367 bert
        event->axis_idx = 0;
368 bert
        event->axis_value = 0;
369 bert
        event->hat_idx = 0;
370 bert
        event->hat_direction = 0;
371 bert
 
372 bert
        if(!joystick_enabled || joystick == NULL)
373 bert
                return;
374 bert
 
375 bert
        joystick_wait_released();
376 bert
 
377 bert
        old_state = SDL_JoystickEventState(SDL_QUERY);
378 bert
        SDL_JoystickEventState(SDL_ENABLE);
379 bert
 
380 bert
        jindex = SDL_JoystickIndex(joystick);
381 bert
 
382 bert
        while(Main::instance->running) {
383 bert
                SDL_WaitEvent(&sdlevent);
384 bert
 
385 bert
                Main::instance->handle_event(&sdlevent);
386 bert
 
387 bert
                if(sdlevent.type == SDL_JOYBUTTONDOWN && sdlevent.jbutton.which == jindex) {
388 bert
                        event->type = event->BUTTON;
389 bert
                        event->button = sdlevent.jbutton.button;
390 bert
                        break;
391 bert
                }
392 bert
                if(sdlevent.type == SDL_JOYAXISMOTION && sdlevent.jaxis.which == jindex) {
393 bert
                        if(sdlevent.jaxis.value < -JOYSTICK_AXIS_THRESHOLD || sdlevent.jaxis.value > JOYSTICK_AXIS_THRESHOLD) {
394 bert
                                event->type = event->AXIS;
395 bert
                                event->axis_idx = sdlevent.jaxis.axis;
396 bert
                                if(sdlevent.jaxis.value < -JOYSTICK_AXIS_THRESHOLD) {
397 bert
                                        event->axis_value = -JOYSTICK_AXIS_THRESHOLD;
398 bert
                                } else {
399 bert
                                        event->axis_value = JOYSTICK_AXIS_THRESHOLD;
400 bert
                                }
401 bert
                                break;
402 bert
                        }
403 bert
                }
404 bert
                if(sdlevent.type == SDL_JOYHATMOTION && sdlevent.jhat.which == jindex) {
405 bert
                        event->type = event->HAT;
406 bert
                        event->hat_idx = sdlevent.jhat.hat;
407 bert
                        event->hat_direction = sdlevent.jhat.value;
408 bert
                        break;
409 bert
                }
410 bert
        }
411 bert
 
412 bert
        SDL_JoystickEventState(old_state);
413 bert
}
414 bert
 
415 bert
// Wait until all the joystick buttons are released and all the axes and hats are centered
416 bert
void GameInput::joystick_wait_released() {
417 bert
        int buttons, axes, hats;
418 bert
        int i;
419 bert
 
420 bert
        if(!joystick_enabled || joystick == NULL)
421 bert
                return;
422 bert
 
423 bert
        bool released;
424 bert
 
425 bert
        buttons = SDL_JoystickNumButtons(joystick);
426 bert
        axes = SDL_JoystickNumAxes(joystick);
427 bert
        hats = SDL_JoystickNumHats(joystick);
428 bert
 
429 bert
        do {
430 bert
                released = true;
431 bert
 
432 bert
                SDL_JoystickUpdate();
433 bert
 
434 bert
                for(i = 0; i < buttons; i++) {
435 bert
                        if(SDL_JoystickGetButton(joystick, i) == 1)
436 bert
                                released = false;
437 bert
                }
438 bert
 
439 bert
                for(i = 0; i < axes; i++) {
440 bert
                        if(SDL_JoystickGetAxis(joystick, i) < -JOYSTICK_AXIS_THRESHOLD ||
441 bert
                                SDL_JoystickGetAxis(joystick, i) > JOYSTICK_AXIS_THRESHOLD)
442 bert
                                released = false;
443 bert
                }
444 bert
 
445 bert
                for(i = 0; i < hats; i++) {
446 bert
                        if(SDL_JoystickGetHat(joystick, i) != SDL_HAT_CENTERED)
447 bert
                                released = false;
448 bert
                }
449 bert
        } while(!released);
450 bert
}
451 bert
 
452 bert
// Poll for a key and bind it
453 bert
void GameInput::keyboard_wait_event_bind(int action) {
454 bert
        int key;
455 bert
        key = keyboard_wait_event();
456 bert
        if(key != 0) {
457 bert
                bind_key(key, action);
458 bert
        }
459 bert
}
460 bert
 
461 bert
// Poll for a joystick button, axis or hat press and bind it
462 bert
void GameInput::joystick_wait_event_bind(int action) {
463 bert
        GameInputJoystickEvent event;
464 bert
 
465 bert
        joystick_wait_event(&event);
466 bert
 
467 bert
        if(event.type == event.BUTTON) {
468 bert
                bind_joybutton(event.button, action);
469 bert
        }
470 bert
        if(event.type == event.AXIS) {
471 bert
                bind_joyaxis(event.axis_idx, event.axis_value, action);
472 bert
        }
473 bert
        if(event.type == event.HAT) {
474 bert
                bind_joyhat(event.hat_idx, event.hat_direction, action);
475 bert
        }
476 bert
}
477 bert
 
478 bert
void GameInput::load_options(std::istream * stream) {
479 bert
        int i;
480 bert
        short count;
481 bert
 
482 bert
        count = 0;
483 bert
 
484 bert
        stream->read((char *)&joystick_idx, sizeof(int));
485 bert
        open_joystick(joystick_idx);
486 bert
 
487 bert
        stream->read((char*)&count, sizeof(short));
488 bert
        for(i = 0; i < count; i++) {
489 bert
                GameInputKeyBind bind;
490 bert
                stream->read((char *)&bind, sizeof(GameInputKeyBind));
491 bert
                keybinds->push_back(bind);
492 bert
        }
493 bert
 
494 bert
        stream->read((char*)&count, sizeof(short));
495 bert
        for(i = 0; i < count; i++) {
496 bert
                GameInputJoyButtonBind bind;
497 bert
                stream->read((char *)&bind, sizeof(GameInputJoyButtonBind));
498 bert
                joybuttonbinds->push_back(bind);
499 bert
        }
500 bert
 
501 bert
        stream->read((char*)&count, sizeof(short));
502 bert
        for(i = 0; i < count; i++) {
503 bert
                GameInputJoyAxisBind bind;
504 bert
                stream->read((char *)&bind, sizeof(GameInputJoyAxisBind));
505 bert
                joyaxisbinds->push_back(bind);
506 bert
        }
507 bert
 
508 bert
        stream->read((char*)&count, sizeof(short));
509 bert
        for(i = 0; i < count; i++) {
510 bert
                GameInputJoyHatBind bind;
511 bert
                stream->read((char *)&bind, sizeof(GameInputJoyHatBind));
512 bert
                joyhatbinds->push_back(bind);
513 bert
        }
514 bert
}
515 bert
 
516 bert
void GameInput::save_options(std::ostream * stream) {
517 bert
        short count;
518 bert
 
519 bert
        stream->write((char *)&joystick_idx, sizeof(int));
520 bert
 
521 bert
        count = (short)keybinds->size();
522 bert
        stream->write((char *)&count, sizeof(short));
523 bert
        for(unsigned int i = 0; i < keybinds->size(); i++) {
524 bert
                stream->write((char *)&keybinds->at(i), sizeof(GameInputKeyBind));
525 bert
        }
526 bert
 
527 bert
        count = (short)joybuttonbinds->size();
528 bert
        stream->write((char *)&count, sizeof(short));
529 bert
        for(unsigned int i = 0; i < joybuttonbinds->size(); i++) {
530 bert
                stream->write((char *)&joybuttonbinds->at(i), sizeof(GameInputJoyButtonBind));
531 bert
        }
532 bert
 
533 bert
        count = (short)joyaxisbinds->size();
534 bert
        stream->write((char *)&count, sizeof(short));
535 bert
        for(unsigned int i = 0; i < joyaxisbinds->size(); i++) {
536 bert
                stream->write((char *)&joyaxisbinds->at(i), sizeof(GameInputJoyAxisBind));
537 bert
        }
538 bert
 
539 bert
        count = (short)joyhatbinds->size();
540 bert
        stream->write((char *)&count, sizeof(short));
541 bert
        for(unsigned int i = 0; i < joyhatbinds->size(); i++) {
542 bert
                stream->write((char *)&joyhatbinds->at(i), sizeof(GameInputJoyHatBind));
543 bert
        }
544 bert
}
545 115 bert
 
546 bert
void GameInput::flush_keybinds() {
547 bert
        keybinds->clear();
548 bert
}
549 bert
 
550 116 bert
void GameInput::flush_joybuttons() {
551 115 bert
        joybuttonbinds->clear();
552 116 bert
}
553 bert
 
554 bert
void GameInput::flush_joyaxes() {
555 115 bert
        joyaxisbinds->clear();
556 116 bert
}
557 bert
 
558 bert
void GameInput::flush_joyhats() {
559 115 bert
        joyhatbinds->clear();
560 bert
}