Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5131 clevermous 1
2
>
3
>
4
>Input handling
5
>
6
NAME="GENERATOR"
7
CONTENT="Modular DocBook HTML Stylesheet Version 1.64
8
">
9
REL="HOME"
10
TITLE="SDL Library Documentation"
11
HREF="index.html">
12
REL="UP"
13
TITLE="SDL Guide"
14
HREF="guide.html">
15
REL="PREVIOUS"
16
TITLE="Using OpenGL With SDL"
17
HREF="guidevideoopengl.html">
18
REL="NEXT"
19
TITLE="Handling the Keyboard"
20
HREF="guideinputkeyboard.html">
21
>
22
CLASS="CHAPTER"
23
BGCOLOR="#FFF8DC"
24
TEXT="#000000"
25
LINK="#0000ee"
26
VLINK="#551a8b"
27
ALINK="#ff0000"
28
>
29
CLASS="NAVHEADER"
30
>
31
WIDTH="100%"
32
BORDER="0"
33
CELLPADDING="0"
34
CELLSPACING="0"
35
>
36
>
37
COLSPAN="3"
38
ALIGN="center"
39
>SDL Library Documentation
40
>
41
>
42
>
43
WIDTH="10%"
44
ALIGN="left"
45
VALIGN="bottom"
46
>
47
HREF="guidevideoopengl.html"
48
>Prev
49
>
50
>
51
WIDTH="80%"
52
ALIGN="center"
53
VALIGN="bottom"
54
>
55
>
56
WIDTH="10%"
57
ALIGN="right"
58
VALIGN="bottom"
59
>
60
HREF="guideinputkeyboard.html"
61
>Next
62
>
63
>
64
>
65
>
66
ALIGN="LEFT"
67
WIDTH="100%">
68
>
69
CLASS="CHAPTER"
70
>
71
>
72
NAME="GUIDEINPUT"
73
>Chapter 3. Input handling
74
>
75
>
76
CLASS="TOC"
77
>
78
>
79
>
80
>Table of Contents
81
>
82
>
83
>
84
HREF="guideinput.html#GUIDEINPUTJOYSTICK"
85
>Handling Joysticks
86
>
87
>
88
>
89
HREF="guideinputkeyboard.html"
90
>Handling the Keyboard
91
>
92
>
93
>
94
>
95
CLASS="SECT1"
96
>
97
CLASS="SECT1"
98
>
99
NAME="GUIDEINPUTJOYSTICK"
100
>Handling Joysticks
101
>
102
>
103
CLASS="SECT2"
104
>
105
CLASS="SECT2"
106
>
107
NAME="AEN135"
108
>Initialization
109
>
110
>
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 
112
CLASS="LITERAL"
113
>SDL_INIT_JOYSTICK
114
> flag to 
115
HREF="sdlinit.html"
116
>
117
CLASS="FUNCTION"
118
>SDL_Init
119
>
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
>
122
CLASS="EXAMPLE"
123
>
124
NAME="AEN141"
125
>
126
>
127
>
128
>Example 3-1. Initializing SDL with Joystick Support
129
>
130
>
131
CLASS="PROGRAMLISTING"
132
>    if (SDL_Init( SDL_INIT_VIDEO | SDL_INIT_JOYSTICK ) < 0)
133
    {
134
        fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
135
        exit(1);
136
    }
137
>
138
>
139
>This will attempt to start SDL with both the video and the joystick subsystems activated.
140
>
141
>
142
CLASS="SECT2"
143
>
144
CLASS="SECT2"
145
>
146
NAME="AEN145"
147
>Querying
148
>
149
>
150
>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 
151
HREF="sdlnumjoysticks.html"
152
>
153
CLASS="FUNCTION"
154
>SDL_NumJoysticks
155
>
156
>.
157
>
158
>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 
159
HREF="sdljoystickname.html"
160
>
161
CLASS="FUNCTION"
162
>SDL_JoystickName
163
>
164
>.  The joystick is specified by an index where 0 is the first joystick and the last joystick is the number returned by 
165
CLASS="FUNCTION"
166
>SDL_NumJoysticks
167
> - 1.  In the demonstration a list of all available joysticks is printed to stdout.
168
>
169
CLASS="EXAMPLE"
170
>
171
NAME="AEN154"
172
>
173
>
174
>
175
>Example 3-2. Querying the Number of Available Joysticks
176
>
177
>
178
CLASS="PROGRAMLISTING"
179
>    printf("%i joysticks were found.\n\n", SDL_NumJoysticks() );
180
    printf("The names of the joysticks are:\n");
