SpacePong.cpp


SpacePong source - A little pong clone game

/*--------------------------------------------
   SpacePong Minigame - Roberto Prieto
   Copyright (C) 2001-2011 MegaStorm Systems
  --------------------------------------------
           
           This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.
    
    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    
    Roberto Prieto
           megastorm@ono.com
           http://www.megastormsystems.com

 ------------------------------------------------------------------------
                           SpacePong Minigame - CRM32Pro SDK example
           
             
Pong clone with 3 different game modes:
 
 - Auto demo mode
 - 1 player
 - 2 players (on the same computer)
 - 2D environment at 800x600
 - Graphics, sounds and musics using DPF
 - Platform: Win32 / Linux / MacOS X
  
  Thanks to Worvast for the new in-game graphics.

           Changelog: Check history.txt
 
 ------------------------------------------------------------------------ */

// ---Includes---
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <math.h>
#include "CRM32Pro.h"
#include "SpacePong.h"

#ifdef _WINDOWS
  #include <conio.h>
  #include <windows.h>
#elif defined(_LINUX) || defined(_MACOSX)
  #include <math.h>
  char *_itoa(int i,char *a,size_t len)
  {
           sprintf(a,"%d",i % static_cast<int>(pow(10,len-1-(i<0))));
           return a;
  }
#endif


