Example08_SpriteCollision.cpp


/*--------------------------------------------
   Examples - CRM32Pro SDK - Roberto Prieto
   Copyright (C) 2001-2011 MegaStorm Systems
  --------------------------------------------

  Example 8: Sprites collision
  ----------------------------
  - Initialize SDL and CRM32Pro.
  - Printing help on a window.
  - Use of log system.
  - Initialize graphics: window icon, video mode and cursor.
  - Load resources from DPF: images(IPF), fonts and sprite
  - Image following the mouse cursor.
  - Using Fixed Logic Rate.
  - With F1 key, you can enable/disable collision system.
  - Information panel with FPS(real time) and number of collisions.
  - Exiting using the right way ;)

  This example is totally free and can be used without 
any restriction but there is not any warranty for its usage.
Please, do not forget to include a copy of all the library licenses
located at /licenses directory if you distribute or share it.

Roberto Prieto
megastorm@ono.com
http://www.megastormsystems.com
*/

// ---Includes---
#include "CRM32Pro.h"

// ---Defines---
#define EXAMPLE_VERSION "Example 8: Sprites Collision"
#define GFX_RESOURCE "data/gfx.dpf"     // DPF with graphic resources

// ---Prototypes---
void RenderGraphics(int);
void RenderGraphicsGL(int);
void PrintHelp();

// ---Global vars---
SDL_Surface *bg, *info, *backinfo, *surfCursor;
CRM32Pro_CFont *fInfo;
CRM32Pro_CSprite *sprRabbit;
SDL_Rect inf, rCursor;
Uint32 last = 0, lastinfo = 0;
Uint8 bFlagCollision = 1;

// -------------MAIN FUNCTION----------------
int main(int argc,char *argv[])
{
   Uint8       done = 0;
   int         DirX = 1, DirY = 1, SprX = 100, SprY = 100;
   SDL_Event   event;

   // -Print help on a window-
   PrintHelp();

   // -Log system initialize-    
   ILogSystem.Init("SpriteCollision.log",LOG_FILE,LOG_NORMAL,EXAMPLE_VERSION);

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

   // -Desired config-
   CRM32Pro.Config.Title = EXAMPLE_VERSION;
   CRM32Pro.Config.Icon = IImage->Load(GFX_RESOURCE,"icono");
   CRM32Pro.Config.bMTFriendly = 1;
   //CRM32Pro.Config.VideoRenderer = RENDER_OPENGL;
   //CRM32Pro.Config.VideoAccel = ACCEL_HARDSMOOTH ;

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

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

   // -Set our render graphics function to fullfil desired Rendering Frame Rate-
   if(!CRM32Pro.IsGL()) CRM32Pro.SetRenderCallback(RenderGraphics);
   else CRM32Pro.SetRenderCallback(RenderGraphicsGL);

   // -Load resources: background, info panel, info font, sprite and image to follow the cursor-    
   bg = IImage->Load(GFX_RESOURCE,"background2");
   info = IImage->Load(GFX_RESOURCE,"info");
   inf.x = 6;inf.y = 6;inf.w = info->w;inf.h = info->h;
   backinfo = IImage->Load(GFX_RESOURCE,"info");       
   fInfo = new CRM32Pro_CFont();
   fInfo->Load(GFX_RESOURCE,"InfoFont");
   sprRabbit = new CRM32Pro_CSprite();
   sprRabbit->Load(GFX_RESOURCE,"rabbit");
   sprRabbit->AutoRestore(0);
   surfCursor = IImage->Load(GFX_RESOURCE,"Smiley");
   if(surfCursor == NULL) exit(1);
   rCursor.x = 100;rCursor.y = 110;rCursor.w = surfCursor->w;rCursor.h = surfCursor->h;

   // -Main loop-
   bFlagCollision = 1;
   done = 0;          
   while(!done)
   {                                        
      // 1.Logic frame stuff
             // Each logic frame (20 per seconds) we move the sprite. We assume that sprRabbit size is 64x64             
      SprX = SprX + (2 * DirX);
      SprY = SprY + (2 * DirY);
      if((SprX + 64) > CRM32Pro.screen->w) DirX = DirX * (-1);
      if((SprY + 64) > CRM32Pro.screen->h) DirY = DirY * (-1);
      if(SprX < 2) DirX = DirX * (-1);
      if(SprY < 2) DirY = DirY * (-1);
      sprRabbit->SetPosition(SprX,SprY);

      // 2.Event loop: update all systems: graphics,events,timing...
      // surfCursor follow the position of mouse. With F1 activate/desactivate collision system. ESC exit.
      while(CRM32Pro.Update(&event))        
      {
         switch(event.type)
         {
            case SDL_KEYDOWN:
               if(event.key.keysym.sym == SDLK_ESCAPE) done = 1;
               if(event.key.keysym.sym == SDLK_F1) bFlagCollision = bFlagCollision * (-1);
                      break;
            case SDL_MOUSEMOTION:
               rCursor.x = event.motion.x - rCursor.w / 2;
               rCursor.y = event.motion.y - rCursor.h / 2;
                                    // As we have moved the sprite that follows the cursor, we order a render update
                                    CRM32Pro.RenderNeeded();
               break;

            case SDL_QUIT:
               done = 1;
               break;
                                 case EVENT_LOGICWAIT:
               // While CRM32Pro.Update() wait for fulfill the logic rate this event is raised     
                                    // You could do some stuff here.
                                    // Is possible to call here to your Rendering Graphics after checking the user.code returned instead of using the CRM32Pro callback,
                                    // but it will have some extra overdraw.
                                    break;
            default:
               break;
         }
      }
   }

   // -Free resources, show information and exit-
   delete fInfo;   
   sprRabbit->Info();
   delete sprRabbit;
    CRM32Pro.FreeSurface(bg);
   CRM32Pro.FreeSurface(info);
   CRM32Pro.FreeSurface(backinfo);
   CRM32Pro.FreeSurface(surfCursor);
   ITimeSystem->Info();
   CRM32Pro.VideoInfo();
   CRM32Pro.Quit();
   return 0;
}

