• Advertisement
Sign in to follow this  

Trouble with object Collisions

This topic is 4171 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm really having trouble with detecting collisions between my objects. Basically I load my objects in from a file which contains, there locations on my map. That works fine, they are drawn in the correct spots. The problem is when I got to determine if the objects collide I can't seem to get them to work Right now my code looks like this: int Echo_Engine_2D_Map::Sprite_collision_fall() { OBJECTS_OBSTACLES *temp_ptr; OBJECTS_OBSTACLES *temp_ptr_2; int i; temp_ptr = obj_ob_head; temp_ptr_2 = temp_ptr; for(i = 0; i <= num_objects; i++) { //THIS WORKS FINE //check to see if object collides with a block tile on the map while(tiles[Map_Array[(temp_ptr->map_pos_y+64)/64][(temp_ptr->map_pos_x)/64][0]].obstacle == 1) { temp_ptr->map_pos_y -=8; ( THIS IS MY PROBLEM // check object to object Sprite_collision_down(temp_ptr,temp_ptr_2); temp_ptr->map_pos_y +=temp_ptr->v_y; temp_ptr = temp_ptr->next_object; } return TRUE; } bool Sprite_collision_down(OBJECTS_OBSTACLES *ptr1,OBJECTS_OBSTACLES *ptr2) { if(ptr1->map_pos_y+64 <= ptr2->map_pos_y) { dx7.Display_Text("Yes!",384,256); return false; } if(ptr1->map_pos_y >= ptr2->map_pos_y+64) { dx7.Display_Text("Yes!",384,256); return false; } if(ptr1->map_pos_x+64 <= ptr2->map_pos_x) { dx7.Display_Text("Yes!",384,256); return false; } if(ptr1->map_pos_x >= ptr2->map_pos_x+64) { dx7.Display_Text("Yes!",384,256); return false; } dx7.Display_Text("No!",384,256); return true; } When I run the code both the Yes/No are displayed on the screen, I don't know where I'm going wrong Any help on where I'm going wrong would be greatly appreciated [Edited by - Taco2003 on September 18, 2006 6:32:44 PM]

Share this post


Link to post
Share on other sites
Advertisement
I assume you are trying to see if two rectangles intersect in that last function. I can't really take yours to bits at the moment but it looks all wrong to be honest.

The way I'd do this would be first of all have a function that tests to see if a single point is within a rectangle:


// assumes struct Rect { x,y,w,h };

bool IsIn(int X,int Y,Rect R)
{
return(X>=R.x && X<R.x+R.w && Y>=R.y && Y<R.y+R.h);
}




You can then build on this to create a function that tests if one rectangle intersects another:


bool IsIn(Rect A,Rect B)
{
if(IsIn(A.x,A.y,B)) return true;
if(IsIn(A.x+A.w-1,A.y,B)) return true;
if(IsIn(A.x,A.y+A.h-1,B)) return true;
if(IsIn(A.x+A.w-1,A.y+A.h-1,B)) return true;
return true;
}




Then to test two rectangles for intersection, you can just do:


bool Intersect(Rect A,Rect B)
{
return IsIn(A,B) || IsIn(B,A);
}




Once you have removed rectangle checking logic from your sprite code like that, you can then just base the sprite checking code on the Intersect function above.

A slightly nicer approach is to have a Rect class that supports these operations:


class Rect
{
public:
Rect(int x=0,int y=0,int w=0,int h=0) : X(x),Y(y),W(w),H(h) { }

bool Contains(int x,int y);
bool Contains(Rect R);

int X,Y,W,H;
};

bool Rect::Contains(int x,int y)
{
return(x>=X && x<X+W && y>=Y && y<Y+H);
}

bool Rect::IsIn(Rect R)
{
if(Contains(R.X,R.Y)) return true;
if(Contains(R.X+R.W-1,R.Y)) return true;
if(Contains(R.X,R.Y+R.H-1)) return true;
if(Contains(R.X+R.W-1,R.Y+R.H-1)) return true;

return false;
}

bool Intersect(Rect A,Rect B)
{
return A.Contains(B) || B.Contains(A);
}



You can then either have your sprite class contain a Rect structure defining its location and size, or alternatively:


class Sprite
{
private:
int X,Y,Width,Height;

public:
Sprite(){ }

Rect GetRect() const { return Rect(X,Y,Width,Height); }
};

bool SpritesIntersect(Sprite A,Sprite B)
{
return Intersect(A.GetRect(),B.GetRect());
}



HTH Paul

Share this post