181
 
182
    for( i=0; i < SDL_NumJoysticks(); i++ )
183
    {
184
        printf("    %s\n", SDL_JoystickName(i));
185
    }
186
>
187
>
188
>
189
CLASS="SECT2"
190
>
191
CLASS="SECT2"
192
>
193
NAME="AEN157"
194
>Opening a Joystick and Receiving Joystick Events
195
>
196
>
197
>SDL's event driven architecture makes working with joysticks a snap.  Joysticks can trigger 4 different types of events:
198
199
>
200
>
201
BORDER="0"
202
>
203
>
204
>
205
>
206
HREF="sdljoyaxisevent.html"
207
>
208
CLASS="STRUCTNAME"
209
>SDL_JoyAxisEvent
210
>
211
>
212
>
213
>Occurs when an axis changes
214
>
215
>
216
>
217
>
218
HREF="sdljoyballevent.html"
219
>
220
CLASS="STRUCTNAME"
221
>SDL_JoyBallEvent
222
>
223
>
224
>
225
>Occurs when a joystick trackball's position changes
226
>
227
>
228
>
229
>
230
HREF="sdljoyhatevent.html"
231
>
232
CLASS="STRUCTNAME"
233
>SDL_JoyHatEvent
234
>
235
>
236
>
237
>Occurs when a hat's position changes
238
>
239
>
240
>
241
>
242
HREF="sdljoybuttonevent.html"
243
>
244
CLASS="STRUCTNAME"
245
>SDL_JoyButtonEvent
246
>
247
>
248
>
249
>Occurs when a button is pressed or released
250
>
251
>
252
>
253
>
254
>
255
>
256
>
257
>Events are received from all joysticks opened. The first thing that needs to be done in order to receive joystick events is to call 
258
HREF="sdljoystickeventstate.html"
259
>
260
CLASS="FUNCTION"
261
>SDL_JoystickEventState
262
>
263
> with the 
264
CLASS="LITERAL"
265
>SDL_ENABLE
266
> flag. Next you must open the joysticks that you want to receive envents from. This is done with the 
267
HREF="sdljoystickopen.html"
268
>
269
CLASS="FUNCTION"
270
>SDL_JoystickOpen
271
>
272
> 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:
273
>
274
CLASS="EXAMPLE"
275
>
276
NAME="AEN183"
277
>
278
>
279
>
280
>Example 3-3. Opening a Joystick
281
>
282
>
283
CLASS="PROGRAMLISTING"
284
>    SDL_Joystick *joystick;
285
 
286
    SDL_JoystickEventState(SDL_ENABLE);
287
    joystick = SDL_JoystickOpen(0);
288
>
289
>
290
>If we wanted to receive events for other joysticks we would open them with calls to 
291
CLASS="FUNCTION"
292
>SDL_JoystickOpen
293
> just like we opened joystick 0, except we would store the 
294
CLASS="STRUCTNAME"
295
>SDL_Joystick
296
> 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.
297
>
298
>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:
299
300
CLASS="PROGRAMLISTING"
301
>    SDL_Event event;
302
    /* Other initializtion code goes here */
303
 
304
    /* Start main game loop here */
305
 
306
    while(SDL_PollEvent(&event))
307
    {
308
        switch(event.type)
309
        {
310
            case SDL_KEYDOWN:
311
            /* handle keyboard stuff here */
312
            break;
313
 
314
            case SDL_QUIT:
315
            /* Set whatever flags are necessary to */
316
            /* end the main game loop here */
317
            break;
318
        }
319
    }
320
 
321
    /* End loop here */
322
>
323
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:
324
>
325
CLASS="EXAMPLE"
326
>
327
NAME="AEN191"
328
>
329
>
330
>
331
>Example 3-4. Joystick Axis Events
332
>
333
>
334
CLASS="PROGRAMLISTING"
335
>    case SDL_JOYAXISMOTION:  /* Handle Joystick Motion */
336
    if ( ( event.jaxis.value < -3200 ) || (event.jaxis.value > 3200 ) )
337
    {
338
      /* code goes here */
339
    }
340
    break;
