home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection 1998 Fall: Game Toolkit / Disc.iso / Samples / SprocketExamples / SprocketInvaders / Source / EventHandler.c < prev    next >
Encoding:
Text File  |  1998-07-14  |  10.1 KB  |  500 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        EventHandler.c
  3.  
  4.     Contains:    xxx put contents here xxx
  5.  
  6.     Version:    xxx put version here xxx
  7.  
  8.     Copyright:    © 1998 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     File Ownership:
  11.  
  12.         DRI:                xxx put dri here xxx
  13.  
  14.         Other Contact:        xxx put other contact here xxx
  15.  
  16.         Technology:            xxx put technology here xxx
  17.  
  18.     Writers:
  19.  
  20.         (cjd)    Chris DeSalvo
  21.         (sjb)    Steve Bollinger
  22.         (BWS)    Brent Schorsch
  23.  
  24.     Change History (most recent first):
  25.  
  26.         <20>      7/1/98    cjd        Added CPU load axis to InputSprocket data set
  27.         <19>     6/18/98    sjb        InputSprocket.h comes from <> place
  28.         <18>     6/12/98    BWS        Changed to use InputSprocket 68k
  29. */
  30.  
  31. //•    ------------------------------------------------------------------------------------------    •
  32. //•
  33. //•    Copyright © 1996 Apple Computer, Inc., All Rights Reserved
  34. //•
  35. //•
  36. //•        You may incorporate this sample code into your applications without
  37. //•        restriction, though the sample code has been provided "AS IS" and the
  38. //•        responsibility for its operation is 100% yours.  However, what you are
  39. //•        not permitted to do is to redistribute the source as "DSC Sample Code"
  40. //•        after having made changes. If you're going to re-distribute the source,
  41. //•        we require that you make it clear in the source that the code was
  42. //•        descended from Apple Sample Code, but that you've made changes.
  43. //•
  44. //•        Authors:
  45. //•            Chris De Salvo
  46. //•            Michael Evans
  47. //•
  48. //•    ------------------------------------------------------------------------------------------    •
  49.  
  50. //•    ------------------------------    Includes
  51.  
  52. #include <DiskInit.h>
  53. #include <ToolUtils.h>
  54.  
  55. #define USE_OLD_ISPNEED_STRUCT            0
  56. #define USE_OLD_INPUT_SPROCKET_LABELS    0
  57.  
  58. #include <DrawSprocket.h>
  59. #include <InputSprocket.h>
  60.  
  61. #include "ErrorHandler.h"
  62. #include "EventHandler.h"
  63. #include "Graphics.h"
  64. #include "MenuHandler.h"
  65. #include "SprocketInvaders.h"
  66.  
  67. //•    ------------------------------    Private Definitions
  68. //•    ------------------------------    Private Types
  69. //•    ------------------------------    Private Variables
  70.  
  71. static SInt32     gEventTime;
  72. static SInt16    gSleepTime;
  73.  
  74. //•    ------------------------------    Private Functions
  75.  
  76. static void EventDispatch(EventRecord *theEvent);
  77. static Boolean DefaultMouseDown(EventRecord *theEvent);
  78. static Boolean DefaultKeyDown(EventRecord *theEvent);
  79. static Boolean DoDiskEvent(EventRecord *theEvent);
  80. static void DoSuspend(void);
  81.  
  82. //•    ------------------------------    Public Variables
  83.  
  84. Boolean                gDone = false;
  85. SInt32                gDeltaTime;
  86. EventHandlerSet        gEventHandlers;
  87. ISpElementReference    gInputElements[numInputs];
  88. GameKeys            gGameKeys;
  89.  
  90. //•    --------------------    EventInit
  91.  
  92. short
  93. EventInit(void)
  94. {
  95. SInt16        modifiers = 0;
  96. EventRecord    dummy;
  97. OSStatus    theError;
  98.  
  99. //•    This structure defines the input needs that we'll be requesting from InputSprocket
  100. ISpNeed        myNeeds[numInputs] =
  101. {
  102.     {
  103.         "\pPlayer 1 Movement",
  104.         200,
  105.         1,
  106.         0,
  107.         kISpElementKind_Axis,
  108.         kISpElementLabel_Axis_XAxis,
  109.         0,
  110.         0,
  111.         0,
  112.         0
  113.     },
  114.     {
  115.         "\pPlayer 1 Fire",
  116.         201,
  117.         1,
  118.         0,
  119.         kISpElementKind_Button,
  120.         kISpElementLabel_Btn_Fire,
  121.         0,
  122.         0,
  123.         0,
  124.         0
  125.     },
  126.     {
  127.         "\pPlayer 2 Movement",
  128.         203,
  129.         2,
  130.         0,
  131.         kISpElementKind_Axis,
  132.         kISpElementLabel_Axis_XAxis,
  133.         0,
  134.         0,
  135.         0,
  136.         0
  137.     },
  138.     {
  139.         "\pPlayer 2 Fire",
  140.         204,
  141.         2,
  142.         0,
  143.         kISpElementKind_Button,
  144.         kISpElementLabel_Btn_Fire,
  145.         0,
  146.         0,
  147.         0,
  148.         0
  149.     },
  150.     {
  151.         "\pAbort Game",
  152.         202,
  153.         0,
  154.         0,
  155.         kISpElementKind_Button,
  156.         kISpElementLabel_Btn_PauseResume,
  157.         0,
  158.         0,
  159.         0,
  160.         0
  161.     },
  162.     {
  163.         "\pToggle Sound",
  164.         205,
  165.         0,
  166.         0,
  167.         kISpElementKind_Button,
  168.         kISpElementLabel_None,
  169.         kISpNeedFlag_Utility,
  170.         0,
  171.         0,
  172.         0
  173.     },
  174.     {
  175.         "\pSoundSprocket CPU Load",
  176.         206,
  177.         0,
  178.         0,
  179.         kISpElementKind_Axis,
  180.         kISpElementLabel_None,
  181.         0,
  182.         0,
  183.         0,
  184.         0
  185.     }
  186. };
  187.  
  188.     EventAvail(everyEvent, &dummy);
  189.     modifiers |= dummy.modifiers;
  190.     EventAvail(everyEvent, &dummy);
  191.     modifiers |= dummy.modifiers;
  192.     EventAvail(everyEvent, &dummy);
  193.     modifiers |= dummy.modifiers;
  194.  
  195.     RegisterEventHandlers(DefaultKeyDown, DefaultKeyDown, DefaultMouseDown, nil, nil);
  196.     gEventHandlers.diskHandler = DoDiskEvent;
  197.  
  198.     //•    This sets up how often we'll call WaitNextEvent() in out event loop.
  199.     //•    WNE is still emulated so it's sort of a time waster if you call it too often.
  200.     //•    So, we check DblTime which is the user-selected double-click speed.  We make sure
  201.     //•    that we check inputs at least often enough to notice double-clicks.
  202.     gEventTime = GetDblTime();
  203.     gEventTime /= 2;
  204.  
  205.     //•    This is how much time we'll give to background apps when we're not actively playing
  206.     //•    a game.
  207.     gSleepTime = 32767;
  208.  
  209.     //•    Setup the input sprocket elements
  210.     theError = ISpElement_NewVirtualFromNeeds(numInputs, myNeeds, gInputElements, 0);
  211.     if (theError)
  212.         FatalError("Could not create ISp virtual controls from needs.");
  213.  
  214.     //•    Init InputSprocket and tell it our needs
  215.     theError = ISpInit(numInputs, myNeeds, gInputElements, 'SInv', '0002', 0, 128, 0);
  216.     if (theError)
  217.         FatalError("Could not initialize ISp.");
  218.  
  219.     //•    Turn on the keyboard and mouse handlers
  220.     ISpDevices_ActivateClass (kISpDeviceClass_Keyboard);
  221.     ISpDevices_ActivateClass (kISpDeviceClass_Mouse);
  222.     ISpDevices_ActivateClass (kISpDeviceClass_SpeechRecognition);
  223.  
  224.     ISpSuspend ();
  225.  
  226.     return (modifiers);
  227. }
  228.  
  229. //•    --------------------    EventLoop
  230.  
  231. void
  232. EventLoop(void)
  233. {
  234. EventRecord    theEvent;
  235.  
  236. static SInt32    lastTime = 0L;
  237.  
  238. SInt32            thisTime;
  239. Boolean            wasProcessed;
  240.  
  241.     while (false == gDone)
  242.     {
  243.         thisTime = TickCount();
  244.  
  245.         //•    We don't call WNE while we're playing the game
  246.         if (false == gGameInProgress)
  247.         {
  248.             if (WaitNextEvent(everyEvent, &theEvent, gSleepTime, nil))
  249.             {
  250.                 //•    See if DrawSprocket wants to handle this event
  251.                 DSpProcessEvent(&theEvent, &wasProcessed);
  252.  
  253.                 //•    If DSp punted then we process the event
  254.                 if (false == wasProcessed)
  255.                     EventDispatch(&theEvent);
  256.             }
  257.             else
  258.             {
  259.                 //•    Run any idle tasks
  260.                 if (gEventHandlers.idleHandler)
  261.                 {
  262.                     (*gEventHandlers.idleHandler)(&theEvent);
  263.                 }
  264.             }
  265.         }
  266.  
  267.         //•    gDeltaTime tells the game engine how much time has passed since the last
  268.         //•    game loop.
  269.         if (lastTime > 0)
  270.             gDeltaTime = thisTime - lastTime;
  271.  
  272.         //•    We must tell it that at least SOME time has passed.
  273.         if (gDeltaTime < 1)
  274.             gDeltaTime = 1;
  275.  
  276.         if (gGameInProgress)
  277.         {
  278.             ISpTickle();
  279.             GameLoop();
  280.         }
  281.  
  282.         lastTime = TickCount();
  283.     }
  284. }
  285.  
  286. //•    --------------------    EventDispatch
  287.  
  288. static void
  289. EventDispatch(EventRecord *theEvent)
  290. {
  291.     switch (theEvent->what)
  292.     {
  293.         case mouseDown:
  294.             if (gEventHandlers.clickHandler != nil)
  295.                 if ((*gEventHandlers.clickHandler)(theEvent))
  296.                 {
  297.                     break;
  298.                 }
  299.  
  300.             DefaultMouseDown(theEvent);
  301.             break;
  302.  
  303.         case keyDown:
  304.             if (gEventHandlers.keyHandler != nil)
  305.                 if ((*gEventHandlers.keyHandler)(theEvent))
  306.                 {
  307.                     break;
  308.                 }
  309.  
  310.             DefaultKeyDown(theEvent);
  311.             break;
  312.  
  313.         case autoKey:
  314.             if (gEventHandlers.autoKeyHandler != nil)
  315.                 if ((*gEventHandlers.autoKeyHandler)(theEvent))
  316.                 {
  317.                     break;
  318.                 }
  319.  
  320.             DefaultKeyDown(theEvent);
  321.             break;
  322.  
  323.         case updateEvt:
  324.             if (gEventHandlers.updateHandler != nil)
  325.             {
  326.                 if ((*gEventHandlers.updateHandler)(theEvent))
  327.                 {
  328.                 }
  329.             }
  330.  
  331.             BeginUpdate((WindowRef) theEvent->message);
  332.             GraphicsDoUpdateEvent();
  333.             EndUpdate((WindowRef) theEvent->message);
  334.             break;
  335.  
  336.         case diskEvt:
  337.             if (gEventHandlers.diskHandler != nil)
  338.                 (*gEventHandlers.diskHandler)(theEvent);
  339.             break;
  340.  
  341.         case osEvt:
  342.             if (theEvent->message & 0x01000000)        //•    Suspend/resume event
  343.             {
  344.                 if (theEvent->message & 0x00000001)    //•    Resume
  345.                 {
  346.                 }
  347.                 else
  348.                 {
  349.                     DoSuspend();                    //•    Suspend
  350.                 }
  351.             }
  352.             break;
  353.  
  354.         case kHighLevelEvent:
  355.             AEProcessAppleEvent(theEvent);
  356.             break;
  357.     }
  358. }
  359.  
  360. //•    ------------------------------    DefaultMouseDown
  361.  
  362. static Boolean
  363. DefaultMouseDown(EventRecord *theEvent)
  364. {
  365. SInt16        whatPart;
  366. SInt32        menuResult;
  367. WindowRef    whichWindow;
  368.  
  369.     whatPart = FindWindow(theEvent->where, &whichWindow);
  370.  
  371.     switch (whatPart)
  372.     {
  373.         case inGoAway:
  374.             break;
  375.  
  376.         case inMenuBar:
  377.             DrawMenuBar();
  378.             menuResult = MenuSelect(theEvent->where);
  379.  
  380.             if (HiWord(menuResult) != 0)
  381.                 MenuDoChoice(menuResult);
  382.             break;
  383.  
  384.         case inSysWindow:
  385.             SystemClick(theEvent, whichWindow);
  386.             break;
  387.     }
  388.  
  389.     return (true);
  390. }
  391.  
  392. //•    ------------------------------    DefaultKeyDown
  393.  
  394. static Boolean
  395. DefaultKeyDown(EventRecord *theEvent)
  396. {
  397. SInt8    theKey;
  398. SInt8    theCode;
  399. SInt32    menuResult;
  400.  
  401.     theKey = theEvent->message & charCodeMask;
  402.     theCode = (theEvent->message & keyCodeMask) >> 8;
  403.     if ((theEvent->modifiers & cmdKey) != 0)
  404.     {
  405.         menuResult = MenuKey(theKey);
  406.         if (HiWord(menuResult) != 0)
  407.             MenuDoChoice(menuResult);
  408.  
  409.         return (true);
  410.     }
  411.     
  412.     if ('e' == theKey)
  413.         GraphicsDoUpdateEvent();
  414.     
  415.     return (true);
  416. }
  417.  
  418. //•    ------------------------------    DoDiskEvent
  419.  
  420. static Boolean
  421. DoDiskEvent(EventRecord *theEvent)
  422. {
  423. Point    thePoint;
  424. SInt16    value;
  425.  
  426.     if (theEvent->message & 0xFFFF0000)        //•    Error mounting disk
  427.     {
  428.         SetPt(&thePoint, 100, 100);
  429.         value = DIBadMount(thePoint, theEvent->message);
  430.     }
  431.  
  432.     return (true);
  433. }
  434.  
  435. //•    ------------------------------    RegisterEventHandlers
  436.  
  437. void
  438. RegisterEventHandlers(EventHandlerProc keyDown, EventHandlerProc autoKey, EventHandlerProc mouseDown,
  439.                     EventHandlerProc update, EventHandlerProc idle)
  440. {
  441.     gEventHandlers.keyHandler = keyDown;
  442.     gEventHandlers.autoKeyHandler = autoKey;
  443.     gEventHandlers.clickHandler = mouseDown;
  444.     gEventHandlers.updateHandler = update;
  445.     gEventHandlers.idleHandler = idle;
  446. }
  447.  
  448. //•    ------------------------------    ModifyEventHandlers
  449.  
  450. void
  451. ModifyEventHandlers(EventHandlerProc keyDown, EventHandlerProc autoKey, EventHandlerProc mouseDown,
  452.                     EventHandlerProc update, EventHandlerProc idle)
  453. {
  454.     if (keyDown)
  455.         gEventHandlers.keyHandler = keyDown;
  456.  
  457.     if (autoKey)
  458.         gEventHandlers.autoKeyHandler = autoKey;
  459.  
  460.     if (mouseDown)
  461.         gEventHandlers.clickHandler = mouseDown;
  462.  
  463.     if (update)
  464.         gEventHandlers.updateHandler = update;
  465.  
  466.     if (idle)
  467.         gEventHandlers.idleHandler = idle;
  468. }
  469.  
  470. //•    --------------------    DoSuspend
  471. //•
  472. //•    This is a small, local event loop.  All it does is fetch screen update
  473. //•    events and wait to get put back in the foreground.
  474.  
  475. static void
  476. DoSuspend(void)
  477. {
  478. EventRecord    theEvent;
  479.  
  480.     while (true)
  481.     {
  482.         //•    Only check for resume and update events.  While doing so, give TONS of time to other apps
  483.         if (WaitNextEvent(osMask, &theEvent, 32767, nil))
  484.         {
  485.             if (theEvent.message & 0x01000000)        //•    Suspend/resume event
  486.             {
  487.                 if (theEvent.message & 0x00000001)    //•    Resume
  488.                 {
  489.                 Boolean    dummy;
  490.  
  491.                     //•    Make sure that DrawSprocket knows that we've resumed
  492.                     DSpProcessEvent(&theEvent, &dummy);
  493.                 }
  494.                 break;
  495.             }
  496.         }
  497.     }
  498. }
  499.  
  500.