// ---Our render graphics function---
// We render our graphics if a logic frame occurred(bLogicUpdate = 1) or if CRM32Pro.IsRenderNeeded() return 1
void RenderGraphics(int bLogicUpdate)
{
   char  sTmp[16];
   int   isCollision = 0, nCollisions = 0;

   // Check if we need to render everything
   if(!CRM32Pro.IsRenderNeeded() && (!bLogicUpdate)) return;

   // Blit background
   SDL_BlitSurface(bg, NULL, CRM32Pro.screen, NULL);

   // Sprite blitting
   sprRabbit->Draw();

   // Detecting collisions
   nCollisions = 0;
   if(bFlagCollision == 1)
   {
      isCollision = sprRabbit->Collision(surfCursor,&rCursor,-1,-1,1);
      if(isCollision) nCollisions++;
   }
   // Image following the cursor blitting
   SDL_BlitSurface(surfCursor, NULL, CRM32Pro.screen, &rCursor);                                                                    

   // Blit information panel: state of collision system and FPS (four times per second)
   SDL_BlitSurface(info,NULL,CRM32Pro.screen,&inf);    
   if((lastinfo + 250) < ITimeSystem->GetTime())
   {
      lastinfo = ITimeSystem->GetTime();
      // Restore original info panel
      SDL_BlitSurface(backinfo,NULL,info,NULL);

      // Are we detecting collisions?                  
      if(bFlagCollision == 1) fInfo->PutString(info,62,7,"ON");
      else
         fInfo->PutString(info,62,7,"OFF");

      // Frames per second (real time)
      sprintf(sTmp,"%d",(Uint32)ITimeSystem->GetCurrentRFR());
      fInfo->PutString(info,43,23,sTmp);

      // Print number of collisions
      sprintf(sTmp,"%d",nCollisions);
      fInfo->PutString(info,70,42,sTmp);
   }
}

// ---Our render graphics function for OpenGL mode---
// In OpenGL modes, blitting from a surface to another surface requires some conversions
// so the best workaround is just blit everything to CRM32Pro.screen surface.
// CRM32Pro.IsRenderNeeded() knows we are on an OpenGL mode so it will force to render everything
void RenderGraphicsGL(int bLogicUpdate)
{
   char  sTmp[16];
   int   isCollision = 0, nCollisions = 0;

   // Check if we need to render everything
   if(!CRM32Pro.IsRenderNeeded() && (!bLogicUpdate)) return;

   // Blit background
   SDL_BlitSurface(bg, NULL, CRM32Pro.screen, NULL);

   // Sprite blitting
   sprRabbit->Draw();

   // Detecting collisions
   nCollisions = 0;
   if(bFlagCollision == 1)
   {
      isCollision = sprRabbit->Collision(surfCursor,&rCursor,-1,-1,1);
             if(isCollision) nCollisions++;
   }

   // Image following the cursor blitting
   SDL_BlitSurface(surfCursor, NULL, CRM32Pro.screen, &rCursor);                                                                    

   // Blit information panel: state of collision system and FPS (four times per second)
   lastinfo = ITimeSystem->GetTime();
   // Restore original info panel
   SDL_BlitSurface(backinfo,NULL,CRM32Pro.screen,&inf);

   // Are we detecting collisions?                     
   if(bFlagCollision == 1) fInfo->PutString(CRM32Pro.screen,68,13,"ON");
   else   fInfo->PutString(CRM32Pro.screen,68,13,"OFF");

   // Frames per second (real time)
   sprintf(sTmp,"%d",(Uint32)ITimeSystem->GetCurrentRFR());
   fInfo->PutString(CRM32Pro.screen,49,29,sTmp);

   // Print number of collisions
   sprintf(sTmp,"%d",nCollisions);
   fInfo->PutString(CRM32Pro.screen,79,48,sTmp); 
}

// --------------------Help STUFF------------------------
// -Print help-
void PrintHelp()
{
           char *sMsg;

           // Create the message
           sMsg = new char[1024];
    strcpy(sMsg,"-----------------------------------------------------------\n");
           strcat(sMsg,"                     ");
           strcat(sMsg,EXAMPLE_VERSION);
           strcat(sMsg,"\n-----------------------------------------------------------\n\n");
           strcat(sMsg," Press [ESCAPE] key to exit.\n");
           strcat(sMsg," Press [F1] key to enable/disable collision detection.\n");
           strcat(sMsg,"\n Runtime information is logged into 'SpriteCollision.log' file.\n");
           strcat(sMsg,"\n");

           // Display the message
    #ifdef _WINDOWS
             MessageBox(NULL,sMsg,"CRM32Pro SDK - HelpScreen",MB_OK);
    #endif
           #ifdef _LINUX 
             printf("CRM32Pro SDK - HelpScreen\n%s",sMsg);
    #endif

           // Free the message
           delete sMsg;
}

 All Classes Functions Variables