Thread: SDL Collision Handling

  1. #1
    Internet Superhero
    Join Date
    Sep 2006
    Location
    Denmark
    Posts
    964

    SDL Collision Handling

    I'm making a simple maze game with SDL, it's my first ever SDL program and really my first non-console program ever, so far i've been doing good, but now i've begun on the collision detection, and something is not doing what it's supposed to.

    This is how my collision detection function looks:
    Code:
    bool CollisionCheck(SDL_Rect A, SDL_Rect B)
    {
    	//The sides of the rectangles
    	unsigned int LeftA, LeftB;
    	unsigned int RightA, RightB;
    	unsigned int TopA, TopB;
    	unsigned int BottomA, BottomB;
    	
    	//Get the sizes from the SDL_Rect structs - Rect A
    	LeftA = A.x;
    	RightA = A.x + A.w;
    	TopA = A.y;
    	BottomA = A.y + A.h;
    	
    	//Get the sizes from the SDL_Rect structs - Rect B
    	LeftB = B.x;
    	RightB = B.x + B.w;
    	TopB = B.y;
    	BottomB = B.y + B.h;
    	
    
    	if( (BottomA <= TopB) || (TopA >= BottomB) || (RightA <= LeftB) || (LeftA >= RightB) )
    	      return false;
    	
    	else
    	{
    	      return true;
    	}
    }
    Is there anything wrong with this function? The thing is, i've got it in a loop checking if the player hits a wall (I only have 1 wall at the moment, no maze yet), if that is the case, the game quits. But with the above function, it just quits instantly when i run it.

    This is the entire program:
    Code:
    //Neo1
    //LabyrinthX 1.0
    #include "SDL/SDL.h"
    #include "SDL/SDL_Image.h"
    #include <string>
    
    #define START_POS_X 180
    #define START_POS_Y 140
    #define VELOCITY 3
    
    SDL_Surface *LoadImage(std::string Filename);
    void ApplySurface(SDL_Rect &Rect, SDL_Surface* Source, SDL_Surface* Destination);
    bool CollisionCheck(SDL_Rect A, SDL_Rect B);
    
    //Need CMD-linge arguments for SDL to function properly
    int main(int argc, char *argv[])
    {
    	//Struct for the position of the man and set coordinates to the default values
    	SDL_Rect MyMan;
    	MyMan.x = START_POS_X;
    	MyMan.y = START_POS_Y;
    	
    	//Struct for the background position
    	SDL_Rect MyBackgroundPos;
    	MyBackgroundPos.x = 0;
    	MyBackgroundPos.y = 0;
    	
    	//Wall
    	SDL_Rect MyWall;
    	MyWall.y = 40;
    	MyWall.x = 300;
    	MyWall.w = 40;
    	MyWall.h = 400;
    	
    	//Screen width, height and color depth
    	const int SCREEN_WIDTH = 640;
    	const int SCREEN_HEIGHT = 480;
    	const int SCREEN_BPP = 32;
    	
    	//Pointers to the stick man, the background image, and the screen
    	SDL_Surface *Man = NULL;
    	SDL_Surface *Background = NULL;
    	SDL_Surface *Screen = NULL;
    	
    	//An event struct for holding KB input
    	SDL_Event Event;
    	//Bool for checking if the user want's to exit
    	bool Quit = false;
    	//Pointer for holding the key state array
    	Uint8 *KeyStates;
    	
    	//Initialize SDL and check for errors
    	if(SDL_Init(SDL_INIT_EVERYTHING) == -1)
    	{
    		return 1;
    	}
    	
    	//Set up the display and check for errors
    	Screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE);
    	if(Screen == NULL)
    	{
    		return 1;
    	}
    	
    	//Set the window caption
    	SDL_WM_SetCaption("LabyrinthX", NULL);
    	
    	//Load the images into the surfaces
    	Man = LoadImage("Man.bmp");
    	Background = LoadImage("background.bmp");
    	
    	//Main program loop
    	while(!Quit)
    	{
    		while(SDL_PollEvent(&Event))
    		{
    			if(Event.type == SDL_QUIT)
    			{
    					Quit = true;
    			}
    		}
    		
    		//Update the KeyStates array
    		KeyStates = SDL_GetKeyState(NULL);
    		
    		//Move the man according to key presses -Y
    		if(KeyStates[SDLK_UP])
    			MyMan.y -= VELOCITY;
    		if(KeyStates[SDLK_DOWN])
    			MyMan.y += VELOCITY;
    		//Move the man according to key presses -X
    		if(KeyStates[SDLK_LEFT])
    			MyMan.x -= VELOCITY;
    		if(KeyStates[SDLK_RIGHT])
    			MyMan.x += VELOCITY;
    		
    		//Check that the man isn't on his way out of the screen -Y
    		if(MyMan.y < 0)
    			MyMan.y += VELOCITY;
    		if( (MyMan.y + MyMan.h) > SCREEN_HEIGHT)
    			MyMan.y -= VELOCITY;
    		//Check that the mas isn't on his way out of the screen -X
    		if(MyMan.x < 0)
    			MyMan.x += VELOCITY;
    		if( (MyMan.x + MyMan.w) > SCREEN_WIDTH)
    			MyMan.x -= VELOCITY;
    		
    		//Check if the man has touched the wall -X
    		if(CollisionCheck(MyWall, MyMan))
    		{
    			Quit = true;
    		}
    		
    		//Draw the background
    		ApplySurface(MyBackgroundPos, Background, Screen);
    		//Draw the man
    		ApplySurface(MyMan, Man, Screen);
    		//Fill the wall
    		SDL_FillRect(Screen, &MyWall, SDL_MapRGB(Screen->format, 0xFF, 0xFF, 0xFF));
    		
    		//Update the screen and check for errors
    		if(SDL_Flip(Screen) == -1)
    		{
    			return 1;
    		}
    	}
    	
    	//Clean Up
    	SDL_FreeSurface(Man);
    	SDL_FreeSurface(Background);
    	
    	SDL_Quit();
    	return 0;
    }
    
    //Image loading function
    SDL_Surface *LoadImage(std::string Filename)
    {
    	//Surface pointers for the image
    	SDL_Surface *LoadedImage = NULL;
    	SDL_Surface *OptimizedImage = NULL;
    	
    	//Load the image
    	LoadedImage = IMG_Load(Filename.c_str());
    	
    	//Error check
    	if(LoadedImage == NULL)
    	{
    		return NULL;
    	}
    	
    	//Optimize the image for the display format and release the original image
    	OptimizedImage = SDL_DisplayFormat(LoadedImage);
    	SDL_FreeSurface(LoadedImage);
    	
    	//Error check
    	if(OptimizedImage == NULL)
    	{
    		return NULL;
    	}
    	
    	//Color key is "0, 255, 255"
    	Uint32 ColorKey = SDL_MapRGB(OptimizedImage->format, 0, 0xFF, 0xFF);
    	SDL_SetColorKey(OptimizedImage, SDL_SRCCOLORKEY, ColorKey);
    	
    	return OptimizedImage;
    }
    
    void ApplySurface(SDL_Rect &Rect, SDL_Surface* Source, SDL_Surface* Destination)
    {	
    	SDL_BlitSurface(Source, NULL, Destination, &Rect);
    	return;
    }
    
    bool CollisionCheck(SDL_Rect A, SDL_Rect B)
    {
    	//The sides of the rectangles
    	unsigned int LeftA, LeftB;
    	unsigned int RightA, RightB;
    	unsigned int TopA, TopB;
    	unsigned int BottomA, BottomB;
    	
    	//Get the sizes from the SDL_Rect structs - Rect A
    	LeftA = A.x;
    	RightA = A.x + A.w;
    	TopA = A.y;
    	BottomA = A.y + A.h;
    	
    	//Get the sizes from the SDL_Rect structs - Rect B
    	LeftB = B.x;
    	RightB = B.x + B.w;
    	TopB = B.y;
    	BottomB = B.y + B.h;
    	
    	if( (BottomA <= TopB) || (TopA >= BottomB) || (RightA <= LeftB) || (LeftA >= RightB) )
    	{
    		return false;
    	}
    	
    	return true;
    }
    I'm guessing something is wrong with my logic, if i take out the call to collision check the program runs flawlessly...
    How I need a drink, alcoholic in nature, after the heavy lectures involving quantum mechanics.

  2. #2
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    I think part of your problem is this.
    Code:
    $ gdb -q ./1
    Using host libthread_db library "/lib/libthread_db.so.1".
    (gdb) break CollisionCheck(SDL_Rect, SDL_Rect) 
    Breakpoint 1 at 0x400d44: file 1.cpp, line 184.
    (gdb) run
    Starting program: 1 
    [Thread debugging using libthread_db enabled]
    [New Thread 0x2b9712106500 (LWP 12151)]
    [New Thread 0x40800950 (LWP 12154)]
    [Switching to Thread 0x2b9712106500 (LWP 12151)]
    
    Breakpoint 1, CollisionCheck (A={x = 300, y = 40, w = 40, h = 400}, B=
          {x = 177, y = 140, w = 11159, h = 0}) at 1.cpp:184
    184		LeftA = A.x;
    (gdb) l
    179		unsigned int RightA, RightB;
    180		unsigned int TopA, TopB;
    181		unsigned int BottomA, BottomB;
    182		
    183		//Get the sizes from the SDL_Rect structs - Rect A
    184		LeftA = A.x;
    185		RightA = A.x + A.w;
    186		TopA = A.y;
    187		BottomA = A.y + A.h;
    188		
    (gdb) l
    189		//Get the sizes from the SDL_Rect structs - Rect B
    190		LeftB = B.x;
    191		RightB = B.x + B.w;
    192		TopB = B.y;
    193		BottomB = B.y + B.h;
    194		
    195		if( (BottomA <= TopB) || (TopA >= BottomB) || (RightA <= LeftB) || (LeftA >= RightB) )
    196		{
    197			return false;
    198		}
    (gdb) n
    185		RightA = A.x + A.w;
    (gdb) 
    186		TopA = A.y;
    (gdb) 
    187		BottomA = A.y + A.h;
    (gdb) 
    190		LeftB = B.x;
    (gdb) 
    191		RightB = B.x + B.w;
    (gdb) 
    192		TopB = B.y;
    (gdb) 
    193		BottomB = B.y + B.h;
    (gdb) 
    195		if( (BottomA <= TopB) || (TopA >= BottomB) || (RightA <= LeftB) || (LeftA >= RightB) )
    (gdb) p BottomA
    $1 = 440
    (gdb) p TopB
    $2 = 140
    (gdb) p TopA
    $3 = 40
    (gdb) p BottomB
    $4 = 140
    (gdb) p A
    $5 = {x = 300, y = 40, w = 40, h = 400}
    (gdb) p B
    $6 = {x = 177, y = 140, w = 11159, h = 0}
    (gdb) bt
    #0  CollisionCheck (A={x = 300, y = 40, w = 40, h = 400}, B=
          {x = 177, y = 140, w = 11159, h = 0}) at 1.cpp:195
    #1  0x00000000004011dc in main (argc=1, argv=0x7fff9b776cd8) at 1.cpp:109
    (gdb) up
    #1  0x00000000004011dc in main (argc=1, argv=0x7fff9b776cd8) at 1.cpp:109
    109			if(CollisionCheck(MyWall, MyMan))
    (gdb) p MyMan
    $7 = {x = 177, y = 140, w = 11159, h = 0}
    (gdb) q
    The program is running.  Exit anyway? (y or n) y
    $ nl 1.cpp | grep MyMan
        16		SDL_Rect MyMan;
        17		MyMan.x = START_POS_X;
        18		MyMan.y = START_POS_Y;
        85				MyMan.y -= VELOCITY;
        87				MyMan.y += VELOCITY;
        90				MyMan.x -= VELOCITY;
        92				MyMan.x += VELOCITY;
        95			if(MyMan.y < 0)
        96				MyMan.y += VELOCITY;
        97			if( (MyMan.y + MyMan.h) > SCREEN_HEIGHT)
        98				MyMan.y -= VELOCITY;
       100			if(MyMan.x < 0)
       101				MyMan.x += VELOCITY;
       102			if( (MyMan.x + MyMan.w) > SCREEN_WIDTH)
       103				MyMan.x -= VELOCITY;
       106			if(CollisionCheck(MyWall, MyMan))
       114			ApplySurface(MyMan, Man, Screen);
    $
    You never assign anything to MyMan.w.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  3. #3
    Internet Superhero
    Join Date
    Sep 2006
    Location
    Denmark
    Posts
    964
    dwks:

    But isn't the width and height of the rectangle set when i load an image into it?

    Edit: Apparently it isn't, i've specified the width and height of the rectangle now and it works like a charm! Thanks DWKS, i need to learn how to use a debugger very soon!
    Last edited by Neo1; 04-02-2008 at 02:31 PM.
    How I need a drink, alcoholic in nature, after the heavy lectures involving quantum mechanics.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. event handling is serialized in MS Visual Studio C++ 2005 ??
    By mynickmynick in forum Windows Programming
    Replies: 3
    Last Post: 08-07-2008, 04:47 AM
  2. Some collision handling fun
    By DavidP in forum Game Programming
    Replies: 9
    Last Post: 04-13-2008, 08:45 AM
  3. Collision Detection Problems
    By Dark_Phoenix in forum Game Programming
    Replies: 1
    Last Post: 12-17-2006, 03:25 PM
  4. explanation of void collision in sdl lib
    By Shadow12345 in forum Game Programming
    Replies: 0
    Last Post: 05-26-2002, 09:28 AM
  5. Replies: 4
    Last Post: 05-03-2002, 09:40 PM