341
>
342
>
343
>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:
344
>
345
CLASS="EXAMPLE"
346
>
347
NAME="AEN195"
348
>
349
>
350
>
351
>Example 3-5. More Joystick Axis Events
352
>
353
>
354
CLASS="PROGRAMLISTING"
355
>    case SDL_JOYAXISMOTION:  /* Handle Joystick Motion */
356
    if ( ( event.jaxis.value < -3200 ) || (event.jaxis.value > 3200 ) )
357
    {
358
        if( event.jaxis.axis == 0)
359
        {
360
            /* Left-right movement code goes here */
361
        }
362
 
363
        if( event.jaxis.axis == 1)
364
        {
365
            /* Up-Down movement code goes here */
366
        }
367
    }
368
    break;
369
>
370
>
371
>Ideally the code here should use 
372
CLASS="STRUCTFIELD"
373
>
374
>event.jaxis.value
375
>
376
> 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.
377
>
378
>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 
379
CLASS="STRUCTFIELD"
380
>
381
>event.jaxis.axis
382
>
383
> values.
384
>
385
>Button handling is simple compared to the axis checking.
386
>
387
CLASS="EXAMPLE"
388
>
389
NAME="AEN203"
390
>
391
>
392
>
393
>Example 3-6. Joystick Button Events
394
>
395
>
396
CLASS="PROGRAMLISTING"
397
>    case SDL_JOYBUTTONDOWN:  /* Handle Joystick Button Presses */
398
    if ( event.jbutton.button == 0 )
399
    {
400
        /* code goes here */
401
    }
402
    break;
403
>
404
>
405
>Button checks are simpler than axis checks because a button can only be pressed or not pressed.  The 
406
CLASS="LITERAL"
407
>SDL_JOYBUTTONDOWN
408
> event is triggered when a button is pressed and the 
409
CLASS="LITERAL"
410
>SDL_JOYBUTTONUP
411
> event is fired when a button is released. We do have to know what button was pressed though, that is done by reading the 
412
CLASS="STRUCTFIELD"
413
>
414
>event.jbutton.button
415
>
416
> field.
417
>
418
>Lastly when we are through using our joysticks we should close them with a call to 
419
HREF="sdljoystickclose.html"
420
>
421
CLASS="FUNCTION"
422
>SDL_JoystickClose
423
>
424
>. To close our opened joystick 0 we would do this at the end of our program:
425
426
CLASS="PROGRAMLISTING"
427
>    SDL_JoystickClose(joystick);
428
>
429
>
430
>
431
CLASS="SECT2"
432
>
433
CLASS="SECT2"
434
>
435
NAME="AEN214"
436
>Advanced Joystick Functions
437
>
438
>
439
>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:
440
>
441
CLASS="EXAMPLE"
442
>
443
NAME="AEN217"
444
>
445
>
446
>
447
>Example 3-7. Joystick Ball Events
448
>
449
>
450
CLASS="PROGRAMLISTING"
451
>    case SDL_JOYBALLMOTION:  /* Handle Joyball Motion */
452
    if( event.jball.ball == 0 )
453
    {
454
      /* ball handling */
455
    }
456
    break;
457
>
458
>
459
>The above checks the first joyball on the joystick. The change in position will be stored in 
460
CLASS="STRUCTFIELD"
461
>
462
>event.jball.xrel
463
>
464
> and 
465
CLASS="STRUCTFIELD"
466
>
467
>event.jball.yrel
468
>
469
>.
470
>
471
>Finally we have the hat event. Hats report only the direction they are pushed in. We check hat's position with the bitmasks:
472
 
473
474
>
475
>
476
BORDER="0"
477
>
478
>
479
>
480
>
481
CLASS="LITERAL"
482
>SDL_HAT_CENTERED
483
>
484
>
485
>
486
>
487
>
488
CLASS="LITERAL"
489
>SDL_HAT_UP
490
>
491
>
492
>
493
>
494
>
495
CLASS="LITERAL"
496
>SDL_HAT_RIGHT
497
>
498
>
499
>
500
>
501
>
502
CLASS="LITERAL"
503
>SDL_HAT_DOWN
504
>
505
>
506
>
507
>
508
>
509
CLASS="LITERAL"
510
>SDL_HAT_LEFT
511
>
512
>
513
>
514
>
515
>
516
>
517
>
518
 
