home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / METEOR.PAK / METEOR.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  8.0 KB  |  297 lines

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