comparison docs/html/guideinput.html @ 0:74212992fb08

Initial revision
author Sam Lantinga <slouken@lokigames.com>
date Thu, 26 Apr 2001 16:45:43 +0000
parents
children 55f1f1b3e27d
comparison
equal deleted inserted replaced
-1:000000000000 0:74212992fb08
1 <HTML
2 ><HEAD
3 ><TITLE
4 >Input handling</TITLE
5 ><META
6 NAME="GENERATOR"
7 CONTENT="Modular DocBook HTML Stylesheet Version 1.61
8 "><LINK
9 REL="HOME"
10 TITLE="SDL Library Documentation"
11 HREF="index.html"><LINK
12 REL="UP"
13 TITLE="SDL Guide"
14 HREF="guide.html"><LINK
15 REL="PREVIOUS"
16 TITLE="Graphics and Video"
17 HREF="guidevideo.html"><LINK
18 REL="NEXT"
19 TITLE="Handling the Keyboard"
20 HREF="guideinputkeyboard.html"></HEAD
21 ><BODY
22 CLASS="CHAPTER"
23 BGCOLOR="#FFF8DC"
24 TEXT="#000000"
25 LINK="#0000ee"
26 VLINK="#551a8b"
27 ALINK="#ff0000"
28 ><DIV
29 CLASS="NAVHEADER"
30 ><TABLE
31 WIDTH="100%"
32 BORDER="0"
33 CELLPADDING="0"
34 CELLSPACING="0"
35 ><TR
36 ><TH
37 COLSPAN="3"
38 ALIGN="center"
39 >SDL Library Documentation</TH
40 ></TR
41 ><TR
42 ><TD
43 WIDTH="10%"
44 ALIGN="left"
45 VALIGN="bottom"
46 ><A
47 HREF="guidevideo.html"
48 >Prev</A
49 ></TD
50 ><TD
51 WIDTH="80%"
52 ALIGN="center"
53 VALIGN="bottom"
54 ></TD
55 ><TD
56 WIDTH="10%"
57 ALIGN="right"
58 VALIGN="bottom"
59 ><A
60 HREF="guideinputkeyboard.html"
61 >Next</A
62 ></TD
63 ></TR
64 ></TABLE
65 ><HR
66 ALIGN="LEFT"
67 WIDTH="100%"></DIV
68 ><DIV
69 CLASS="CHAPTER"
70 ><H1
71 ><A
72 NAME="GUIDEINPUT"
73 >Chapter 3. Input handling</A
74 ></H1
75 ><DIV
76 CLASS="TOC"
77 ><DL
78 ><DT
79 ><B
80 >Table of Contents</B
81 ></DT
82 ><DT
83 ><A
84 HREF="guideinput.html#GUIDEINPUTJOYSTICK"
85 >Handling Joysticks</A
86 ></DT
87 ><DT
88 ><A
89 HREF="guideinputkeyboard.html"
90 >Handling the Keyboard</A
91 ></DT
92 ></DL
93 ></DIV
94 ><DIV
95 CLASS="SECT1"
96 ><H1
97 CLASS="SECT1"
98 ><A
99 NAME="GUIDEINPUTJOYSTICK"
100 >Handling Joysticks</A
101 ></H1
102 ><DIV
103 CLASS="SECT2"
104 ><H2
105 CLASS="SECT2"
106 ><A
107 NAME="AEN94"
108 >Initialization</A
109 ></H2
110 ><P
111 >The first step in using a joystick in a SDL program is to initialize the Joystick subsystems of SDL. This done by passing the <TT
112 CLASS="LITERAL"
113 >SDL_INIT_JOYSTICK</TT
114 > flag to <A
115 HREF="sdlinit.html"
116 ><TT
117 CLASS="FUNCTION"
118 >SDL_Init</TT
119 ></A
120 >. The joystick flag will usually be used in conjunction with other flags (like the video flag) because the joystick is usually used to control something.
121 <PRE
122 CLASS="PROGRAMLISTING"
123 > if ( ! SDL_Init( SDL_INIT_VIDEO | SDL_INIT_JOYSTICK ) )
124 {
125 fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
126 exit(1);
127 }</PRE
128 >
129 This will attempt to start SDL with both the video and the joystick subsystems activated.</P
130 ></DIV
131 ><DIV
132 CLASS="SECT2"
133 ><H2
134 CLASS="SECT2"
135 ><A
136 NAME="AEN101"
137 >Querying</A
138 ></H2
139 ><P
140 >If we have reached this point then we can safely assume that the SDL library has been initialized and that the Joystick subsystem is active. We can now call some video and/or sound functions to get things going before we need the joystick. Eventually we have to make sure that there is actually a joystick to work with. It's wise to always check even if you know a joystick will be present on the system because it can also help detect when the joystick is unplugged. The function used to check for joysticks is <A
141 HREF="sdlnumjoysticks.html"
142 ><TT
143 CLASS="FUNCTION"
144 >SDL_NumJoysticks</TT
145 ></A
146 >.</P
147 ><P
148 >This function simply returns the number of joysticks available on the system. If it is at least one then we are in good shape. The next step is to determine which joystick the user wants to use. If the number of joysticks available is only one then it is safe to assume that one joystick is the one the user wants to use. SDL has a function to get the name of the joysticks as assigned by the operations system and that function is <A
149 HREF="sdljoystickname.html"
150 ><TT
151 CLASS="FUNCTION"
152 >SDL_JoystickName</TT
153 ></A
154 >. The joystick is specified by an index where 0 is the first joystick and the last joystick is the number returned by <TT
155 CLASS="FUNCTION"
156 >SDL_NumJoysticks</TT
157 > - 1. In the demonstration a list of all available joysticks is printed to stdout.
158 <PRE
159 CLASS="PROGRAMLISTING"
160 > printf("%i joysticks were found.\n\n", SDL_NumJoysticks() );
161 printf("The names of the joysticks are:\n");
162
163 for( i=0; i &#60; SDL_NumJoysticks(); i++ )
164 {
165 printf(" %s\n", SDL_JoystickName(i));
166 }</PRE
167 ></P
168 ></DIV
169 ><DIV
170 CLASS="SECT2"
171 ><H2
172 CLASS="SECT2"
173 ><A
174 NAME="AEN111"
175 >Opening a Joystick and Receiving Joystick Events</A
176 ></H2
177 ><P
178 >SDL's event driven architecture makes working with joysticks a snap. Joysticks can trigger 4 different types of events:
179 <P
180 ></P
181 ><TABLE
182 BORDER="0"
183 ><TBODY
184 ><TR
185 ><TD
186 ><A
187 HREF="sdljoyaxisevent.html"
188 ><SPAN
189 CLASS="STRUCTNAME"
190 >SDL_JoyAxisEvent</SPAN
191 ></A
192 ></TD
193 ><TD
194 >Occurs when an axis changes</TD
195 ></TR
196 ><TR
197 ><TD
198 ><A
199 HREF="sdljoyballevent.html"
200 ><SPAN
201 CLASS="STRUCTNAME"
202 >SDL_JoyBallEvent</SPAN
203 ></A
204 ></TD
205 ><TD
206 >Occurs when a joystick trackball's position changes</TD
207 ></TR
208 ><TR
209 ><TD
210 ><A
211 HREF="sdljoyhatevent.html"
212 ><SPAN
213 CLASS="STRUCTNAME"
214 >SDL_JoyHatEvent</SPAN
215 ></A
216 ></TD
217 ><TD
218 >Occurs when a hat's position changes</TD
219 ></TR
220 ><TR
221 ><TD
222 ><A
223 HREF="sdljoybuttonevent.html"
224 ><SPAN
225 CLASS="STRUCTNAME"
226 >SDL_JoyButtonEvent</SPAN
227 ></A
228 ></TD
229 ><TD
230 >Occurs when a button is pressed or released</TD
231 ></TR
232 ></TBODY
233 ></TABLE
234 ><P
235 ></P
236 ></P
237 ><P
238 >Events are received from all joysticks opened. The first thing that needs to be done in order to receive joystick events is to call <A
239 HREF="sdljoystickeventstate.html"
240 ><TT
241 CLASS="FUNCTION"
242 >SDL_JoystickEventState</TT
243 ></A
244 > with the <TT
245 CLASS="LITERAL"
246 >SDL_ENABLE</TT
247 > flag. Next you must open the joysticks that you want to receive envents from. This is done with the <A
248 HREF="sdljoystickopen.html"
249 ><TT
250 CLASS="FUNCTION"
251 >SDL_JoystickOpen</TT
252 ></A
253 > function. For the example we are only interested in events from the first joystick on the system, regardless of what it may be. To receive events from it we would do this:
254 <PRE
255 CLASS="PROGRAMLISTING"
256 > SDL_Joystick *joystick;
257
258 SDL_JoystickEventState(SDL_ENABLE);
259 joystick = SDL_JoystickOpen(0);</PRE
260 >
261 If we wanted to receive events for other joysticks we would open them with calls to <TT
262 CLASS="FUNCTION"
263 >SDL_JoystickOpen</TT
264 > just like we opened joystick 0, except we would store the <SPAN
265 CLASS="STRUCTNAME"
266 >SDL_Joystick</SPAN
267 > structure they return in a different pointer. We only need the joystick pointer when we are querying the joysticks or when we are closing the joystick.</P
268 ><P
269 >Up to this point all the code we have is used just to initialize the joysticks in order to read values at run time. All we need now is an event loop, which is something that all SDL programs should have anyway to receive the systems quit events. We must now add code to check the event loop for at least some of the above mentioned events. Let's assume our event loop looks like this:
270 <PRE
271 CLASS="PROGRAMLISTING"
272 > SDL_Event *event;
273 /* Other initializtion code goes here */
274
275 /* Start main game loop here */
276
277 while(SDL_PollEvent(&#38;event))
278 {
279 switch(event.type)
280 {
281 case SDL_KEYDOWN:
282 /* handle keyboard stuff here */
283 break;
284
285 case SDL_QUIT:
286 /* Set whatever flags are necessary to */
287 /* end the main game loop here */
288 break;
289 }
290 }
291
292 /* End loop here */</PRE
293 >
294 To handle Joystick events we merely add cases for them, first we'll add axis handling code. Axis checks can get kinda of tricky because alot of the joystick events received are junk. Joystick axis have a tendency to vary just a little between polling due to the way they are designed. To compensate for this you have to set a threshold for changes and ignore the events that have'nt exceeded the threshold. 10% is usually a good threshold value. This sounds a lot more complicated than it is. Here is the Axis event handler:
295 <PRE
296 CLASS="PROGRAMLISTING"
297 > case SDL_JOYAXISMOTION: /* Handle Joystick Motion */
298 if ( ( event.jaxis.value &#60; -3200 ) || (event.jaxis.value &#62; 3200 ) )
299 {
300 /* code goes here */
301 }
302 break;</PRE
303 >
304 Another trick with axis events is that up-down and left-right movement are two different sets of axes. The most important axis is axis 0 (left-right) and axis 1 (up-down). To handle them seperatly in the code we do the following:
305 <PRE
306 CLASS="PROGRAMLISTING"
307 > case SDL_JOYAXISMOTION: /* Handle Joystick Motion */
308 if ( ( event.jaxis.value &#60; -3200 ) || (event.jaxis.value &#62; 3200 ) )
309 {
310 if( event.jaxis.axis == 0)
311 {
312 /* Left-right movement code goes here */
313 }
314
315 if( event.jaxis.axis == 1)
316 {
317 /* Up-Down movement code goes here */
318 }
319 }
320 break;</PRE
321 >
322 Ideally the code here should use <TT
323 CLASS="STRUCTFIELD"
324 ><I
325 >event.jaxis.value</I
326 ></TT
327 > to scale something. For example lets assume you are using the joystick to control the movement of a spaceship. If the user is using an analog joystick and they push the stick a little bit they expect to move less than if they pushed it a lot. Designing your code for this situation is preferred because it makes the experience for users of analog controls better and remains the same for users of digital controls.</P
328 ><P
329 >If your joystick has any additional axis then they may be used for other sticks or throttle controls and those axis return values too just with different <TT
330 CLASS="STRUCTFIELD"
331 ><I
332 >event.jaxis.axis</I
333 ></TT
334 > values.</P
335 ><P
336 >Button handling is simple compared to the axis checking.
337 <PRE
338 CLASS="PROGRAMLISTING"
339 > case SDL_JOYBUTTONDOWN: /* Handle Joystick Button Presses */
340 if ( event.jbutton.button == 0 )
341 {
342 /* code goes here */
343 }
344 break;</PRE
345 >
346
347 Button checks are simpler than axis checks because a button can only be pressed or not pressed. The <TT
348 CLASS="LITERAL"
349 >SDL_JOYBUTTONDOWN</TT
350 > event is triggered when a button is pressed and the <TT
351 CLASS="LITERAL"
352 >SDL_JOYBUTTONUP</TT
353 > event is fired when a button is released. We do have to know what button was pressed though, that is done by reading the <TT
354 CLASS="STRUCTFIELD"
355 ><I
356 >event.jbutton.button</I
357 ></TT
358 > field.</P
359 ><P
360 >Lastly when we are through using our joysticks we should close them with a call to <A
361 HREF="sdljoystickclose.html"
362 ><TT
363 CLASS="FUNCTION"
364 >SDL_JoystickClose</TT
365 ></A
366 >. To close our opened joystick 0 we would do this at the end of our program:
367 <PRE
368 CLASS="PROGRAMLISTING"
369 > SDL_JoystickClose(joystick);</PRE
370 ></P
371 ></DIV
372 ><DIV
373 CLASS="SECT2"
374 ><H2
375 CLASS="SECT2"
376 ><A
377 NAME="AEN156"
378 >Advanced Joystick Functions</A
379 ></H2
380 ><P
381 >That takes care of the controls that you can count on being on every joystick under the sun, but there are a few extra things that SDL can support. Joyballs are next on our list, they are alot like axis we a few minor differences. Joyballs store relative changes unlike the the absolute postion stored in a axis event. Also one trackball event contains both the change in x and they change in y. Our case for it is as follows:
382 <PRE
383 CLASS="PROGRAMLISTING"
384 > case SDL_JOYBALLMOTION: /* Handle Joyball Motion */
385 if( event.jball.ball == 0 )
386 {
387 /* ball handling */
388 }
389 break;</PRE
390 >
391 The above checks the first joyball on the joystick. The change in position will be stored in <TT
392 CLASS="STRUCTFIELD"
393 ><I
394 >event.jball.xrel</I
395 ></TT
396 > and <TT
397 CLASS="STRUCTFIELD"
398 ><I
399 >event.jball.yrel</I
400 ></TT
401 >.</P
402 ><P
403 >Finally we have the hat event. Hats report only the direction they are pushed in. We check hat's position with the bitmasks:
404
405 <P
406 ></P
407 ><TABLE
408 BORDER="0"
409 ><TBODY
410 ><TR
411 ><TD
412 ><TT
413 CLASS="LITERAL"
414 >SDL_HAT_CENTERED</TT
415 ></TD
416 ></TR
417 ><TR
418 ><TD
419 ><TT
420 CLASS="LITERAL"
421 >SDL_HAT_UP</TT
422 ></TD
423 ></TR
424 ><TR
425 ><TD
426 ><TT
427 CLASS="LITERAL"
428 >SDL_HAT_RIGHT</TT
429 ></TD
430 ></TR
431 ><TR
432 ><TD
433 ><TT
434 CLASS="LITERAL"
435 >SDL_HAT_DOWN</TT
436 ></TD
437 ></TR
438 ><TR
439 ><TD
440 ><TT
441 CLASS="LITERAL"
442 >SDL_HAT_LEFT</TT
443 ></TD
444 ></TR
445 ></TBODY
446 ></TABLE
447 ><P
448 ></P
449 >
450
451 Also there are some predefined combinations of the above:
452 <P
453 ></P
454 ><TABLE
455 BORDER="0"
456 ><TBODY
457 ><TR
458 ><TD
459 ><TT
460 CLASS="LITERAL"
461 >SDL_HAT_RIGHTUP</TT
462 ></TD
463 ></TR
464 ><TR
465 ><TD
466 ><TT
467 CLASS="LITERAL"
468 >SDL_HAT_RIGHTDOWN</TT
469 ></TD
470 ></TR
471 ><TR
472 ><TD
473 ><TT
474 CLASS="LITERAL"
475 >SDL_HAT_LEFTUP</TT
476 ></TD
477 ></TR
478 ><TR
479 ><TD
480 ><TT
481 CLASS="LITERAL"
482 >SDL_HAT_LEFTDOWN</TT
483 ></TD
484 ></TR
485 ></TBODY
486 ></TABLE
487 ><P
488 ></P
489 >
490
491 Our case for the hat may resemble the following:
492
493 <PRE
494 CLASS="PROGRAMLISTING"
495 > case SDL_JOYHATMOTION: /* Handle Hat Motion */
496 if ( event.jhat.hat | SDL_HAT_UP )
497 {
498 /* Do up stuff here */
499 }
500
501 if ( event.jhat.hat | SDL_HAT_LEFT )
502 {
503 /* Do left stuff here */
504 }
505
506 if ( event.jhat.hat | SDL_HAT_RIGHTDOWN )
507 {
508 /* Do right and down together stuff here */
509 }
510 break;</PRE
511 ></P
512 ><P
513 >In addition to the queries for number of joysticks on the system and their names there are additional functions to query the capabilities of attached joysticks:
514 <P
515 ></P
516 ><TABLE
517 BORDER="0"
518 ><TBODY
519 ><TR
520 ><TD
521 ><A
522 HREF="sdljoysticknumaxes.html"
523 ><TT
524 CLASS="FUNCTION"
525 >SDL_JoystickNumAxes</TT
526 ></A
527 ></TD
528 ><TD
529 >Returns the number of joysitck axes</TD
530 ></TR
531 ><TR
532 ><TD
533 ><A
534 HREF="sdljoysticknumbuttons.html"
535 ><TT
536 CLASS="FUNCTION"
537 >SDL_JoystickNumButtons</TT
538 ></A
539 ></TD
540 ><TD
541 >Returns the number of joysitck buttons</TD
542 ></TR
543 ><TR
544 ><TD
545 ><A
546 HREF="sdljoysticknumballs.html"
547 ><TT
548 CLASS="FUNCTION"
549 >SDL_JoystickNumBalls</TT
550 ></A
551 ></TD
552 ><TD
553 >Returns the number of joysitck balls</TD
554 ></TR
555 ><TR
556 ><TD
557 ><A
558 HREF="sdljoysticknumhats.html"
559 ><TT
560 CLASS="FUNCTION"
561 >SDL_JoystickNumHats</TT
562 ></A
563 ></TD
564 ><TD
565 >Returns the number of joysitck hats</TD
566 ></TR
567 ></TBODY
568 ></TABLE
569 ><P
570 ></P
571 >
572
573 To use these functions we just have to pass in the joystick structure we got when we opened the joystick. For Example:
574
575 <PRE
576 CLASS="PROGRAMLISTING"
577 > int number_of_buttons;
578 SDL_Joystick *joystick;
579
580 joystick = SDL_JoystickOpen(0);
581 number_of_buttons = SDL_JoystickNumButtons(joystick);</PRE
582 >
583
584 This block of code would get the number of buttons on the first joystick in the system. </P
585 ></DIV
586 ></DIV
587 ></DIV
588 ><DIV
589 CLASS="NAVFOOTER"
590 ><HR
591 ALIGN="LEFT"
592 WIDTH="100%"><TABLE
593 WIDTH="100%"
594 BORDER="0"
595 CELLPADDING="0"
596 CELLSPACING="0"
597 ><TR
598 ><TD
599 WIDTH="33%"
600 ALIGN="left"
601 VALIGN="top"
602 ><A
603 HREF="guidevideo.html"
604 >Prev</A
605 ></TD
606 ><TD
607 WIDTH="34%"
608 ALIGN="center"
609 VALIGN="top"
610 ><A
611 HREF="index.html"
612 >Home</A
613 ></TD
614 ><TD
615 WIDTH="33%"
616 ALIGN="right"
617 VALIGN="top"
618 ><A
619 HREF="guideinputkeyboard.html"
620 >Next</A
621 ></TD
622 ></TR
623 ><TR
624 ><TD
625 WIDTH="33%"
626 ALIGN="left"
627 VALIGN="top"
628 >Graphics and Video</TD
629 ><TD
630 WIDTH="34%"
631 ALIGN="center"
632 VALIGN="top"
633 ><A
634 HREF="guide.html"
635 >Up</A
636 ></TD
637 ><TD
638 WIDTH="33%"
639 ALIGN="right"
640 VALIGN="top"
641 >Handling the Keyboard</TD
642 ></TR
643 ></TABLE
644 ></DIV
645 ></BODY
646 ></HTML
647 >