519
Also there are some predefined combinations of the above:
520
521
>
522
>
523
BORDER="0"
524
>
525
>
526
>
527
>
528
CLASS="LITERAL"
529
>SDL_HAT_RIGHTUP
530
>
531
>
532
>
533
>
534
>
535
CLASS="LITERAL"
536
>SDL_HAT_RIGHTDOWN
537
>
538
>
539
>
540
>
541
>
542
CLASS="LITERAL"
543
>SDL_HAT_LEFTUP
544
>
545
>
546
>
547
>
548
>
549
CLASS="LITERAL"
550
>SDL_HAT_LEFTDOWN
551
>
552
>
553
>
554
>
555
>
556
>
557
>
558
 
559
Our case for the hat may resemble the following:
560
>
561
CLASS="EXAMPLE"
562
>
563
NAME="AEN244"
564
>
565
>
566
>
567
>Example 3-8. Joystick Hat Events
568
>
569
>
570
CLASS="PROGRAMLISTING"
571
>    case SDL_JOYHATMOTION:  /* Handle Hat Motion */
572
    if ( event.jhat.hat | SDL_HAT_UP )
573
    {
574
        /* Do up stuff here */
575
    }
576
 
577
    if ( event.jhat.hat | SDL_HAT_LEFT )
578
    {
579
        /* Do left stuff here */
580
    }
581
 
582
    if ( event.jhat.hat | SDL_HAT_RIGHTDOWN )
583
    {
584
        /* Do right and down together stuff here */
585
    }
586
    break;
587
>
588
>
589
>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:
590
591
>
592
>
593
BORDER="0"
594
>
595
>
596
>
597
>
598
HREF="sdljoysticknumaxes.html"
599
>
600
CLASS="FUNCTION"
601
>SDL_JoystickNumAxes
602
>
603
>
604
>
605
>Returns the number of joysitck axes
606
>
607
>
608
>
609
>
610
HREF="sdljoysticknumbuttons.html"
611
>
612
CLASS="FUNCTION"
613
>SDL_JoystickNumButtons
614
>
615
>
616
>
617
>Returns the number of joysitck buttons
618
>
619
>
620
>
621
>
622
HREF="sdljoysticknumballs.html"
623
>
624
CLASS="FUNCTION"
625
>SDL_JoystickNumBalls
626
>
627
>
628
>
629
>Returns the number of joysitck balls
630
>
631
>
632
>
633
>
634
HREF="sdljoysticknumhats.html"
635
>
636
CLASS="FUNCTION"
637
>SDL_JoystickNumHats
638
>
639
>
640
>
641
>Returns the number of joysitck hats
642
>
643
>
644
>
645
>
646
>
647
>
648
 
649
To use these functions we just have to pass in the joystick structure we got when we opened the joystick. For Example:
650
>
651
CLASS="EXAMPLE"
652
>
653
NAME="AEN265"
654
>
655
>
656
>
657
>Example 3-9. Querying Joystick Characteristics
658
>
659
>
660
CLASS="PROGRAMLISTING"
661
>    int number_of_buttons;
662
    SDL_Joystick *joystick;
663
 
664
    joystick = SDL_JoystickOpen(0);
665
    number_of_buttons = SDL_JoystickNumButtons(joystick);
666
>
667
>
668
>This block of code would get the number of buttons on the first joystick in the system.	
669
>
670
>
671
>
672
>
673
CLASS="NAVFOOTER"
674
>
675
ALIGN="LEFT"
676
WIDTH="100%">
677
WIDTH="100%"
678
BORDER="0"
679
CELLPADDING="0"
680
CELLSPACING="0"
681
>
682
>
683
WIDTH="33%"
684
ALIGN="left"
685
VALIGN="top"
686
>
687
HREF="guidevideoopengl.html"
688
>Prev
689
>
690
>
691
WIDTH="34%"
692
ALIGN="center"
693
VALIGN="top"
694
>
695
HREF="index.html"
696
>Home
697
>
698
>
699
WIDTH="33%"
700
ALIGN="right"
701
VALIGN="top"
702
>
703
HREF="guideinputkeyboard.html"
704
>Next
705
>
706
>
707
>
708
>
709
WIDTH="33%"
710
ALIGN="left"
711
VALIGN="top"
712
>Using OpenGL With SDL
713
>
714
WIDTH="34%"
715
ALIGN="center"
716
VALIGN="top"
717
>
718
HREF="guide.html"
719
>Up
720
>
721
>
722
WIDTH="33%"
723
ALIGN="right"
724
VALIGN="top"
725
>Handling the Keyboard
726
>
727
>
728
>
729
>
730
>
731
>