Link to post
Share on other sites
I understand what you are saying, but will that way work the same for way I have my objects set up?

I create my objects using a typedef struct

eg.


typedef struct obj_str {
int pos_x; // the x position on the map
int pos_y; // the y position on the map
int map_pos_x;
int map_pos_y;
int destroy;
int push;
int v_y;
int block;
obj_str *next_object;
} OBJECTS_OBSTACLES;



then during Initialization I read the objects in from a text file


int Echo_Engine_2D_Map::Read_Object_File(char *filename)
{
FILE *fileinfo;

OBJECTS_OBSTACLES *obj_ptr;
fileinfo = fopen(filename, "r");

for(int i = 0; i <=num_objects; i++)
{

if((obj_ptr = newObject()) == NULL)
{
dx7.Report_Error("could Not create new object");
return FALSE;
}

fscanf(fileinfo,"%d",&obj_ptr->pos_x); // read in the tiles location in bitmap (x direction)
fscanf(fileinfo,"%d",&obj_ptr->pos_y); // read in the tiles location in bitmap (y direction)
fscanf(fileinfo,"%d",&obj_ptr->map_pos_x);// read in the tiles location on the map (x direction)
fscanf(fileinfo,"%d",&obj_ptr->map_pos_y);// read in the tiles location on the map(y direction)
fscanf(fileinfo,"%d",&obj_ptr->destroy);// read in the tile push value
fscanf(fileinfo,"%d",&obj_ptr->push);//ead in the tile push value
fscanf(fileinfo,"%d",&obj_ptr->v_y);//ead in the tile push value
fscanf(fileinfo,"%d\n",&obj_ptr->block);// read in the tiles block value


}
fclose(fileinfo);
return TRUE;
}




I think I'm really getting fooled up in looping through my objects on each update, or does this have any effect on it?

Share this post


Link to post
Share on other sites
Well first up, you are needlessly mixing C and C++. In C++ there is no difference between the following:


typedef struct object_s
{
int x,y;
} object;

struct x
{
int x,y;
};

class x
{
public:
int x,y;
};









The first one is pointless as it is a throwback to pure C, where it was needed in order to avoid doing "struct object" everywhere you wanted to just do "object".

The second point to bear in mind here is that in C++ there is no difference between a struct and a class except that at struct has public (by default) access and inheritance whereas a class has private.

The implication of this is that a struct can have member functions, constructors and destructors just like a class. It can even have private and protected sections, you just have to explicitly declare them in the same way you have to explicitly declare a public section in a class.

So yes, the approach I suggest would work perfectly well with your approach. You should really consider dumping the typedef stuff though since it serves no purpose in C++ except to provide backwards-compatibility with legacy C code. This is completely equivalent to your declaration (I've added a GetRect() member):


struct OBJECTS_OBSTACLES {
int pos_x; // the x position on the map
int pos_y; // the y position on the map
int map_pos_x;
int map_pos_y;
int destroy;
int push;
int v_y;
int block;
OBJECTS_OBSTACLES *next_object;

Rect GetRect(){ return Rect(pos_x,pos_y,64,64); }
};









I also have to suggest that you consider using the C++ file stream objects as well as they are a lot more concise and typesafe.


bool LoadObjects(const std::string &Path)
{
std::ifstream is(Path.c_str()); if(!is.is_open()) return false;

for(int i=0;i<num_objects;++i)
{
OBJECT_OBSTACLES *O=newObject();
// I assume your newObject() function stores the object as well as creating it

is >> O->pos_x >> O->pos_y >> O->map_pos_x; // etc
}

return true;
}







Even better would be to create an extractor function for your object:


// this would sit with your class definintion and get updated as the class changes
std::ifstream &operator>>(std::ifstream &is,OBJECT_OBSTACLES &O)
{
is >> O.pos_x >> O.pos_y >> O.map_pos_x; // etc
return is;
}

// this can sit elsewhere and is now independent of the details of the object class
bool LoadObjects(const std::string &Path)
{
std::ifstream is(Path.c_str()); if(!is.is_open()) return false;

for(int i=0;i<num_objects;++i)
{
OBJECT_OBSTACLES *O=newObject();

is >> *O;
}

return true;
}







This seperates out the loading of a single object from the mechanics of loading a variety of objects.

Share this post


Link to post
Share on other sites
so I can just create a Rect
ie


Rect E;
Rect F;

E=temp_ptr->GetRect();
E=temp_ptr_2->GetRect();


and test them using the Intersect(routine)?


Intersect(E,F);




Is there more too it because looking at your examples, and I'm just wondering were does the IsIn function get called?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement