home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bc45 / meteor.pak / METEOR.CPP next >
C/C++ Source or Header  |  1997-07-23  |  8KB  |  288 lines

  1. //--------------------------------------------------------------------------
  2. //  Turbo Meteor -- Copyright (c) 1995, Borland International
  3. //--------------------------------------------------------------------------
  4. #include <owl/owlpch.h>     // all of OWL
  5.  
  6. #include "sprite.h"
  7. #include "meteor.rh"
  8.  
  9. const METEOR_COUNT = 8;
  10. const char IniFilename[] = "METEOR.INI";
  11.  
  12. // MeteorsWindow -- the game window
  13. //
  14. class MeteorWindow: public TWindow {
  15.  
  16.   uint UseCompatibleBitmap, // settings read from the INI file
  17.        width,height;
  18.  
  19.   SpriteList sprites;       // list of all the sprites on the screen
  20.  
  21.   Ship       *ship;         // a seperate pointer to the ship, so we can adjust
  22.                             // it's speed, etc.  the ship is also inserted into
  23.                             // the sprite list
  24.  
  25.   Message    *scoreDisplay; // pointer to the score object, so we can update it
  26.  
  27.   TMemoryDC  *gameField;    // this is where the objects draw to, then it is
  28.                             // BitBlt'ed to the window
  29.  
  30.   bool       rotateLeft,    // flags set when the player presses keys
  31.              rotateRight,
  32.              thrust,
  33.              fire;
  34.  
  35.   long       score;
  36.   int        shipsLeft;
  37.   int        newShipCountdown;    // countdown to new player ship appearing
  38.   bool       gameOver;
  39.  
  40.   uint shotDelay,shotDelayReset;  // used to limit how many shots can be fired
  41.  
  42. public:
  43.   MeteorWindow( TWindow* parent );
  44.   void SetupWindow();
  45.   void CleanupWindow() {
  46.     KillTimer(1);
  47.   }
  48.  
  49.   // don't let windows paint our window, or it will flicker
  50.   //
  51.   BOOL EvEraseBkgnd( HDC ) {
  52.     return true;
  53.   }
  54.   void Paint( TDC& dc, BOOL erase, TRect& rect );
  55.   void EvTimer( UINT id );
  56.   void EvKeyDown( uint key, uint repeatCount, uint flags );
  57.   void EvKeyUp( uint key, uint repeatCount, uint flags );
  58.   DECLARE_RESPONSE_TABLE( MeteorWindow );
  59. };
  60. DEFINE_RESPONSE_TABLE1( MeteorWindow, TWindow )
  61.   EV_WM_TIMER,
  62.   EV_WM_KEYDOWN,
  63.   EV_WM_KEYUP,
  64. END_RESPONSE_TABLE;
  65.  
  66. MeteorWindow::MeteorWindow( TWindow* parent ):
  67.   TWindow( parent ) {
  68.  
  69.   width = GetPrivateProfileInt( "Display", "Width", 600, IniFilename );
  70.   height = GetPrivateProfileInt( "Display", "Height", 400, IniFilename );
  71.   UseCompatibleBitmap = GetPrivateProfileInt( "Display", "UseCompatibleBitmap",
  72.                                               0, IniFilename );
  73.  
  74.   Attr.W = width;
  75.   Attr.H = height;
  76.   for (int i=0;i<METEOR_COUNT;i++)
  77.     sprites.Add( new Meteor( TPoint( random(width), random(height) ),
  78.                                          TSize( random(5)-3, random(5)-3 ),
  79.                                3, 3 ) );
  80.   ship = new Ship( TPoint( width/2, height/2 ) );
  81.   scoreDisplay = new Message(TPoint(5,5),25);
  82.   scoreDisplay->SetText("");
  83.   sprites.Add( ship );
  84.   sprites.Add( scoreDisplay );
  85.   rotateLeft = rotateRight = thrust = fire = false;
  86. }
  87.  
  88. void MeteorWindow::SetupWindow() {
  89.   TWindow::SetupWindow();
  90.  
  91.   // create a memory DC that we will copy the sprites to
  92.  
  93.   gameField = new TMemoryDC( TClientDC( HWindow ) );
  94.  
  95.   // a memory DC must have a bitmap selected into it before you can
  96.   // draw on it.  A compatible bitmap may be slower on some video modes.
  97.  
  98.   if (UseCompatibleBitmap)
  99.     gameField->SelectObject( TBitmap( TClientDC( HWindow ), width, height ) );
  100.   else
  101.     gameField->SelectObject( TBitmap( width, height ) );
  102.  
  103.   // set the pen color to white, and the textbackground color to black
  104.  
  105.   gameField->SelectObject( TPen( TColor( 255, 255, 255 ) ) );
  106.   gameField->SetBkColor( TColor( 0,0,0 ) );
  107.  
  108.   // initialize a timer to run the game
  109.  
  110.   SetTimer( 1, 50 );
  111.  
  112.   shotDelay = shotDelayReset = 5;
  113.  
  114.   score=0;
  115.   shipsLeft=4;
  116.   gameOver=false;
  117.   newShipCountdown=0;
  118. }
  119.  
  120. // EvKeyDown/EvKeyUp -- sets/resets the appropriate flag to indicate that
  121. // the player is holding a key down
  122. //
  123. void MeteorWindow::EvKeyDown( uint key, uint, uint ) {
  124.   switch (key) {
  125.     case VK_LEFT:
  126.       rotateLeft = true;
  127.       break;
  128.     case VK_UP:
  129.       thrust = true;
  130.       break;
  131.     case VK_RIGHT:
  132.       rotateRight = true;
  133.       break;
  134.     case VK_SPACE:
  135.       fire = true;
  136.       break;
  137.   }
  138. }
  139.  
  140. void MeteorWindow::EvKeyUp( uint key, uint, uint ) {
  141.   switch (key) {
  142.     case VK_LEFT:
  143.       rotateLeft = false;
  144.       break;
  145.     case VK_UP:
  146.       thrust = false;
  147.       break;
  148.     case VK_RIGHT:
  149.       rotateRight = false;
  150.       break;
  151.     case VK_SPACE:
  152.       fire = false;
  153.       shotDelay = 0;
  154.       break;
  155.   }
  156. }
  157.  
  158. // EvTimer -- this is the heart of the game.  Every timer tick, we update
  159. // all the sprites on the screen, check for collisions, and redraw everything
  160. //
  161. void MeteorWindow::EvTimer( UINT ) {
  162.   char temp[20];
  163.   int points;
  164.  
  165.   // ExtTextOut is faster than using FillRect
  166.  
  167.   gameField->ExtTextOut(0,0,ETO_OPAQUE,&GetClientRect(),"",0);
  168.  
  169.   // draw all the sprites to the memory DC, then update them all
  170.  
  171.   sprites.DrawAll( *gameField );
  172.  
  173.   // UpdateAll returns the number of points generated by bullets hitting
  174.   // meteors.  If it returns a negative number, it means the ship was hit
  175.  
  176.   points = sprites.UpdateAll();
  177.  
  178.   if (points<0) {  // ship was hit
  179.     ship->Explode();
  180.     ship=0;
  181.     points=0;
  182.     newShipCountdown = 100;
  183.     shipsLeft--;
  184.     if (!shipsLeft)
  185.       gameOver=true;
  186.   }
  187.  
  188.  
  189.   // if the ship was destroyed, adjust countdown to new ship
  190.  
  191.   if (newShipCountdown) {
  192.     newShipCountdown--;
  193.     if (newShipCountdown==0) {
  194.       ship = new Ship( TPoint( width/2, height/2 ) );
  195.       sprites.Add( ship );
  196.     }
  197.   }
  198.  
  199.   // depending on what keys the user has pressed, adjust the
  200.   // ship position/thrust/etc
  201.  
  202.   if (ship) {
  203.     if (rotateLeft) ship->Rotate( 15 );
  204.     if (rotateRight) ship->Rotate( -15 );
  205.  
  206.     if (thrust)
  207.       ship->AddThrust( +1 );
  208.     else
  209.       ship->AddThrust( -1 );
  210.  
  211.     // if the user is holding the spacebar, countdown to the next
  212.     // shot
  213.  
  214.     if ((fire)&&(!shotDelay)) {
  215.         sprites.Add( ship->CreateNewShot() );
  216.       shotDelay = shotDelayReset;
  217.     }
  218.     if (shotDelay)
  219.       shotDelay--;
  220.   }
  221.  
  222.   // update the score display
  223.  
  224.   if (points) {
  225.     score+=points;
  226.     wsprintf(temp,"%8ld",score);
  227.     temp[8]=' ';
  228.     for (int i=0;i<shipsLeft;i++)
  229.       temp[9+i]='*';
  230.     temp[9+shipsLeft]=0;
  231.     scoreDisplay->SetText(temp);
  232.   }
  233.  
  234.   // bit-blit the memory DC to our windows DC
  235.  
  236.   TClientDC( HWindow ).BitBlt( GetClientRect(), /*0, 0, width, height,*/
  237.                                *gameField, TPoint(0,0) );
  238. }
  239.  
  240. // Paint -- in case we ever need to repaint (because another window was
  241. // blocking us, etc), just bitblit the memory DC back to our window.
  242. //
  243. void MeteorWindow::Paint( TDC& dc, BOOL, TRect& ) {
  244.   dc.BitBlt( GetClientRect(), *gameField, TPoint(0,0) );
  245. }
  246.  
  247. // MeteorApp -- our application
  248. //
  249. class MeteorApp: public TApplication {
  250. public:
  251.   void InitMainWindow() {
  252.     int width,height;
  253.     TFrameWindow *fw = new TFrameWindow( 0, "Turbo Meteors",
  254.                                                       new MeteorWindow(0), true );
  255.  
  256.     // to center our window in the middle of the screen, get the screen
  257.     // resolution, and adjust our position accordingly
  258.  
  259.     width = TScreenDC().GetDeviceCaps( HORZRES );
  260.     height = TScreenDC().GetDeviceCaps( VERTRES );
  261.  
  262.     fw->Attr.Style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
  263.     fw->Attr.X = (width-600)/2;
  264.     fw->Attr.Y = (height-400)/2-20;
  265.     fw->SetIcon( this, ICON_1 );
  266.     fw->AssignMenu( MENU_1 );
  267.     SetMainWindow( fw );
  268.   }
  269.   void AboutBox() {
  270.      TDialog( GetMainWindow(), ABOUT_BOX ).Execute();
  271.   }
  272.   void Exit() {
  273.      GetMainWindow()->CloseWindow();
  274.   }
  275.   DECLARE_RESPONSE_TABLE( MeteorApp );
  276. };
  277. DEFINE_RESPONSE_TABLE1( MeteorApp, TApplication )
  278.   EV_COMMAND( CM_HELPABOUT, AboutBox ),
  279.   EV_COMMAND( CM_GAME_EXIT, Exit ),
  280. END_RESPONSE_TABLE;
  281.  
  282. // the main program
  283. //
  284. int OwlMain( int, char *[] ) {
  285.   randomize();
  286.   return MeteorApp().Run();
  287. }
  288.