Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. <HTML
  2. ><HEAD
  3. ><TITLE
  4. >Input handling</TITLE
  5. ><META
  6. NAME="GENERATOR"
  7. CONTENT="Modular DocBook HTML Stylesheet Version 1.64
  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="Using OpenGL With SDL"
  17. HREF="guidevideoopengl.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="guidevideoopengl.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="AEN135"
  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.</P
  121. ><DIV
  122. CLASS="EXAMPLE"
  123. ><A
  124. NAME="AEN141"
  125. ></A
  126. ><P
  127. ><B
  128. >Example 3-1. Initializing SDL with Joystick Support</B
  129. ></P
  130. ><PRE
  131. CLASS="PROGRAMLISTING"
  132. >    if (SDL_Init( SDL_INIT_VIDEO | SDL_INIT_JOYSTICK ) &#60; 0)
  133.     {
  134.         fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
  135.         exit(1);
  136.     }</PRE
  137. ></DIV
  138. ><P
  139. >This will attempt to start SDL with both the video and the joystick subsystems activated.</P
  140. ></DIV
  141. ><DIV
  142. CLASS="SECT2"
  143. ><H2
  144. CLASS="SECT2"
  145. ><A
  146. NAME="AEN145"
  147. >Querying</A
  148. ></H2
  149. ><P
  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 <A
  151. HREF="sdlnumjoysticks.html"
  152. ><TT
  153. CLASS="FUNCTION"
  154. >SDL_NumJoysticks</TT
  155. ></A
  156. >.</P
  157. ><P
  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 <A
  159. HREF="sdljoystickname.html"
  160. ><TT
  161. CLASS="FUNCTION"
  162. >SDL_JoystickName</TT
  163. ></A
  164. >.  The joystick is specified by an index where 0 is the first joystick and the last joystick is the number returned by <TT
  165. CLASS="FUNCTION"
  166. >SDL_NumJoysticks</TT
  167. > - 1.  In the demonstration a list of all available joysticks is printed to stdout.</P
  168. ><DIV
  169. CLASS="EXAMPLE"
  170. ><A
  171. NAME="AEN154"
  172. ></A
  173. ><P
  174. ><B
  175. >Example 3-2. Querying the Number of Available Joysticks</B
  176. ></P
  177. ><PRE
  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 &#60; SDL_NumJoysticks(); i++ )
  183.    {
  184.        printf("    %s\n", SDL_JoystickName(i));
  185.    }</PRE
  186. ></DIV
  187. ></DIV
  188. ><DIV
  189. CLASS="SECT2"
  190. ><H2
  191. CLASS="SECT2"
  192. ><A
  193. NAME="AEN157"
  194. >Opening a Joystick and Receiving Joystick Events</A
  195. ></H2
  196. ><P
  197. >SDL's event driven architecture makes working with joysticks a snap.  Joysticks can trigger 4 different types of events:
  198. <P
  199. ></P
  200. ><TABLE
  201. BORDER="0"
  202. ><TBODY
  203. ><TR
  204. ><TD
  205. ><A
  206. HREF="sdljoyaxisevent.html"
  207. ><SPAN
  208. CLASS="STRUCTNAME"
  209. >SDL_JoyAxisEvent</SPAN
  210. ></A
  211. ></TD
  212. ><TD
  213. >Occurs when an axis changes</TD
  214. ></TR
  215. ><TR
  216. ><TD
  217. ><A
  218. HREF="sdljoyballevent.html"
  219. ><SPAN
  220. CLASS="STRUCTNAME"
  221. >SDL_JoyBallEvent</SPAN
  222. ></A
  223. ></TD
  224. ><TD
  225. >Occurs when a joystick trackball's position changes</TD
  226. ></TR
  227. ><TR
  228. ><TD
  229. ><A
  230. HREF="sdljoyhatevent.html"
  231. ><SPAN
  232. CLASS="STRUCTNAME"
  233. >SDL_JoyHatEvent</SPAN
  234. ></A
  235. ></TD
  236. ><TD
  237. >Occurs when a hat's position changes</TD
  238. ></TR
  239. ><TR
  240. ><TD
  241. ><A
  242. HREF="sdljoybuttonevent.html"
  243. ><SPAN
  244. CLASS="STRUCTNAME"
  245. >SDL_JoyButtonEvent</SPAN
  246. ></A
  247. ></TD
  248. ><TD
  249. >Occurs when a button is pressed or released</TD
  250. ></TR
  251. ></TBODY
  252. ></TABLE
  253. ><P
  254. ></P
  255. ></P
  256. ><P
  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 <A
  258. HREF="sdljoystickeventstate.html"
  259. ><TT
  260. CLASS="FUNCTION"
  261. >SDL_JoystickEventState</TT
  262. ></A
  263. > with the <TT
  264. CLASS="LITERAL"
  265. >SDL_ENABLE</TT
  266. > flag. Next you must open the joysticks that you want to receive envents from. This is done with the <A
  267. HREF="sdljoystickopen.html"
  268. ><TT
  269. CLASS="FUNCTION"
  270. >SDL_JoystickOpen</TT
  271. ></A
  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:</P
  273. ><DIV
  274. CLASS="EXAMPLE"
  275. ><A
  276. NAME="AEN183"
  277. ></A
  278. ><P
  279. ><B
  280. >Example 3-3. Opening a Joystick</B
  281. ></P
  282. ><PRE
  283. CLASS="PROGRAMLISTING"
  284. >    SDL_Joystick *joystick;
  285.  
  286.     SDL_JoystickEventState(SDL_ENABLE);
  287.     joystick = SDL_JoystickOpen(0);</PRE
  288. ></DIV
  289. ><P
  290. >If we wanted to receive events for other joysticks we would open them with calls to <TT
  291. CLASS="FUNCTION"
  292. >SDL_JoystickOpen</TT
  293. > just like we opened joystick 0, except we would store the <SPAN
  294. CLASS="STRUCTNAME"
  295. >SDL_Joystick</SPAN
  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.</P
  297. ><P
  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. <PRE
  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(&#38;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 */</PRE
  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:</P
  324. ><DIV
  325. CLASS="EXAMPLE"
  326. ><A
  327. NAME="AEN191"
  328. ></A
  329. ><P
  330. ><B
  331. >Example 3-4. Joystick Axis Events</B
  332. ></P
  333. ><PRE
  334. CLASS="PROGRAMLISTING"
  335. >    case SDL_JOYAXISMOTION:  /* Handle Joystick Motion */
  336.    if ( ( event.jaxis.value &#60; -3200 ) || (event.jaxis.value &#62; 3200 ) )
  337.    {
  338.      /* code goes here */
  339.    }
  340.    break;</PRE
  341. ></DIV
  342. ><P
  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:</P
  344. ><DIV
  345. CLASS="EXAMPLE"
  346. ><A
  347. NAME="AEN195"
  348. ></A
  349. ><P
  350. ><B
  351. >Example 3-5. More Joystick Axis Events</B
  352. ></P
  353. ><PRE
  354. CLASS="PROGRAMLISTING"
  355. >    case SDL_JOYAXISMOTION:  /* Handle Joystick Motion */
  356.    if ( ( event.jaxis.value &#60; -3200 ) || (event.jaxis.value &#62; 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;</PRE
  369. ></DIV
  370. ><P
  371. >Ideally the code here should use <TT
  372. CLASS="STRUCTFIELD"
  373. ><I
  374. >event.jaxis.value</I
  375. ></TT
  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.</P
  377. ><P
  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 <TT
  379. CLASS="STRUCTFIELD"
  380. ><I
  381. >event.jaxis.axis</I
  382. ></TT
  383. > values.</P
  384. ><P
  385. >Button handling is simple compared to the axis checking.</P
  386. ><DIV
  387. CLASS="EXAMPLE"
  388. ><A
  389. NAME="AEN203"
  390. ></A
  391. ><P
  392. ><B
  393. >Example 3-6. Joystick Button Events</B
  394. ></P
  395. ><PRE
  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;</PRE
  403. ></DIV
  404. ><P
  405. >Button checks are simpler than axis checks because a button can only be pressed or not pressed.  The <TT
  406. CLASS="LITERAL"
  407. >SDL_JOYBUTTONDOWN</TT
  408. > event is triggered when a button is pressed and the <TT
  409. CLASS="LITERAL"
  410. >SDL_JOYBUTTONUP</TT
  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 <TT
  412. CLASS="STRUCTFIELD"
  413. ><I
  414. >event.jbutton.button</I
  415. ></TT
  416. > field.</P
  417. ><P
  418. >Lastly when we are through using our joysticks we should close them with a call to <A
  419. HREF="sdljoystickclose.html"
  420. ><TT
  421. CLASS="FUNCTION"
  422. >SDL_JoystickClose</TT
  423. ></A
  424. >. To close our opened joystick 0 we would do this at the end of our program:
  425. <PRE
  426. CLASS="PROGRAMLISTING"
  427. >    SDL_JoystickClose(joystick);</PRE
  428. ></P
  429. ></DIV
  430. ><DIV
  431. CLASS="SECT2"
  432. ><H2
  433. CLASS="SECT2"
  434. ><A
  435. NAME="AEN214"
  436. >Advanced Joystick Functions</A
  437. ></H2
  438. ><P
  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:</P
  440. ><DIV
  441. CLASS="EXAMPLE"
  442. ><A
  443. NAME="AEN217"
  444. ></A
  445. ><P
  446. ><B
  447. >Example 3-7. Joystick Ball Events</B
  448. ></P
  449. ><PRE
  450. CLASS="PROGRAMLISTING"
  451. >    case SDL_JOYBALLMOTION:  /* Handle Joyball Motion */
  452.    if( event.jball.ball == 0 )
  453.    {
  454.      /* ball handling */
  455.    }
  456.    break;</PRE
  457. ></DIV
  458. ><P
  459. >The above checks the first joyball on the joystick. The change in position will be stored in <TT
  460. CLASS="STRUCTFIELD"
  461. ><I
  462. >event.jball.xrel</I
  463. ></TT
  464. > and <TT
  465. CLASS="STRUCTFIELD"
  466. ><I
  467. >event.jball.yrel</I
  468. ></TT
  469. >.</P
  470. ><P
  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. <P
  474. ></P
  475. ><TABLE
  476. BORDER="0"
  477. ><TBODY
  478. ><TR
  479. ><TD
  480. ><TT
  481. CLASS="LITERAL"
  482. >SDL_HAT_CENTERED</TT
  483. ></TD
  484. ></TR
  485. ><TR
  486. ><TD
  487. ><TT
  488. CLASS="LITERAL"
  489. >SDL_HAT_UP</TT
  490. ></TD
  491. ></TR
  492. ><TR
  493. ><TD
  494. ><TT
  495. CLASS="LITERAL"
  496. >SDL_HAT_RIGHT</TT
  497. ></TD
  498. ></TR
  499. ><TR
  500. ><TD
  501. ><TT
  502. CLASS="LITERAL"
  503. >SDL_HAT_DOWN</TT
  504. ></TD
  505. ></TR
  506. ><TR
  507. ><TD
  508. ><TT
  509. CLASS="LITERAL"
  510. >SDL_HAT_LEFT</TT
  511. ></TD
  512. ></TR
  513. ></TBODY
  514. ></TABLE
  515. ><P
  516. ></P
  517. >
  518.  
  519. Also there are some predefined combinations of the above:
  520. <P
  521. ></P
  522. ><TABLE
  523. BORDER="0"
  524. ><TBODY
  525. ><TR
  526. ><TD
  527. ><TT
  528. CLASS="LITERAL"
  529. >SDL_HAT_RIGHTUP</TT
  530. ></TD
  531. ></TR
  532. ><TR
  533. ><TD
  534. ><TT
  535. CLASS="LITERAL"
  536. >SDL_HAT_RIGHTDOWN</TT
  537. ></TD
  538. ></TR
  539. ><TR
  540. ><TD
  541. ><TT
  542. CLASS="LITERAL"
  543. >SDL_HAT_LEFTUP</TT
  544. ></TD
  545. ></TR
  546. ><TR
  547. ><TD
  548. ><TT
  549. CLASS="LITERAL"
  550. >SDL_HAT_LEFTDOWN</TT
  551. ></TD
  552. ></TR
  553. ></TBODY
  554. ></TABLE
  555. ><P
  556. ></P
  557. >
  558.  
  559. Our case for the hat may resemble the following:</P
  560. ><DIV
  561. CLASS="EXAMPLE"
  562. ><A
  563. NAME="AEN244"
  564. ></A
  565. ><P
  566. ><B
  567. >Example 3-8. Joystick Hat Events</B
  568. ></P
  569. ><PRE
  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;</PRE
  587. ></DIV
  588. ><P
  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. <P
  591. ></P
  592. ><TABLE
  593. BORDER="0"
  594. ><TBODY
  595. ><TR
  596. ><TD
  597. ><A
  598. HREF="sdljoysticknumaxes.html"
  599. ><TT
  600. CLASS="FUNCTION"
  601. >SDL_JoystickNumAxes</TT
  602. ></A
  603. ></TD
  604. ><TD
  605. >Returns the number of joysitck axes</TD
  606. ></TR
  607. ><TR
  608. ><TD
  609. ><A
  610. HREF="sdljoysticknumbuttons.html"
  611. ><TT
  612. CLASS="FUNCTION"
  613. >SDL_JoystickNumButtons</TT
  614. ></A
  615. ></TD
  616. ><TD
  617. >Returns the number of joysitck buttons</TD
  618. ></TR
  619. ><TR
  620. ><TD
  621. ><A
  622. HREF="sdljoysticknumballs.html"
  623. ><TT
  624. CLASS="FUNCTION"
  625. >SDL_JoystickNumBalls</TT
  626. ></A
  627. ></TD
  628. ><TD
  629. >Returns the number of joysitck balls</TD
  630. ></TR
  631. ><TR
  632. ><TD
  633. ><A
  634. HREF="sdljoysticknumhats.html"
  635. ><TT
  636. CLASS="FUNCTION"
  637. >SDL_JoystickNumHats</TT
  638. ></A
  639. ></TD
  640. ><TD
  641. >Returns the number of joysitck hats</TD
  642. ></TR
  643. ></TBODY
  644. ></TABLE
  645. ><P
  646. ></P
  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:</P
  650. ><DIV
  651. CLASS="EXAMPLE"
  652. ><A
  653. NAME="AEN265"
  654. ></A
  655. ><P
  656. ><B
  657. >Example 3-9. Querying Joystick Characteristics</B
  658. ></P
  659. ><PRE
  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);</PRE
  666. ></DIV
  667. ><P
  668. >This block of code would get the number of buttons on the first joystick in the system.        </P
  669. ></DIV
  670. ></DIV
  671. ></DIV
  672. ><DIV
  673. CLASS="NAVFOOTER"
  674. ><HR
  675. ALIGN="LEFT"
  676. WIDTH="100%"><TABLE
  677. WIDTH="100%"
  678. BORDER="0"
  679. CELLPADDING="0"
  680. CELLSPACING="0"
  681. ><TR
  682. ><TD
  683. WIDTH="33%"
  684. ALIGN="left"
  685. VALIGN="top"
  686. ><A
  687. HREF="guidevideoopengl.html"
  688. >Prev</A
  689. ></TD
  690. ><TD
  691. WIDTH="34%"
  692. ALIGN="center"
  693. VALIGN="top"
  694. ><A
  695. HREF="index.html"
  696. >Home</A
  697. ></TD
  698. ><TD
  699. WIDTH="33%"
  700. ALIGN="right"
  701. VALIGN="top"
  702. ><A
  703. HREF="guideinputkeyboard.html"
  704. >Next</A
  705. ></TD
  706. ></TR
  707. ><TR
  708. ><TD
  709. WIDTH="33%"
  710. ALIGN="left"
  711. VALIGN="top"
  712. >Using OpenGL With SDL</TD
  713. ><TD
  714. WIDTH="34%"
  715. ALIGN="center"
  716. VALIGN="top"
  717. ><A
  718. HREF="guide.html"
  719. >Up</A
  720. ></TD
  721. ><TD
  722. WIDTH="33%"
  723. ALIGN="right"
  724. VALIGN="top"
  725. >Handling the Keyboard</TD
  726. ></TR
  727. ></TABLE
  728. ></DIV
  729. ></BODY
  730. ></HTML
  731. >