// -------------------------MAIN ENTRY POINT---------------------------------
int main(int argc,char *argv[])
{
   Uint8 done;
   int   iRet;

   // -Init log system-
   ILogSystem.Init("spacepong.log",LOG_FILE,LOG_NORMAL,PONG_VERSION);

   // -Init CRM32Pro- 
   if(CRM32Pro.Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_AUDIO) < 0)
   {
      ILogSystem.Msg(LOG_NORMAL," ·[PONG Init Error] - Couldnīt initialize CRM32Pro: %s\n",SDL_GetError());
      exit(1);
   }

   // -Desired config-
   if(!CRM32Pro.LoadConfig("setup.dpf","setup.xml"))
   {
      ILogSystem.Msg(LOG_NORMAL," ·[PONG Init Error] - Couldnīt load 'setup.xml'. Please, run 'Setup.exe'\n");
      exit(1);
   }
   CRM32Pro.Config.Title = PONG_VERSION;
   CRM32Pro.Config.Icon = IImage->Load(GFX_RESOURCE,"icono");

   // -Graphics system initialize-  
   if(!CRM32Pro.SetVideoMode())
   {
      CRM32Pro.Quit();
      return 1;
   }
   ICursor->Init();

   // -Time system initialize-
   ITimeSystem->Init();
   ITimeSystem->SetRate(0,40);  // Optional: desired Rendering and Logic Frame Rate

   // -Init sound system-
   iRet = ISoundFX->Init(); // It uses the config of CRM32Pro.Config
   if(iRet == -1) ILogSystem.Msg(LOG_NORMAL," ·[PONG Sound System] - Couldnīt init sound system: %s\n",SDL_GetError());  
   else if(iRet == 1) LoadAudio();
   
   // -MegaStorm Systems presentation-    
  /* ISoundFX->SoundPlay(1,thunder,0);
   sGameBg = IImage->Load(GFX_RESOURCE,"logotipoMS");   
   SDL_FillRect(CRM32Pro.screen,NULL,SDL_MapRGB(CRM32Pro.screen->format,0,0,0));
   IScreenFX->FadeToImage(sGameBg,500);    
   while(ISoundFX->IsPlaying(1)) SDL_Delay(50); 
   IScreenFX->FadeToColor(0,0,0,500);
   SDL_FreeSurface(sGameBg);*/

   // -Loading gfx-
   LoadGraphics();
  
   // -Main menu loop-
   IButton->SetState(bGoalID,B_PRESS);
   sGameDat.iTipo = GAME_GOAL;
   done = PONG_ENTRY;
   while(done != PONG_QUIT)
   {
      // 1.First execution or after a game match: 
             //  - initial fade, music play, show cursor
             //  - set our render callback
      if(done == PONG_ENTRY)
      {
         IScreenFX->FadeToImage(sMenuBg,600);
         ISoundFX->MusicPlay(music_menu, 100);         
                       ICursor->Show();
                       ICursor->Invalidate();           
         CRM32Pro.SetRenderCallback(RenderInMenu);
                       CRM32Pro.CleanUp();
                       bID = -1;
                       done = PONG_LOOP;
      }    

      // 2.Buttons management. The bID is retrieved by our render callback.   
      // 2.1.Exit to OS
      if(bID == bExitID)
      {
         ISoundFX->SoundPlay(1,click,0);
         while(ISoundFX->IsPlaying(1)) SDL_Delay(200);
         done = PONG_QUIT;
      }
      // 2.2.Start game with 1 Player
      else if(bID == bPlayer1ID)
      {
         ISoundFX->SoundPlay(1,click,0);
         // Execute the game loop
         sGameDat.iModo = MODE_1PLAYER;
         GameLoop();
         done = PONG_ENTRY;
      }
      // 2.3.Start game with 2 Players
      else if(bID == bPlayer2ID)
      {
         ISoundFX->SoundPlay(1,click,0);
         // Execute the game loop
         sGameDat.iModo = MODE_2PLAYER;
         GameLoop();
         done = PONG_ENTRY;                 
      }
      // 2.4.Start game with autoplay
      else if(bID == bAutoID)
      {
         ISoundFX->SoundPlay(1,click,0);
         // Execute the game loop
         sGameDat.iModo = MODE_COMPUTER;
         GameLoop();
         done = PONG_ENTRY;                 
      }
      // 2.5.Change game mode to normal
      else if(bID == bNormalID)
      {
         ISoundFX->SoundPlay(1,click2,0);
         IButton->SetState(bGoalID,B_NORMAL);
         IButton->SetState(bTimeID,B_NORMAL);
         IButton->SetState(bNormalID,B_PRESS);
         sGameDat.iTipo = GAME_NORMAL;                  
      }
      // 2.6.Change game mode to goal
      else if(bID == bGoalID)
      {
         ISoundFX->SoundPlay(1,click2,0);
         IButton->SetState(bGoalID,B_PRESS);
         IButton->SetState(bTimeID,B_NORMAL);
         IButton->SetState(bNormalID,B_NORMAL);
         sGameDat.iTipo = GAME_GOAL;
      }
      // 2.7.Change game mode to time
      else if(bID == bTimeID)
      {
         ISoundFX->SoundPlay(1,click2,0);
         IButton->SetState(bGoalID,B_NORMAL);
         IButton->SetState(bTimeID,B_PRESS);
         IButton->SetState(bNormalID,B_NORMAL);
         sGameDat.iTipo = GAME_TIME;        
      }
           
      // 3.Main update: blit to screen, update time system, etc.
      while(CRM32Pro.Update());
   }

   // -Exiting...-
   ISoundFX->MusicFadeOut(500);
   SDL_Delay(250);
   ISoundFX->MusicStop();
   IScreenFX->FadeToColor(0,0,0,500);
   FreeAudio();
   FreeGraphics();   
   CRM32Pro.AudioInfo();
   CRM32Pro.VideoInfo();
   CRM32Pro.Quit();
   ILogSystem.Msg(LOG_NORMAL,"\n · End of execution\n");
   return 1;
}

// Callback function called by CRM32Pro.Update() fulfilling with Rendering Frame Rate
// Used in the menu screen. Not in the game.
void RenderInMenu(int bLogicUpdate)
{
           if(!CRM32Pro.IsRenderNeeded()) return;
    {
                      CRM32Pro.Blit(sMenuBg,NULL,CRM32Pro.screen,NULL);
                      rRect.x = 27;rRect.y = 20;rRect.w = sMenuTitle->w; rRect.h = sMenuTitle->h;
                      CRM32Pro.Blit(sMenuTitle,NULL,CRM32Pro.screen,&rRect);
                      rRect.x = 133;rRect.y = 578;rRect.w = sMenuInfo->w; rRect.h = sMenuInfo->h;
                      CRM32Pro.Blit(sMenuInfo,NULL,CRM32Pro.screen,&rRect);   
                      bID = IButton->Draw();
           } 
}

