home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff247.lzh / AnalogJoystick / JoyDemo.c < prev    next >
C/C++ Source or Header  |  1989-09-15  |  15KB  |  427 lines

  1.  
  2.  
  3. /*********************************************************/
  4. /*                                                       */
  5. /*             ANALOG JOYSTICK DEMO                      */
  6. /*                                                       */
  7. /* Copyright (c) 1989, David Kinzer, All Rights Reserved */
  8. /*                                                       */
  9. /* Permission hereby granted to redistribute this        */
  10. /* program in unmodified form in a not for profit manner.*/
  11. /*                                                       */
  12. /* Permission hereby granted to use this software freely */
  13. /* in programs, commercial or not.                       */
  14. /*                                                       */
  15. /*********************************************************/
  16. /*                                                       */
  17. /* JoyDemo.c                                             */
  18. /*                                                       */
  19. /*    This program demonstrates the use of an Analog     */
  20. /* Joystick input device on the Amiga (tm) Computer.     */
  21. /* This program also demonstrates the use of libraries,  */
  22. /* screens, and windows.                                 */
  23. /*                                                       */
  24. /*                                                       */
  25. /*********************************************************/
  26.  
  27.  
  28. /* The following includes some header files which define
  29.    some types and structures used by this program.  Note
  30.    that these include files will themselves include more
  31.    files so that everything they need is also included.  */
  32.  
  33. #include <exec/types.h>
  34. #include <exec/memory.h>
  35. #include <intuition/intuition.h>
  36.  
  37. /* Include our own defines for the Joystick portion of
  38.    the program. The use of quotes around the include
  39.    file name tells the compiler to  look in the current
  40.    directory for the specified file.  If not found, the
  41.    compiler will look in the default library.            */
  42.  
  43. #include "ajoystick.h"
  44.  
  45. /* The following variables are required to use the
  46.    libraries.  The libraries are loaded into ram so many
  47.    programs can use them at the same time.   This
  48.    reduces duplication and therefore reduces the ammount
  49.    of ram needed for multitasking.  These variables are
  50.    pointers to the base of the library entry point.  They
  51.    must be global variables so the 'C' library routines
  52.    (which call the actual Amiga library routines) can
  53.    find them during the linking process.  The 'C' library
  54.    routine adds an offset to this pointer and goes to the
  55.    subroutine located there.                             */
  56.  
  57. struct IntuitionBase *IntuitionBase;
  58. struct GfxBase *GfxBase;
  59.  
  60. /* The following will be used during the open library to
  61.    ask for a particular revision or greater in the
  62.    library.  A value of Zero says open any revision.
  63.    This would be useful if you used one of the new version
  64.    1.2 routines which did not exist in V1.1.  If you
  65.    were to call a non-existant routine, the system will 
  66.    crash.                                                */
  67.  
  68. #define INTUITION_REV 0L
  69. #define GRAPHICS_REV 0L
  70.  
  71. /* Here we define the height of the title bar on a
  72.    window so our program will be able to skip over
  73.    that space, as well as the width of the  window
  74.    boarders.                                            */
  75.  
  76. #define TITLEHEIGHT 10L
  77. #define BOTTOMWIDTH 1L
  78. #define LEFTWIDTH   2L
  79. #define RIGHTWIDTH  2L
  80.  
  81. /* Here is where we will define the font that we will
  82.    use for our display.  It defines the font that will
  83.    be used by the text function for rendering in any
  84.    window on our screen.                                */
  85.  
  86. struct TextAttr MyFont =
  87.    {
  88.    (STRPTR)"topaz.font",  /* Font Name */
  89.    TOPAZ_EIGHTY,        /* Font Height */
  90.    FS_NORMAL,          /* Style */
  91.    FPF_ROMFONT,         /* Preferences */
  92.    };
  93.  
  94. /* Next we set up the data structure which opens the
  95.    screen.  Notice we include the address of our font
  96.    structure in this structure.                          */
  97.  
  98. struct NewScreen OurScreen =
  99.    {
  100.    0,                /* the left edge has to be zero     */
  101.    0,                /* top edge, start at top of screen */
  102.    640,              /* Width, we want High Resolution   */
  103.    200,              /* Height, we want non-interlace    */
  104.    2,                /* Depth, Two Planes, 4 colors      */
  105.    0,1,              /* DetailPen and BlockPen specs     */
  106.    HIRES,            /* Let's go for High Res            */
  107.    CUSTOMSCREEN,     /* screen type, not the Workbench   */
  108.    &MyFont,          /* use the font we said to          */
  109.    (STRPTR)"Joystick Screen",/* Screen name, in title bar*/
  110.    NULL,             /* screen gadget                    */
  111.    NULL,             /* No custom Bitmap                 */
  112.    };
  113.  
  114.  
  115. /* OK, here comes the program.                           */
  116.  
  117. VOID main()
  118. {
  119. /* The following are used to open the screen and window. */
  120. struct Screen *Screen_ptr;
  121. struct NewWindow OurWindow;
  122. struct Window *Window_ptr;
  123.  
  124. /* The following variables are used in the demo loop.    */
  125. struct AJoyData *JP;
  126. long pcolor;
  127. struct message *msgptr = NULL;
  128. long old_x = -1; 
  129. long old_y = -1;
  130. long old_color = 0;
  131.  
  132. /* Declare the return type of the functions used.       */
  133. APTR OpenLibrary(),OpenScreen(),OpenWindow();
  134. APTR AllocMem(),GetMsg();
  135.  
  136. /* Declare our function to keep Lattice (tm) happy.     */
  137. VOID DrawBox();
  138.  
  139.  
  140. /* Open the Intuition library.  The result returned by
  141.    this call is a pointer to the jump table of the
  142.    Intuition library.  This call will load the library
  143.    from disk if it is not already loaded.  If this call
  144.    returns zero, something is wrong and Intuition is
  145.    not available to us.  If this is true, attempting to
  146.    use the library will cause the machine to crash, so
  147.    we should exit the program.                          */
  148.  
  149.    IntuitionBase = (struct IntuitionBase *) OpenLibrary(
  150.              (STRPTR)"intuition.library",INTUITION_REV);
  151.    if (IntuitionBase == NULL)
  152.       exit(FALSE);
  153.  
  154. /* Same with the Graphics Library */
  155.  
  156.    GfxBase = (struct GfxBase *)OpenLibrary((STRPTR)
  157.                "graphics.library",GRAPHICS_REV);
  158.    if (GfxBase == NULL)
  159.       exit(FALSE);
  160.  
  161.  
  162. /* Now it is time to get our screen.  The OpenScreen call
  163.    does a bunch of neat stuff for us like getting chip
  164.    memory for the screen and RastPort structures.  We
  165.    could do all this stuff for ourselves, but why?       */
  166.  
  167.    Screen_ptr = (struct Screen *)OpenScreen(&OurScreen);
  168.    if (Screen_ptr == NULL)
  169.       exit(FALSE);
  170.  
  171.  
  172. /* We are going to fill out the window structure in order
  173.    so we can open a window on our new screen.  Our window
  174.    will have a few gadgets for us to play with.  Since
  175.    one of the IDCMP flags is set, this program will open
  176.    a message port which we will monitor to see when the
  177.    window should be closed.                              */
  178.  
  179.    OurWindow.LeftEdge = 20;
  180.    OurWindow.TopEdge = 20;
  181.    OurWindow.Width = 512+LEFTWIDTH+RIGHTWIDTH;
  182.    OurWindow.Height = 128+TITLEHEIGHT+BOTTOMWIDTH;
  183.    OurWindow.DetailPen = 0;
  184.    OurWindow.BlockPen = 1;
  185.    OurWindow.Title = (STRPTR)"Joystick Drawing Window";
  186.    OurWindow.Flags = WINDOWCLOSE | SMART_REFRESH
  187.                      | ACTIVATE  | WINDOWDRAG
  188.                      | WINDOWDEPTH | NOCAREREFRESH;
  189.    OurWindow.IDCMPFlags = CLOSEWINDOW;
  190.    OurWindow.Type = CUSTOMSCREEN;
  191.    OurWindow.FirstGadget = NULL;
  192.    OurWindow.CheckMark = NULL;
  193.    OurWindow.Screen = Screen_ptr;
  194.    OurWindow.BitMap = NULL;
  195.    OurWindow.MinWidth = 512+LEFTWIDTH+RIGHTWIDTH;
  196.    OurWindow.MinHeight = 128+TITLEHEIGHT+BOTTOMWIDTH;
  197.    OurWindow.MaxWidth = 512+LEFTWIDTH+RIGHTWIDTH;
  198.    OurWindow.MaxHeight = 128+TITLEHEIGHT+BOTTOMWIDTH;
  199.  
  200. /* Now open the window on our screen. */
  201.  
  202.    Window_ptr = (struct Window *)OpenWindow(&OurWindow);
  203.    if (Window_ptr == NULL)
  204.       exit(FALSE);
  205.  
  206. /* Move the graphics pen (an imaginary thing) to where
  207.    we would like our text to be drawn.                   */
  208.  
  209.    Move(Window_ptr->RPort,20L,20L);
  210.  
  211. /* Now let's send some text out to the screen */
  212.  
  213.    Text(Window_ptr->RPort,(STRPTR)"Joystick Draw",13L);
  214.  
  215. /* Let's outline the text with a box, this is our own
  216.    function                                              */
  217.  
  218.    DrawBox(Window_ptr->RPort,1,12,22,16,128);
  219.  
  220. /*                                                      */
  221. /* Now we get to the Analog Joystick part.              */
  222. /*                                                      */
  223.  
  224.  
  225. /* Define some conversion functions that change the
  226.    0-255 input values into the coordinates for drawing
  227.    into our window.                                     */
  228.  
  229. #define fx(x) (x / 128 + LEFTWIDTH)
  230. #define fy(y) (y / 512 + TITLEHEIGHT)
  231.  
  232. /* Allocate some public memory for a data structure that
  233.    the ReadAJoystick will return the data to us in.  It
  234.    is not necessary for this to be public for this
  235.    example program since we are linking the driver with
  236.    our program, but should this become a library, this
  237.    would be required. (It doesn't hurt to think ahead
  238.    some.)                                               */
  239.  
  240.    JP = (struct AJoyData *)AllocMem((long)sizeof
  241.            (struct AJoyData),MEMF_PUBLIC);
  242.  
  243. /* Continue only if the allocate worked.                */
  244.  
  245.    if (JP) {
  246.  
  247. /* Call the open routine of our driver.  We are
  248.    requesting Unit 1 (the  right mouse port), and we
  249.    want it to give us a single pressed indication for
  250.    each time button 2 is pressed. (This means button
  251.    1 [as well as 3 and 4 if your joystick is so
  252.    equipped] will report pressed as long as the user
  253.    holds it down.)                                      */
  254.  
  255.       if (OpenAJoystick(AJOYUNIT1 | U1B2SINGLE)) {
  256.  
  257. /* Set the graphics pen to color 1 (actual color
  258.    depends upon preferences)                            */
  259.  
  260.          pcolor = 1;
  261.          SetAPen(Window_ptr->RPort,pcolor);
  262.  
  263. /* Loop until user clicks close box on the window.      */
  264.  
  265.          do {
  266.  
  267. /* Read settings of the Analog joystick and buttons.    */
  268.  
  269.             ReadAJoystick(AJOYUNIT1,JP);
  270.  
  271. /* Check button 2.  Button 2 indicates the user wants
  272.    to change the color that he is drawing with.  Note
  273.    that if we had not specified U1B2SINGLE on the open
  274.    call, the color would cycle as long as the user held
  275.    the button down.  This would make it difficult for
  276.    him or her to select a color.  If the button is
  277.    pressed, change the color variable and write the
  278.    new color on the display.                           */
  279.  
  280.             if (JP->button2 != BUTTONUP) {
  281.                pcolor = (pcolor+1) % 4;
  282.                SetAPen(Window_ptr->RPort,pcolor);
  283.                WritePixel(Window_ptr->RPort,old_x,old_y);
  284.                WritePixel(Window_ptr->RPort,old_x+1,old_y);
  285.             }
  286.  
  287. /* If the joystick position has moved, we need to decide
  288.    if are to clean up the screen where we were drawing. 
  289.    If the button is pressed, we leave the current color
  290.    on the screen.  This is done in conjunction with the
  291.    statement below.  If the old color matches the current
  292.    color, we just leave it.  If it does not match, we
  293.    replace it with the color that used to be there.  We
  294.    then move to the new position, save the color that
  295.    was there, and write out the new color.              */
  296.  
  297.             if ((fx(JP->x) != old_x) ||
  298.                   (fy(JP->y) != old_y)) {
  299.                if (pcolor != old_color) {
  300.                   SetAPen(Window_ptr->RPort,old_color);
  301.                   WritePixel(Window_ptr->RPort,old_x,
  302.                      old_y);
  303.                   WritePixel(Window_ptr->RPort,old_x+1,
  304.                      old_y);
  305.                   SetAPen(Window_ptr->RPort,pcolor);
  306.                }
  307.                old_x = fx(JP->x);
  308.                old_y = fy(JP->y);
  309.                old_color = ReadPixel(Window_ptr->RPort,
  310.                   old_x,old_y);
  311.  
  312.                WritePixel(Window_ptr->RPort,old_x,old_y);
  313.                WritePixel(Window_ptr->RPort,old_x+1,old_y);
  314.             }
  315.  
  316. /* If button 1 is pressed, the user wants to draw in the
  317.    window.  As long as the button is held, points will
  318.    change to the current color.  We do this by changing
  319.    the saved color to the current color so when the
  320.    joystick is moved the color is retained.              */
  321.  
  322.             if (JP->button1 != BUTTONUP) {
  323.                old_color = pcolor;
  324.             }
  325.  
  326. /* Check for any messages coming in to our program.  The
  327.    GetMsg routine returns a pointer to the first message
  328.    in the queue, if any.  If there are no messages, it
  329.    returns a NULL.                                      */ 
  330.  
  331.          } while (!(msgptr = (struct message *)
  332.             GetMsg(Window_ptr->UserPort)));
  333.  
  334. /* We looped until a message arrived at the IDCMP port.
  335.    Since we only asked for one type of message, we are
  336.    assured that it is the close window message.  If we
  337.    had asked for more types, we would have to decode it
  338.    to see what type of message it is.  For our case, we
  339.    just reply the  message, clean up, and we're done.  */
  340.  
  341.          ReplyMsg(msgptr);
  342.   
  343. /* Turn off the joystick routines.                     */
  344.  
  345.          CloseAJoystick();
  346.       }
  347.  
  348. /* Free up the memory we allocated for our data
  349.    structure.                                          */
  350.  
  351.       FreeMem(JP,(long)sizeof(struct AJoyData));
  352.  
  353.    }
  354.    
  355.  
  356. /* Close up the window, and then the screen.  Then we
  357.    are done.                                           */
  358.  
  359.    CloseWindow(Window_ptr);
  360.    CloseScreen(Screen_ptr);
  361.  
  362.    exit(TRUE);
  363.  
  364. }
  365.  
  366.  
  367. /* Here we have our own function which draws a box on 
  368.    the screen.  It calls an Amiga function called
  369.    PolyDraw which draws polygons on the display area.
  370.    We change the color of the pen to what is desired,
  371.    draw the box and set it back.  We also preserve the
  372.    graphics pen location.                              */
  373.  
  374.  
  375. VOID DrawBox(RP,PenColor,Top,Bottom,Left,Right)
  376.  
  377. struct RastPort *RP;
  378. int PenColor,Top,Bottom,Left,Right;
  379.  
  380. {
  381. int OldPenColor,x,y;
  382. short points[4][2];
  383.  
  384. /* Fill in the points of our box polygon that will
  385.    be used by the DrawPoly function.   The array must
  386.    be made up of 16 bit numbers.                      */
  387.  
  388.    points [3][0] = Left;
  389.    points [3][1] = Top;
  390.    points [0][0] = Right;
  391.    points [0][1] = Top;
  392.    points [1][0] = Right;
  393.    points [1][1] = Bottom;
  394.    points [2][0] = Left;
  395.    points [2][1] = Bottom;
  396.  
  397.  
  398. /* The Amiga routines should include ones to find out
  399.    the current color and location of the graphics pen,
  400.    but it was not to be.  We will just go grab the
  401.    information from the RastPort structure.            */
  402.  
  403.    OldPenColor = RP->FgPen;
  404.    x = RP->cp_x;
  405.    y = RP->cp_y;
  406.  
  407. /* Set the pen to what we desire, and move the pen
  408.    to the top left corner of the Box.                  */
  409.  
  410.    SetAPen(RP,(long)PenColor);
  411.    Move(RP,(long)Left,(long)Top);
  412.  
  413. /* Draw the Box.                                       */
  414.  
  415.    PolyDraw(RP,4L,points);
  416.  
  417. /* And set everything back again.                      */
  418.  
  419.    SetAPen(RP,(long)OldPenColor);
  420.    Move(RP,(long)x,(long)y);
  421.  
  422. }
  423.  
  424.  
  425. /* End: JoyDemo.c */
  426.  
  427.