-
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...
-
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.
-
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!