// ------------------------------GAME LOOP------------------------------------
void GameLoop()
{
   Uint8    done;
   Uint32   iTmp = 0;

   // Hide cursor, stop previous render callback 
   ICursor->Hide();
   CRM32Pro.SetRenderCallback(NULL);

   // Init vars, starting position and init ball
   srand(SDL_GetTicks());
   sGameDat.iWinP1 = 0; sGameDat.iWinP2 = 0;
   sPadder[0].x = 384.0f; sPadder[0].size = 64; sPadder[0].speed=0.0f; sPadder[0].random=64/2;
   sPadder[1].x = 384.0f; sPadder[1].size = 64; sPadder[1].speed=0.0f; sPadder[1].random=64/2;
   InitBall(0);
   sBall.spr->SetPosition((int)sBall.x,(int)sBall.y);
   sPadder[0].spr->SetPosition((int)sPadder[0].x,Y_POSITION_1);
   sPadder[1].spr->SetPosition((int)sPadder[1].x,Y_POSITION_2);
   ILogSystem.Msg(LOG_NORMAL,"\n · Match started...");

   // Finish previous click sound and music. Fade to black and start music with fade to image.
   while(ISoundFX->IsPlaying(1)) SDL_Delay(200);                  
   ISoundFX->MusicFadeOut(500);
   IScreenFX->FadeToColor(0,0,0,500);
   ISoundFX->MusicStop();
   ISoundFX->MusicPlay(music_game, 100);
   IScreenFX->FadeToImage(sGameBg,500);

   // Show game type string
   switch(sGameDat.iTipo)
   {
      case GAME_TIME:
         strcpy(sCad,"TIME"); break;
      case GAME_GOAL:
         strcpy(sCad,"GOAL"); break;
      case GAME_NORMAL:
         strcpy(sCad,"INFI");  break;
   }

   // Set our in-game render callback function
   CRM32Pro.SetRenderCallback(RenderInGame);
   CRM32Pro.CleanUp();

   // As we are using smooth sprite movement, we set the render engine to draw always
   CRM32Pro.RenderNeeded(UPDATEFRAME_ALWAYS);

   // Main game loop with a Fixed Logic Rate of 20 executions per seconds
   done = PONG_ENTRY;
   while(done < PONG_QUIT)
   {
      // 1.Event management
      if(CRM32Pro.GetKeystate(SDLK_ESCAPE)) done = PONG_QUIT;     
      if(CRM32Pro.GetKeystate(SDLK_F2)) SDL_SaveBMP(CRM32Pro.screen,"pong.bmp");
           
      // 2.Ball behaviour
      sBall.x = sBall.x + (sBall.sx * sBall.speed);
      sBall.y = sBall.y + (sBall.sy * sBall.speed);

      // 2.1.Detect wall bounds
      if(sBall.x < LEFT_BAR)
      {
                        sBall.x = LEFT_BAR;
          sBall.sx = sBall.sx * (-1.0f); ISoundFX->SoundPlay(2,pared,0);
      }
      else if(sBall.x + X_SIZE_BALL > RIGHT_BAR)
      {
                        sBall.x = RIGHT_BAR - X_SIZE_BALL;
          sBall.sx = sBall.sx * (-1.0f); ISoundFX->SoundPlay(2,pared,0);
      }
           
      // 2.2.Detect Padder1 goal
      if(sBall.y < UP_LIMIT)
      {
         InitBall(1);
         sGameDat.iWinP1++;                                       
         ISoundFX->SoundPlay(2,gol,0);
         SDL_Delay(250);                    
      }
      // 2.3.Detect Padder2 goal
      else if(sBall.y > DOWN_LIMIT)
      {
         InitBall(2);
         sGameDat.iWinP2++;                 
         ISoundFX->SoundPlay(2,gol,0);
         SDL_Delay(250);
      }

      // 3.Padder movement
      switch(sGameDat.iModo)
      {
         case MODE_COMPUTER:
            AIPadder(0);
            AIPadder(1);
            break;
         case MODE_2PLAYER:
            if(CRM32Pro.GetKeystate(SDLK_x)) SET_SPEED(1,1);
            if(CRM32Pro.GetKeystate(SDLK_z)) SET_SPEED(1,0);
            if(CRM32Pro.GetKeystate(SDLK_RIGHT)) SET_SPEED(0,1);
            if(CRM32Pro.GetKeystate(SDLK_LEFT)) SET_SPEED(0,0);
            break;
         case MODE_1PLAYER:
                                 if(CRM32Pro.GetKeystate(SDLK_RIGHT)) SET_SPEED(0,1);                         
            if(CRM32Pro.GetKeystate(SDLK_LEFT)) SET_SPEED(0,0);
            AIPadder(1);
            break;
      }
             // 3.1.Adjust padders speed and set right animation
             for(iTmp = 0; iTmp < 2; iTmp++)
             {
                        sPadder[iTmp].spr->SelectAnim(SPRSTATE_NORMAL); // Trend to be stopped
         if(sPadder[iTmp].speed > PADDER_MAXSPEED) sPadder[iTmp].speed = PADDER_MAXSPEED;
                       if(sPadder[iTmp].speed < -PADDER_MAXSPEED) sPadder[iTmp].speed = -PADDER_MAXSPEED;
                       if(sPadder[iTmp].speed > 0.0f) 
                       {
                                  sPadder[iTmp].speed -= PADDER_ACEL / 4; // Trend to stop
                                  sPadder[iTmp].spr->SelectAnim(SPRSTATE_LEFT);
                       }
                       if(sPadder[iTmp].speed < 0.0f) 
                       {
                                  sPadder[iTmp].speed += PADDER_ACEL / 4; // Trend to stop
                                  sPadder[iTmp].spr->SelectAnim(SPRSTATE_RIGHT);
                       }
             }
             // 3.2.Calculate new positions
             for(iTmp = 0; iTmp < 2; iTmp++) sPadder[iTmp].x = sPadder[iTmp].x + sPadder[iTmp].speed;
             // 3.3.Adjust padders position
             for(iTmp = 0; iTmp < 2; iTmp++)
             {
                        if(sPadder[iTmp].x > RIGHT_BAR - sPadder[iTmp].size) 
                        { 
                                   sPadder[iTmp].x = RIGHT_BAR - sPadder[iTmp].size; 
                                   sPadder[iTmp].speed = 0.0f; 
                        }
                        if(sPadder[iTmp].x < LEFT_BAR) 
                        { 
                                   sPadder[iTmp].x = LEFT_BAR;  
                                   sPadder[iTmp].speed = 0.0f; 
                        }
             }

             // 4.Detect ball hit on padder1 and padder2. Margin of 12 pixels
      if((sBall.y + Y_SIZE_BALL >= Y_POSITION_1) && (sBall.y + Y_SIZE_BALL <= (Y_POSITION_1 + 12))) PadderHitBall(0);
      if((sBall.y <= Y_POSITION_2 + Y_SIZE_PADDER) && (sBall.y >= (Y_POSITION_2 + Y_SIZE_PADDER - 12))) PadderHitBall(1);

      // 5.Update sprites with smooth system
      sBall.spr->SetPosition((int)sBall.x,(int)sBall.y,1);
      sPadder[0].spr->SetPosition((int)sPadder[0].x,Y_POSITION_1,1);
      sPadder[1].spr->SetPosition((int)sPadder[1].x,Y_POSITION_2,1);
           
      // 6.End of match conditions
      switch(sGameDat.iTipo)
      {
         // Play a match during 5 minutes
         case GAME_TIME:                               
            if(iAux == 5) done = PONG_ENDMATCH;
            break;
         // Play a match until one player reach 10 points
         case GAME_GOAL:
            if((sGameDat.iWinP1 == 10) || (sGameDat.iWinP2 == 10)) done = PONG_ENDMATCH;
            break;
      }

      // 7.Main update: draw sprites using callback function, update interfaces, blit to screen, update time system, etc.
      while(CRM32Pro.Update());
   }

   // Show the winner! (0=player1 1=tie 2=player2)
   ISoundFX->SoundPlay(1,end,0);
   // Did we a break? (ESCAPE key was pressed)
   if(done == PONG_QUIT) 
   {
      if(sGameDat.iTipo != GAME_NORMAL) iTmp = 1;
      else
      {
         if(sGameDat.iWinP1 > sGameDat.iWinP2) iTmp = 0;
         else if(sGameDat.iWinP1 < sGameDat.iWinP2) iTmp = 2;
         else iTmp = 1;
      }
   }
   // There is a winner!
   else
   {
      if(sGameDat.iWinP1 > sGameDat.iWinP2) iTmp = 0;
      else if(sGameDat.iWinP1 < sGameDat.iWinP2) iTmp = 2;
   }
   switch(iTmp)
   {
      case 0:         
         fFont->PutString(CRM32Pro.screen,260,290,"PLAYER 1 WINS !!");
         break;
      case 1:
         fFont->PutString(CRM32Pro.screen,300,290,"TIE GAME !!");
         break;
      case 2:
         fFont->PutString(CRM32Pro.screen,260,290,"PLAYER 2 WINS !!");
         break;
   }
   ILogSystem.Msg(LOG_NORMAL,"\n · Player 1 wins: %d - Player 2 wins: %d\n",sGameDat.iWinP1,sGameDat.iWinP2);
   ITimeSystem->Info();
   ILogSystem.Msg(LOG_NORMAL," · Match finished\n");
   
   // Remove our in-game render callback
   CRM32Pro.SetRenderCallback(NULL);
   CRM32Pro.RenderNeeded(UPDATEFRAME_NONE);

   // Flip now the screen to show the name of the winner
   SDL_Flip(CRM32Pro.screen);
   SDL_Delay(2000);
   // Menu music stop
   ISoundFX->MusicFadeOut(500);
   SDL_Delay(250);
   ISoundFX->MusicStop();
   IScreenFX->FadeToColor(0,0,0,500);
}

