home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1994 October / macformat-005.iso / Shareware City / Developers / GENetRelease2ƒ / GEBreakout / Breakout.c < prev   
Encoding:
C/C++ Source or Header  |  1994-06-23  |  10.8 KB  |  548 lines  |  [TEXT/MPS ]

  1. /*
  2.     Breakout.c
  3.     
  4.     Breakout demo for Graphic Elements library
  5.     
  6.     3/7/94
  7.     
  8.     Al Evans
  9.     
  10.     Note: This is a fairly generic application shell.
  11.     The interesting parts are all in BGame.h and .c
  12. */
  13.  
  14. //Load precompiled symbol table if under MPW
  15. #ifdef applec
  16. #ifndef PRELOAD
  17. #pragma load "::ToolKit.precompile"
  18. #define PRELOAD
  19. #endif
  20. #else
  21. #include <QDOffscreen.h>
  22. #endif
  23.  
  24. #include <Timer.h>
  25. #include <GestaltEqu.h>
  26. #include "GUtilities.h"
  27. #include "GraphElements.h"
  28. #include "BGame.h"
  29.  
  30.  
  31. //define HISTOGRAM to collect times history
  32. #undef HISTOGRAM
  33.  
  34. #ifdef HISTOGRAM
  35. #include "StdIO.h"
  36. #endif
  37.  
  38.  
  39. //Menu Commands
  40.  
  41. #define    rMenuBar                128        /* application's menu bar */
  42.  
  43. #define    mApple                    128        /* Apple menu */
  44. #define    iAbout                    1
  45.  
  46. #define    mFile                    129        /* File menu */
  47. #define iNewGame                1
  48. #define    iQuit                    2
  49.  
  50. #define    mEdit                    130        /* Edit menu */
  51. #define    iUndo                    1
  52. #define    iCut                    3
  53. #define    iCopy                    4
  54. #define    iPaste                    5
  55. #define    iClear                    6
  56.  
  57. #define mSpecial                131
  58. #define iSingleFrame            1
  59.  
  60. #define    rAboutDialog            228        
  61.  
  62.  
  63. //Number of master pointer blocks needed
  64.  
  65. #define masterBlocksNeeded 10
  66.  
  67. //Globals
  68.  
  69. Boolean        gFinished;
  70. WindowPtr    gAnimWindow;
  71. Boolean        gSingleFrame = false;
  72. Boolean        gDoOne = false;
  73.  
  74. //Performance measurement
  75.  
  76. #define thirtySeconds 30L * 1000 * 1000        //µsec for timers -- never time out
  77.  
  78. TMTask    gTTimeTask, gATimeTask;
  79. unsigned long gTotalTime = 0, gAnimTime = 0;
  80.  
  81. #ifdef HISTOGRAM
  82. long    animTimes[100];
  83. long    mainTimes[100];
  84. #endif
  85.  
  86. //Forward declarations
  87.  
  88. #ifdef applec
  89. extern void _DataInit();    //reference so that we can unload it
  90. #endif
  91.  
  92. Boolean Initialize( void );
  93. void Shutdown(void);
  94. void EventLoop( void );
  95.  
  96. main()
  97. {
  98. #ifdef applec
  99.     UnloadSeg((Ptr) _DataInit);
  100. #endif
  101.     
  102.     MaxApplZone();
  103.     if ( Initialize() )
  104.         EventLoop();
  105.     Shutdown();
  106. }
  107.  
  108.  
  109. //Initialization
  110.  
  111. Boolean AdequateSystem(void)
  112. {
  113.     OSErr        err;
  114.     long        response;
  115.     Boolean        ok;
  116.     
  117.     //We need 68020 or better
  118.     err = Gestalt(gestaltProcessorType, &response);
  119.     ok = (!err) & (response >= gestalt68020);
  120.     
  121.     //We need System 7 or later
  122.     err = Gestalt(gestaltSystemVersion, &response);
  123.     ok = (!err) & (((response & 0xFFFF) / 256) >= 7);
  124.     
  125.     //We need color QD & offscreen GWorlds
  126.     err = Gestalt(gestaltQuickdrawVersion, &response);
  127.     ok = ok & (!err) & (response >= gestalt32BitQD);
  128.     err = Gestalt(gestaltQuickdrawFeatures, &response);
  129.     ok = ok & (!err) & (response >= 3);         //hasColor & deep GWorlds
  130.     
  131.     return ok;
  132.     
  133. }
  134.  
  135. //Make window centered on main graphic device
  136. WindowPtr MakeWindow(short wHSize, short wVSize)
  137. {
  138.     GDHandle    mainDevice;
  139.     Rect        devRect;
  140.     short        hOffst, vOffst;
  141.     Rect        windRect;
  142.     
  143.     mainDevice = GetMainDevice();
  144.     devRect = (**mainDevice).gdRect;
  145.     hOffst = (devRect.right - devRect.left - wHSize) / 2;
  146.     if (hOffst < 0) hOffst = 0;
  147.     vOffst = (devRect.bottom - devRect.top - wVSize) / 2;
  148.     if (vOffst < 0 ) vOffst = 0;
  149.     windRect.left = hOffst;
  150.     windRect.right = hOffst + wHSize;
  151.     windRect.top = vOffst;
  152.     windRect.bottom = vOffst + wVSize; 
  153.     
  154.     return NewCWindow(nil, &windRect, "\pGEBreakout", false, documentProc,
  155.                         (WindowPtr) -1L, false, 0L);
  156. }
  157.  
  158. void InitPerformanceTiming(void)
  159. {
  160.     //Init Timers
  161.     gTTimeTask.tmAddr = nil;
  162.     gTTimeTask.tmWakeUp = 0;
  163.     gTTimeTask.tmReserved = 0;
  164.     
  165.     gATimeTask.tmAddr = nil;
  166.     gATimeTask.tmWakeUp = 0;
  167.     gATimeTask.tmReserved = 0;
  168.     
  169. }
  170.  
  171. Boolean Initialize(void)
  172. {
  173.     Rect        animRect;
  174.     GEWorldPtr    animWorld;
  175. #ifdef HISTOGRAM
  176.     short    count;
  177. #endif
  178.     
  179.     gFinished = false;
  180.     
  181.     InitSystem(masterBlocksNeeded);
  182.     
  183.     
  184.     if (!AdequateSystem()) {
  185.         TellUser("\pSorry, more powerful system required", 0);
  186.         return false;
  187.     }
  188.     if (!LoadMenus(rMenuBar)) {
  189.         TellUser("\pCould not load menus", 0);
  190.         return false;
  191.     }
  192.     
  193.     //DebugStr("\pInitializing...");
  194.     //Create window and install animation
  195.     if (gAnimWindow = MakeWindow(gWindWidth, gWindHeight)){
  196.         animRect.left = 0;
  197.         animRect.right = gWindWidth;
  198.         animRect.top = 0;
  199.         animRect.bottom = gWindHeight;
  200.         if (animWorld = NewGEWorld((GrafPtr) gAnimWindow, &animRect, scaleOneToOne, nil))
  201.             SetWRefCon(gAnimWindow, (long) animWorld);
  202.         else {
  203.             TellUser("\pCould not install animation in window", 0);
  204.             return false;
  205.         }
  206.     }
  207.     else {
  208.         TellUser("\pCould not create window", 0);
  209.         return false;
  210.     }
  211.     
  212.     InitPerformanceTiming();
  213.     qd.randSeed = TickCount();
  214.     
  215.     //Load game graphics
  216.     
  217.     if (!LoadBreakoutGame(animWorld)) {
  218.         TellUser("\pCould not load game graphics", 0);
  219.         return false;
  220.     }
  221.         
  222. #ifdef HISTOGRAM
  223.     for (count = 0; count < 100; count++) {
  224.         animTimes[count] = 0;
  225.         mainTimes[count] = 0;
  226.     }
  227. #endif
  228.  
  229.     
  230.     //Turn animation on and show window
  231.     ShowWindow(gAnimWindow);
  232.     ActivateWorld((GEWorldPtr) GetWRefCon(gAnimWindow), true);
  233.     return true;
  234.     
  235. }
  236.  
  237. #ifdef HISTOGRAM
  238. void DumpHistograms(void)
  239. {
  240.     short    count;
  241.     FILE*    dump;
  242.     
  243.     dump = fopen("HistoDump", "w");
  244.     for (count = 0; count < 100; count++) 
  245.         fprintf(dump, "%d\t%d\t%d\n", count, mainTimes[count], animTimes[count]);
  246.     fflush(dump);
  247.     fclose(dump);
  248. }
  249. #endif
  250.  
  251. void Shutdown(void)
  252. {
  253.     //Release system resources
  254.     
  255. #ifdef HISTOGRAM
  256.     DumpHistograms();
  257. #endif
  258.  
  259.     DisposeGEWorld((GEWorldPtr) GetWRefCon(gAnimWindow));
  260.     
  261.     ExitToShell();
  262. }
  263.  
  264.  
  265. #ifdef HISTOGRAM
  266. void DoHistogram(void)
  267. {
  268.     if ((gTotalTime - gAnimTime) < 100)
  269.         mainTimes[(gTotalTime - gAnimTime)]++;
  270.     else
  271.         mainTimes[99]++;
  272.     if (gAnimTime < 100)
  273.         animTimes[gAnimTime]++;
  274.     else
  275.         animTimes[99]++;
  276. }
  277. #endif
  278.  
  279. pascal Boolean AboutFilter(DialogPtr dialog, EventRecord *event, short *item)
  280. {
  281. #pragma unused (dialog)
  282.     DoWorldUpdate((GEWorldPtr) GetWRefCon(gAnimWindow), false);
  283.     if ((event->what == mouseDown) || (event->what == keyDown)) {
  284.         *item = ok;
  285.         return true;
  286.     }
  287.     else return false;
  288. }
  289.  
  290. void DoAboutBox(void)
  291. {
  292.     DialogPtr    aboutDialog;
  293.     short        itemHit;
  294.     
  295.     aboutDialog = GetNewDialog(rAboutDialog, nil, (WindowPtr) -1L);
  296.     ModalDialog(AboutFilter, &itemHit);
  297.     DisposDialog(aboutDialog);
  298. }
  299.  
  300.  
  301. //Event Handling
  302.  
  303. void EventLoop( void )
  304. {
  305.     Boolean        gotEvent;
  306.     EventRecord    event;
  307.     
  308.     void DoEvent (EventRecord *event);
  309.     void AdjustCursor( void);
  310.  
  311.     do {
  312.     
  313. #ifdef HISTOGRAM
  314.         InsTime( (QElemPtr) &gTTimeTask);
  315.         InsTime( (QElemPtr) &gATimeTask);
  316.         PrimeTime( (QElemPtr) &gTTimeTask, -thirtySeconds);
  317. #endif
  318.  
  319.         if (!gSingleFrame || gDoOne) {
  320.         
  321. #ifdef HISTOGRAM
  322.             PrimeTime( (QElemPtr) &gATimeTask, -thirtySeconds);
  323. #endif
  324.  
  325.             DoWorldUpdate((GEWorldPtr) GetWRefCon(gAnimWindow), false);
  326.             
  327. #ifdef HISTOGRAM
  328.             RmvTime( (QElemPtr) &gATimeTask);
  329.             gAnimTime = (thirtySeconds + gATimeTask.tmCount) / 1000;
  330. #endif
  331.  
  332.             gDoOne = false;
  333.         }
  334.         AdjustCursor();
  335.         if (gotEvent = WaitNextEvent(everyEvent, &event, 0L, nil)) 
  336.             DoEvent(&event);
  337.             
  338. #ifdef HISTOGRAM
  339.         RmvTime( (QElemPtr) &gTTimeTask);
  340.         gTotalTime = (thirtySeconds + gTTimeTask.tmCount) / 1000; //milliseconds
  341.         DoHistogram();
  342. #endif
  343.  
  344.     } while (!gFinished);
  345. }
  346.  
  347. void DoEvent (EventRecord *event)
  348. {
  349.     short        part;
  350.     WindowPtr    window;
  351.     char        key;
  352.     
  353.     //Prototypes
  354.     void AdjustMenus( void );
  355.     void DoMenuCommand(long menuResult);
  356.     void DoActivate(WindowPtr window, Boolean becomingActive);
  357.     void DoUpdate(WindowPtr window);
  358.     
  359.     switch ( event->what ) {
  360.         case mouseDown:
  361.             part = FindWindow(event->where, &window);
  362.             switch ( part ) {
  363.                 case inMenuBar:
  364.                     AdjustMenus();
  365.                     DoMenuCommand(MenuSelect(event->where));
  366.                     break;
  367.                 case inSysWindow:
  368.                     SystemClick(event, window);
  369.                     break;
  370.                 case inContent:
  371.                     if ( window != FrontWindow() ) 
  372.                         SelectWindow(window);
  373.                     if (MouseDownInSensor((GEWorldPtr) GetWRefCon(gAnimWindow), event->where))
  374.                         ;;
  375.                     break;
  376.                 case inDrag:
  377.                     DragWindow(window, event->where, &qd.screenBits.bounds);
  378.                     break;
  379.             }
  380.             break;
  381.         case keyDown:
  382.             key = event->message & charCodeMask;
  383.             if ( event->modifiers & cmdKey ) {
  384.                 AdjustMenus();
  385.                 DoMenuCommand(MenuKey(key));
  386.             }
  387.             else {
  388.                 switch (key) {
  389.                     case 'U':
  390.                     case 'u':
  391.                         MoveGEWorld((GEWorldPtr) GetWRefCon(gAnimWindow), 0, -50);
  392.                         break;
  393.                     case 'D':
  394.                     case 'd':
  395.                         MoveGEWorld((GEWorldPtr) GetWRefCon(gAnimWindow), 0, 50);
  396.                         break;
  397.                     case 'R':
  398.                     case 'r':
  399.                         MoveGEWorld((GEWorldPtr) GetWRefCon(gAnimWindow), 50, 0);
  400.                         break;
  401.                     case 'L':
  402.                     case 'l':
  403.                         MoveGEWorld((GEWorldPtr) GetWRefCon(gAnimWindow), -50, 0);
  404.                         break;
  405.                 }
  406.             }
  407.             gDoOne = true;
  408.             break;
  409.         case activateEvt:
  410.             DoActivate((WindowPtr) event->message, (event->modifiers & activeFlag) != 0);
  411.             break;
  412.         case updateEvt:
  413.             DoUpdate((WindowPtr) event->message);
  414.             break;
  415.         case osEvt:
  416.             switch ((event->message >> 24) & 0x0FF) {
  417.                 case suspendResumeMessage:
  418.                     gInBackground = (event->message & resumeFlag) == 0;
  419.                     DoActivate(FrontWindow(), !gInBackground);
  420.                     break;
  421.             }
  422.             break;
  423.         }
  424. }
  425.  
  426. void DoActivate(WindowPtr window, Boolean becomingActive)
  427. {
  428. #pragma unused (window)
  429.     //Could start and stop animation here
  430.     ActivateWorld((GEWorldPtr) GetWRefCon(gAnimWindow), becomingActive);
  431. }
  432.  
  433.  
  434. void DoUpdate(WindowPtr window)
  435. {
  436.     Rect geRect;
  437.     GEWorldPtr geWorld;
  438.  
  439.     if (window == gAnimWindow)
  440.     {
  441.         SetPort( (GrafPtr) window );
  442.         //Protect GEWorld rect before updating window, since we will draw it
  443.         geWorld = (GEWorldPtr) GetWRefCon(gAnimWindow);
  444.         geRect = geWorld->animationRect;
  445.         RectOffset(&geRect, geWorld->worldFocus.h, geWorld->worldFocus.v);
  446.         ValidRect(&geRect);
  447.         
  448.         BeginUpdate(window);
  449.             FillRgn(((GrafPtr) window)->visRgn, (ConstPatternParam) &qd.gray);
  450.         EndUpdate(window);
  451.         
  452.         DoWorldUpdate((GEWorldPtr) GetWRefCon(gAnimWindow), true);
  453.     }
  454. }
  455.  
  456. void AdjustMenus( void )
  457. {
  458.     WindowPtr    window;
  459.     MenuHandle    menu;
  460.     
  461.     window = FrontWindow();
  462.     
  463.     menu = GetMHandle(mFile);
  464.     EnableItem(menu, iNewGame);
  465.     EnableItem(menu, iQuit);
  466.  
  467.     menu = GetMHandle(mEdit);
  468.     if (window = gAnimWindow) {
  469.         DisableItem(menu, iUndo);
  470.         DisableItem(menu, iCut);
  471.         DisableItem(menu, iCopy);
  472.         DisableItem(menu, iClear);
  473.         DisableItem(menu, iPaste);
  474.     }
  475.     else {
  476.         EnableItem(menu, iUndo);
  477.         EnableItem(menu, iCut);
  478.         EnableItem(menu, iCopy);
  479.         EnableItem(menu, iClear);
  480.         EnableItem(menu, iPaste);
  481.     }
  482.     menu = GetMHandle(mSpecial);
  483.     //Set up special items!
  484.     CheckItem(menu, iSingleFrame, gSingleFrame);
  485. }
  486.  
  487. void DoMenuCommand(long menuResult)
  488. {
  489.     short        menuID;
  490.     short        menuItem;
  491.     Str255        daName;
  492.     short        daRefNum;
  493.  
  494.     menuID = HiWord(menuResult);
  495.     menuItem = LoWord(menuResult);
  496.     switch ( menuID ) {
  497.         case mApple:
  498.             switch ( menuItem ) {
  499.                 case iAbout:
  500.                     DoAboutBox();
  501.                     break;
  502.                 default:            /* all other items in this menu are DAs */
  503.                     GetItem(GetMHandle(mApple), menuItem, daName);
  504.                     daRefNum = OpenDeskAcc(daName);
  505.                     break;
  506.             }
  507.             break;
  508.         case mFile:
  509.             switch(menuItem) {
  510.                 case iNewGame:
  511.                     NewBreakoutGame((GEWorldPtr) GetWRefCon(gAnimWindow));
  512.                     ActivateWorld((GEWorldPtr) GetWRefCon(gAnimWindow), true);
  513.                     ShowWindow(gAnimWindow);
  514.                     break;
  515.                 case iQuit:
  516.                     gFinished = true;
  517.             }
  518.             break;
  519.         case mEdit:
  520.             (void) SystemEdit(menuItem-1);
  521.             break;
  522.         case mSpecial:
  523.             //Add special items
  524.             switch ( menuItem ) {
  525.                 case iSingleFrame:
  526.                     gSingleFrame = !gSingleFrame;
  527.                     break;
  528.             }
  529.             break;
  530.     }
  531.     HiliteMenu(0);
  532. }
  533.  
  534. //Utility routines
  535.  
  536.  
  537. void AdjustCursor( void )
  538. {
  539.     WindowPtr    window;
  540.     
  541.     window = FrontWindow();
  542.     
  543.     if ( (window == gAnimWindow) && (!gInBackground) ) {
  544.         SetCursor(&qd.arrow);
  545.     }
  546. }
  547.  
  548.