home *** CD-ROM | disk | FTP | other *** search
/ AI Game Programming Wisdom / AIGameProgrammingWisdom.iso / SourceCode / 11 Learning / 04 Mommersteeg / Tennis / TennisField.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-09-23  |  7.7 KB  |  245 lines

  1. //----------------------------------------------------------------------------------------------
  2. // Sequential Prediction Demo: The positioning pattern
  3. // 
  4. // Author:  Fri Mommersteeg
  5. // Date:    10-09-2001
  6. // File:    TennisPredictor.cpp
  7. //----------------------------------------------------------------------------------------------
  8.  
  9. //----------------------------------------------------------------------------------------------
  10. // Include files
  11. //----------------------------------------------------------------------------------------------
  12.  
  13. #include "stdafx.h"
  14. #include "tennisfield.h"
  15. #include "soundbuffer.h"
  16.  
  17. //----------------------------------------------------------------------------------------------
  18. // External declarations
  19. //----------------------------------------------------------------------------------------------
  20.  
  21. extern LPDDS            imgField;
  22. extern CSoundBuffer        sndHitBall;
  23. extern CSoundBuffer        sndBounce;
  24.  
  25. //----------------------------------------------------------------------------------------------
  26. // NetCollision(): checks for collisions between the ball and the tennis net (disabled here
  27. //                   by setting the NET_HEIGHT to 0)    
  28. //----------------------------------------------------------------------------------------------
  29.  
  30. void CTennisField::NetCollision() {
  31.     RECT net;
  32.     net.left = field.left;
  33.     net.right = field.right;
  34.     net.top = (field.top+field.bottom)/2 - NET_WIDTH;
  35.     net.bottom = (field.top+field.bottom)/2 + NET_WIDTH;
  36.  
  37.     POINT pt;
  38.     ball->GetPosition(pt);
  39.     if (ball->GetHeight()<NET_HEIGHT && PtInRect(&net, pt)) {
  40.         ball->SetVelocity(0,0,0);
  41.     }
  42. }
  43.  
  44. //----------------------------------------------------------------------------------------------
  45. // SetupField(): sets up the tennis field and registers the game objects
  46. //----------------------------------------------------------------------------------------------
  47.  
  48. void CTennisField::SetupField(LPRECT pField, CPaddle * Player1, CPaddle * Player2, CTennisBall * Ball) {
  49.     // copy information into private structs
  50.     CopyRect(&field, pField);
  51.     player[0] = Player1;
  52.     player[1] = Player2;
  53.     ball = Ball;
  54.     
  55.     // set up bounce information
  56.     player[0]->bounce = 0;
  57.     player[1]->bounce = 0;
  58.  
  59.     // set up scores
  60.     player[0]->score = 0;
  61.     player[1]->score = 0;
  62.  
  63.     // register to subjects
  64.     player[0]->RegisterObserver(this);
  65.     player[1]->RegisterObserver(this);
  66.     ball->RegisterObserver(this);
  67.  
  68.     // set up service
  69.     SetupService(PLAYER1);
  70. }
  71.  
  72. //----------------------------------------------------------------------------------------------
  73. // ShowPlayerScore(): Displays the player score on the screen
  74. //----------------------------------------------------------------------------------------------
  75.  
  76. void CTennisField::ShowPlayerScore(HDC dc, int x, int y, int PlayerId) {
  77.     // displayed player score at (x, y)
  78.     char s[20];    
  79.     ltoa(player[PlayerId]->score,s,10);
  80.     int length = strlen(s);
  81.     SetTextColor(dc, player[PlayerId]->GetColor());
  82.     TextOut(dc, x, y, s, length);
  83. }
  84.  
  85. //----------------------------------------------------------------------------------------------
  86. // ShowFPS(): Calculates the frames per second and displays the framerate on the screen.
  87. //              Note: all game speeds are relative to this framerate
  88. //----------------------------------------------------------------------------------------------
  89.  
  90. void CTennisField::ShowFPS(HDC dc, int x, int y) {
  91.     // calculate the new framerate
  92.     nFrameCount++;
  93.     g_FrameRate = (1000*nFrameCount) / (timeGetTime()-StartTime);
  94.     
  95.     // display the framerate on the screen
  96.     char s[20] = "FPS: ";    
  97.     ltoa(g_FrameRate,s+5,10);
  98.     int length = strlen(s);
  99.     TextOut(dc, x, y, s, length);    
  100. }
  101.  
  102. //----------------------------------------------------------------------------------------------
  103. // Update(): Updates the tennis field and all game objects registered with it
  104. //----------------------------------------------------------------------------------------------
  105.  
  106. void CTennisField::Update() {
  107.  
  108.     Fill(NULL, 0, lpddss);
  109.     Blit(imgField, lpddss, (SCREEN_WIDTH-FIELD_WIDTH) / 2, (SCREEN_HEIGHT-FIELD_HEIGHT) / 2);
  110.  
  111.     // update ball position
  112.     ball->Update();
  113.  
  114.     // check for collisions between paddles and the ball
  115.     player[0]->BallCollision(ball);
  116.     player[1]->BallCollision(ball);
  117.  
  118.     // check for collisions between ball and net
  119.     NetCollision();
  120.     
  121.     // update paddle positions
  122.     player[0]->Update();
  123.     player[1]->Update();
  124.     
  125.     // paint game objects
  126.     player[0]->Paint(lpddss);
  127.     player[1]->Paint(lpddss);
  128.     ball->Paint(lpddss);
  129.  
  130.     HDC dc;
  131.     lpddss->GetDC(&dc);
  132.  
  133.     // show scores
  134.     SetBkColor(dc, RGB(0,0,0));
  135.     SetTextColor(dc, RGB(255,255,255));
  136.     TextOut(dc, 10, 140, "Score:", 6);
  137.  
  138.     // show frame rate
  139.     ShowFPS(dc, SCREEN_WIDTH-80, SCREEN_HEIGHT-20);
  140.     
  141.     // show footer text
  142.     TextOut(dc, 10, SCREEN_HEIGHT-20, "ESC - quit  F1 - (un)freeze game  F2 - toggle bot targeting  F3 - stop ball", 75);
  143.     
  144.     // show individual scores
  145.     ShowPlayerScore(dc, 10, 160, 0);
  146.     ShowPlayerScore(dc, 10, 175, 1);
  147.  
  148.     lpddss->ReleaseDC(dc);
  149.  
  150.     if (!Flip()){
  151.         MessageBox(NULL,"flip failed","",MB_OK);
  152.         exit(1);
  153.     }
  154. }
  155.  
  156. //----------------------------------------------------------------------------------------------
  157. // BallInField(): Checks if the ball is in the play field of the specified player
  158. //----------------------------------------------------------------------------------------------
  159.  
  160. BOOL CTennisField::BallInField(int index, POINT pt) {
  161.     int opponent = (index+1) % 2;
  162.     LPRECT lpRect = player[index]->GetField();
  163.  
  164.     if (PtInRect(lpRect, pt)) {
  165.         if (ball->GetOwner() != OWNER_SERVICE) {
  166.             player[index]->bounce++;
  167.                 
  168.             if (player[index]->GetId()==ball->GetOwner()) {
  169.                 PlayerScores(opponent);
  170.             } else {
  171.                 if (player[index]->bounce>1) {
  172.                     PlayerScores(opponent);
  173.                 }
  174.             }
  175.         }
  176.         return TRUE;
  177.     }
  178.     return FALSE;
  179. }
  180.  
  181. //----------------------------------------------------------------------------------------------
  182. // Notify(): Observer notification handler; the tennis field can receive notifications from
  183. //             the ball and the players
  184. //----------------------------------------------------------------------------------------------
  185.  
  186. BOOL CTennisField::Notify(int msg, DWORD param) {
  187.     if (msg == HIT_GROUND_EVENT || msg == BALL_ROLLING_EVENT) {
  188.         POINT pt;
  189.         ball->GetPosition(pt);
  190.  
  191.         if (!BallInField(0, pt) && !BallInField(1, pt)) {
  192.  
  193.             for (int i=0; i<2; i++) {
  194.                 int opponent = (i+1) % 2;
  195.                 if (player[i]->GetId()==ball->GetOwner()) {
  196.                     if (player[opponent]->bounce>0) {
  197.                         PlayerScores(i); break;
  198.                     } else {
  199.                         PlayerScores(opponent); break;
  200.                     }
  201.                 }
  202.             }
  203.  
  204.         }
  205.         if (msg == HIT_GROUND_EVENT) {
  206.             sndBounce.Play();
  207.         }
  208.     }
  209.  
  210.     if (msg == HIT_BALL_EVENT) {
  211.         player[0]->bounce = 0;
  212.         player[1]->bounce = 0;
  213.         sndHitBall.Play();
  214.     }
  215.     return TRUE;
  216. }
  217.  
  218. //----------------------------------------------------------------------------------------------
  219. // SetupForService(): sets up the game for the service
  220. //----------------------------------------------------------------------------------------------
  221.  
  222. void CTennisField::SetupService(int ServicePlayer) {
  223.     // set player positions
  224.     for (int i=0; i<2; i++) {
  225.         player[i]->ResetForService(ServicePlayer == i);
  226.         player[i]->bounce = 0;
  227.     }
  228.  
  229.     // set ball position
  230.     RECT field;
  231.     CopyRect(&field, player[ServicePlayer]->GetField());
  232.     ball->SetPosition((float)(field.right+field.left) / 2, (float)(field.top+field.bottom) / 2, 0);
  233.     ball->SetVelocity(0,0,0);
  234.     ball->SetOwner(OWNER_SERVICE);
  235. }
  236.  
  237. //----------------------------------------------------------------------------------------------
  238. // PlayerScores(): called when a player scores a point
  239. //----------------------------------------------------------------------------------------------
  240.  
  241. void CTennisField::PlayerScores(int index) {
  242.     player[index]->score++;
  243.     SetupService(index);
  244. }
  245.