// Callback function called by CRM32Pro.Update() fulfilling with Rendering Frame Rate
// Used in the game. Not in the menu screen.
void RenderInGame(int bLogicUpdate)
{
    // Check if we need to render everything.
           if(!CRM32Pro.IsRenderNeeded() && (!bLogicUpdate)) return; 
           
           CRM32Pro.Blit(sGameBg,NULL,CRM32Pro.screen,NULL);
           sBall.spr->Draw();
           sPadder[0].spr->Draw();
           sPadder[1].spr->Draw();          
           DrawInterfaz(1);
           DrawInterfaz(2);
           fFont->PutString(CRM32Pro.screen,36,463,sCad);
           fFont->PutString(CRM32Pro.screen,685,463,sCad);
}

void DrawInterfaz(int m)
{
   char     sAux[4], sCad[8];
   Uint32   iTime = 0;

   iTime = (Uint32)ITimeSystem->GetSeconds();
           
   switch(m)
   {
      case 1:
         // Restore info pannel of the Player 1
         rRect.x = 25; rRect.y = 199; rRect.w = sRestoreBg[0]->w; rRect.h = sRestoreBg[0]->h;
         SDL_BlitSurface(sRestoreBg[0],NULL,CRM32Pro.screen,&rRect);
         // Score board of the Player 1
         _itoa(sGameDat.iWinP1,sAux,10);
         strcpy(sCad,"");
         if(sGameDat.iWinP1 < 10) strcpy(sCad,"0");    
         strcat(sCad,sAux);
         fFont->PutString(CRM32Pro.screen,55,203,sCad);
         // Time left
         strcpy(sCad,"");                              
         iAux = iTime / 60;
         _itoa(iAux,sAux,10);
         strcpy(sCad,sAux);      
         strcat(sCad,":");
         _itoa(iTime - (iAux * 60),sAux,10);
         if(iTime - (iAux * 60) < 10) strcat(sCad,"0");
         strcat(sCad,sAux);
         fFont->PutString(CRM32Pro.screen,44,264,sCad);           
         break;
           
      case 2:
         // Restore info pannel of the Player 2
         rRect.x = 685; rRect.y = 201; rRect.w = sRestoreBg[1]->w; rRect.h = sRestoreBg[1]->h;
         SDL_BlitSurface(sRestoreBg[1],NULL,CRM32Pro.screen,&rRect);         
         // Score board of the Player 1
         _itoa(sGameDat.iWinP2,sAux,10);
         strcpy(sCad,"");
         if(sGameDat.iWinP2 < 10) strcpy(sCad,"0");    
         strcat(sCad,sAux);
         fFont->PutString(CRM32Pro.screen,704,203,sCad);
         // Time left
         strcpy(sCad,"");        
         iAux = iTime / 60;
         _itoa(iAux,sAux,10);
         strcpy(sCad,sAux);      
         strcat(sCad,":");
         _itoa(iTime - (iAux * 60),sAux,10);
         if(iTime - (iAux * 60) < 10) strcat(sCad,"0");
         strcat(sCad,sAux);      
         fFont->PutString(CRM32Pro.screen,692,264,sCad);
         break;
   }
}


/* AIPadder() - AI movement of the given padder
   m=0 for Padder 1, with limitY at 100 (old 225)
   m=1 for Padder 2, with limitY at 500 (old 375)
   With y>limitY the player tend to move at the center
   when the ball is greater than limitY, the player will try to pursuit it*/
void AIPadder(int m)
{
   // Movement to screen center when the ball is going to the other player
   if(((!m) && (sBall.y < 100)) || ((m) && (sBall.y > 500)))
   {
              if(sPadder[m].x < 368)      { SET_SPEED(m,1); } // Try to center
              else if(sPadder[m].x > 368) { SET_SPEED(m,0); } // Try to center
   }

   // Movement towards the ball with a little random behaviour
   else
   {
             if(((sBall.x + 8)) < (sPadder[m].x + sPadder[m].random))
      {
                        if(sPadder[m].x > LEFT_BAR) { SET_SPEED(m,0); }
      }
      else if(((sBall.x + 8)) > (sPadder[m].x + sPadder[m].random))
      {
                        if(sPadder[m].x <= RIGHT_BAR - sPadder[m].size) { SET_SPEED(m,1); }
      }
   }
}          

// InitBall() - Initialize the ball
void InitBall(int mode)
{
   // Center ball with starting speed
   sBall.sx = 0.0;
   sBall.x = 400.0;
   sBall.y = 300.0;
   sBall.speed = 0.9;

   switch(mode)
   {
      // mode=0, start match with random direction
      case 0:
         if((rand() % 10) >= 5) sBall.sy = -4.0;
         else sBall.sy = 4.0;
         break;
      // mode=1, ball for padder1
      case 1:
         sBall.sy = -4.0;
         break;
      // mode=2, ball for padder2
      case 2:
         sBall.sy = 4.0;
         break;
   }
}

// PadderHitBall() - Change the ball speed and direction depending on current hit. Select the next random hit point.
void PadderHitBall(int m) // Support 7 differents directions
{
   int   iTmp;
   float mod = -1.0;
   if(m == 0) mod = 1.0;

   if(((sBall.x + 12) >= sPadder[m].x) && ((sBall.x + 4) <= (sPadder[m].x + 64)))
   {
      if(m == 0) ISoundFX->SoundPlay(1,p1,0);
      else ISoundFX->SoundPlay(1,p2,0);
      iTmp = 24 + (int)sBall.x - (int)sPadder[m].x;
      // The best hit!
             if(iTmp <= 18)
      {
         sBall.sx = -5;sBall.sy = -4 * mod;
      } 
      else if((iTmp > 18) && (iTmp <= 24))
      {
         sBall.sx = -4.0f;sBall.sy = -4.0f * mod;
      }
      else if((iTmp > 24) && (iTmp <= 40))
      {
         sBall.sx = -2.0f;sBall.sy = -6.0f * mod;
      }
      else if((iTmp > 40) && (iTmp <= 56))
      {
         sBall.sx = 0.0f;sBall.sy = -8.0f * mod;
      }
      else if((iTmp > 56) && (iTmp <= 72))
      {
         sBall.sx = 2.0f;sBall.sy = -6.0f * mod;
      }
      else if((iTmp > 72) && (iTmp <= 78))
      {
         sBall.sx = 4.0f;sBall.sy = -4.0f * mod;
      }
             // The best hit!
      else if(iTmp >= 79)
      {
         sBall.sx = 5.0f;sBall.sy = -4.0f * mod;
      } 
      else ILogSystem.Msg(LOG_NORMAL,"Padder[%d] - Error %d\n",m + 1,iTmp);  
      
             // Set ball speed
             sBall.speed = sBall.speed + 0.03f;
             if(sBall.speed >= MAX_BALL_SPEED) sBall.speed = MAX_BALL_SPEED;
      
             // Set next attempt to hit on a random way
             sPadder[m].random=rand()%sPadder[m].size;
   }       
}

// LoadAudio() - Load audio resources
void LoadAudio()
{
   thunder = ISoundFX->SoundLoad(MUS_RESOURCE,"thunder");
   end = ISoundFX->SoundLoad(MUS_RESOURCE,"endplay");
   gol = ISoundFX->SoundLoad(MUS_RESOURCE,"goal");
   p1 = ISoundFX->SoundLoad(MUS_RESOURCE,"padder1");
   p2 = ISoundFX->SoundLoad(MUS_RESOURCE,"padder2");
   pared = ISoundFX->SoundLoad(MUS_RESOURCE,"pared");
   click = ISoundFX->SoundLoad(MUS_RESOURCE,"click");             
   click2 = ISoundFX->SoundLoad(MUS_RESOURCE,"click2");
   music_menu = ISoundFX->MusicLoad(MUS_RESOURCE,"game");
   music_game = ISoundFX->MusicLoad(MUS_RESOURCE,"game");
}

// FreeAudio() - Free audio resources
void FreeAudio()
{
   ISoundFX->MusicFree(music_menu);
   ISoundFX->MusicFree(music_game);
   ISoundFX->SoundFree(thunder);
   ISoundFX->SoundFree(click);
   ISoundFX->SoundFree(click2);
   ISoundFX->SoundFree(p1);
   ISoundFX->SoundFree(p2);
   ISoundFX->SoundFree(pared);
   ISoundFX->SoundFree(gol);
   ISoundFX->SoundFree(end);
}

// LoadGraphics() - Load graphics resources
void LoadGraphics()
{
   sGameBg = IImage->Load(GFX_RESOURCE,"gamebg");
   sRestoreBg[0] = SDL_CreateRGBSurface(CRM32Pro.screen->flags,100,95,sGameBg->format->BitsPerPixel,
                                        sGameBg->format->Rmask,sGameBg->format->Gmask,sGameBg->format->Bmask,
                                        sGameBg->format->Amask);
   rRect.x = 25;rRect.y = 199;rRect.w = 100;rRect.h = 95;
   SDL_BlitSurface(sGameBg,&rRect,sRestoreBg[0],NULL);
   sRestoreBg[1] = SDL_CreateRGBSurface(CRM32Pro.screen->flags,100,90,sGameBg->format->BitsPerPixel,
                                        sGameBg->format->Rmask,sGameBg->format->Gmask,sGameBg->format->Bmask,
                                        sGameBg->format->Amask);
   rRect.x = 685;rRect.y = 201;rRect.w = 100;rRect.h = 90;
   SDL_BlitSurface(sGameBg,&rRect,sRestoreBg[1],NULL);

   sMenuBg = IImage->Load(GFX_RESOURCE,"menubg");
   sMenuTitle = IImage->Load(GFX_RESOURCE,"menutitle");
   sMenuInfo = IImage->Load(GFX_RESOURCE,"menuinfo");
   sPadder[0].spr = new CRM32Pro_CSprite();
   sPadder[0].spr->Load(GFX_RESOURCE,"SPR_PADDER1");
   sPadder[1].spr = new CRM32Pro_CSprite();
   sPadder[1].spr->Load(GFX_RESOURCE,"SPR_PADDER2");
   sBall.spr = new CRM32Pro_CSprite();
   sBall.spr->Load(GFX_RESOURCE,"SPR_BALL");
   fFont = new CRM32Pro_CFont;
   fFont->Load(GFX_RESOURCE,"FVerde");

   bExitID = IButton->Load(GFX_RESOURCE,"bExit");
   bPlayer1ID = IButton->Load(GFX_RESOURCE,"bPlayer1");
   bPlayer2ID = IButton->Load(GFX_RESOURCE,"bPlayer2");
   bAutoID = IButton->Load(GFX_RESOURCE,"bAuto");
   bTimeID = IButton->Load(GFX_RESOURCE,"bTime");
   bGoalID = IButton->Load(GFX_RESOURCE,"bGoal");
   bNormalID = IButton->Load(GFX_RESOURCE,"bNormal");

   cCursor = ICursor->Load(GFX_RESOURCE,"cursor");
   ICursor->Select(cCursor);
}

// FreeGraphics() - Free graphics resources
void FreeGraphics()
{
   delete sPadder[0].spr;
   delete sPadder[1].spr;
   delete sBall.spr;
   delete fFont;
   SDL_FreeSurface(sGameBg);
   SDL_FreeSurface(sMenuBg);
   SDL_FreeSurface(sMenuTitle);
   SDL_FreeSurface(sMenuInfo);
   SDL_FreeSurface(sRestoreBg[0]);
   SDL_FreeSurface(sRestoreBg[1]);
   IButton->RemoveAll();
   ICursor->Delete(cCursor);
}
 All Classes Functions Variables