Sign in to follow this  

opinions on collision / draw sorting in a top down 2d RPG

This topic is 4863 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

hi, ive been working on a 2d RPG in C++ for 4 months or so now. anyway, ive been working on some of the hardest part - Collision between characters and draw sorting. by draw sorting, i mean things are drawn correctly depending on the Y axis. IE, a character can stand below another character, and the one above will be drawn "behind" the one below. Collision is just the 2 characters colliding properly and responding to the collision. the first method ive been trying for the past week to get working, is this: - make a class : Render_Object. has a method virtual void Render(). have my npc, player, and enemy class inherit from this. - have my Tile class have a member - Render_Object *ocupant. now, i already have pathfinding implemented. so each frame, if a character has a path to walk, he moves towards the next step in his path. so basically, i will do this each frame: -if a character has a path to walk, mark the tile he is moving towards with his pointer, and un-mark the tile hes standing on -if a character has no path to walk, and is just standing still, just mark the tile hes standing on with his pointer. then, each frame, i draw my screen tile by tile, row by row, starting from the top and working down. my loop would look like this on the inside: draw_tile(map[y][x]); if(map[y][x]->ocupant != NULL) map[y][x]->ocupant.Render(); so, this would sort everything! now, for collision, i just do this: -when calculating my path, dont consider nodes which are occupied. -each time i step, check if the tile im stepping towards is occupied. if so, re-calculate my path. all of this should work in theory, no? ive been trying to implement it for the past week, but am going through hell trying to get it to work. mainly the characters pointer seems to ocupy more then one tile at a time at points, screwing everything up. basically this method depends heavily on Pathfinding to work. theres no collision detection / response at all. the pathfinder just doesnt allow you to walk into walls / other characters. in fact, all movement would be required to use the pathfinder, even arrow-key movement would just calculate the path for the adjacent tile =). theres one alternative solution: -stick all my Render_Objects into a std::list. -.sort() the list on the Y axis -render each object in the list this will sort everything, and should work great. the problem comes with collision. i would use bounding box, im guessing. but how do i allow one character to stand "behind" the other, if that happends, they will collide since there sprites will be colliding. so i was thinking that, instead of the characters bounding box be their sprite, it would be only a lower portion of their sprite. then a character could stand below / above another, plus a character could stand "in front" of a building, etc. but would this work smoothly? my main concern for the second method is collision D. how do i do collision detection / response? i mean, sure, its easy to detect if 2 characters are colliding, but then what? how do i respond to it in a nice, subtle way, putting the character where they are suposed to be? it seems very difficult. so, what do you think? should i give up on my first method, and try to get the second method to work? basically, the first method is collision avoidance and automatic sorting, which basically depends on using pathfinding for all movement. and the second method is collision detection / response and sorting by the Y axis, and wouldnt need pathfinding to work. im guess the second method would be slightly less efficent, but at this point it seems like it would be easier to implement. oh, and any alternatives are welcome. ive been checking out old Genesis RPG's, and cant for the life of me figure out how the hell they had perfect sorting / collision / pathfinding.

Share this post


Link to post
Share on other sites
Hmm.. just to toss out some ideas (not sure I understood everything you were concerned about)...

As far as draw sorting goes, you could always layer your approach. By layers I mean having multiple drawing layers. Things with less priority would be lower on the list (think of it in terms of a ladder, maybe), so lower things would be drawn first, and therefore appear under or behind things with higher priority. Lists/vectors would handle this fine.

As for collision, you could do it in the exact same way. Use collision layers, maybe. Where some things collide with others, but are immune to eachother. As far as response goes, you could use a slot/signal approach, state machine/messaging system, or something of that nature.

When something collides, tell it has collided, and call it's on_hit() routine, and make it do whatever is necessary. In the case of a guy walking around town, if he collides with a building/tile/whatever, tell him to not move into it, and move him just outside the rect of whatever he just tried to move into.

There's quite a bit of documentation on using step ahead vectors for determining intersection with objects (usually only a concern with very fast moving objects). Otherwise, an old rect intersection and puttin it back at it's old location should be pretty good?

Not sure if any of this helps!

edit: typos, etc.

Share this post


Link to post
Share on other sites
I had a hard time understanfing all that but what i think you are asking is: "how do i get a 3D feel with a 2D game?" (allowing players to stand behind each other and such)

I think the best example would be good ol' Double Dragon. The hit detection works (i assume) if you within a reasonable distance of the other player on the Y axis. If you were not lined up with the other guy, your punches and kicks would not hit. The same is true of other similar games like Secret of Mana and Final Fight.

I think your Y-sorting trick would work fine if it's trully tile based. What i did for my last strategy game project was loop through all the tiles and draw each componant of the tile including the playing pieces.

instead of


foreach tile (list of tiles) {
DrawBackground();
}

foreach tile (list of tiles) {
DrawOccupant();
}


I would do this:



foreach tile (list of tiles) {
DrawBackground();
DrawOccupant();
}


If the occupant is always centered on the tile that works or is off on the Y axis. If he overlaps horizontally, it does not work.

Share this post


Link to post
Share on other sites
@catch
thanks for youre reply. its the on_hit() function im worried about. also, structuring it all. basically, i dont understand how to do collision detection / reaction to all my characters... im guessing i will have to do something like this:

make a Collision_Object class. have it store : x , y, w, h. or better yet, i could just have my Collision_Object class have a single function - Get_Rect(). it will return the rectangle that represents the objects collision information.

now, i have player, npc, and enemy inherit from this. then i have a "master list" of collision objects. each frame, after (or before?) i Update() all of my objects, i should loop through all my collision objects, and do collision detection / reaction. im just not sure how exactly to do this....

@leavoia

thats the approach im trying now, but its not working too well. im starting to seriously consider swithcing, as ive been working for a week battling bugs and getting nowhere. this leaves me back to my original problem, how to do collision reaction to all my objects. also, i dont want to check each object against each object, IE, check A against B, but dont check B against A again since its already happend... to be honest, the draw sorting should be extremely easy to do, just stick all my characters in a master list and call .sort() each frame... its this collision that scares me...

thanks again guys for any further help

Share this post


Link to post
Share on other sites
I've torn my collision scheme apart and put it back together again several times now and i'm getting pretty good at it. If you need specific collision help you can email me. I'll let you know that i'm reorganizing my PollingEngine to accomidate the collision detection, so that may be important to you. Basically, it will go like this now:

1) Update() all objects
2) Check For collisions
3) Regress any object positions if they hit a wall or whatever
4) Draw() all objects

Update() and Draw() will now be handles by my PollingEngine, but collision is handled through a seperate collision list much like my polling objects are.

There are lot of slick tricks i've put together to limit collision checking, but it depends somewhat on your game layout. Since your game is tile-based, that makes it much simpler than what i'm currently doing. The only thing you really need to keep track of is active moving objects (like players).

Other timesavers include:

- Don't check A::B and B::A too. you can do that by:

Collide( Thing* A, Thing* B ) {
if ( A < B ) { /* do collision check */ }
}


This relies on the use of pointers. it prevents you from checking each other and also from checking yourself.

- Don't check passive non-moving objects against other passive objects. If object A is not moving and object B isn't either, of course they don't collide!

- Don't check stupid things like bullets versus other bullets. Give each object a collision_type and sort them somehow.

- Use spatial partitioning. Since you are using a tile map, that's already done for you!

Share this post


Link to post
Share on other sites
For my last shooter game I used a simple collision system (was just a shooter game!), but I'll be doing collision for an RPG type game soon-ish (in a month maybe), so I haven't thought too deeply on it, but here's my at the moment rambles.

In the shooter game I used a layered approach for both my drawing and collision systems. They were nothing but very simple (custom) linked lists. I'd probably abandon that and use STL containers. Anyway, the point is, breaking things up into layers gives you a way to categorize your objects.

My shooter game, for example had a couple collision lists.

1) Friendly list (the player, his bullets, etc)
2) Enemy list (asteroids, baddies, etc).
3) Powerups (can't remember if I got this far :)

All I did was add objects to the lists via their class (on creation), and processed them in my "world" object as a linked list (maybe coulda done it faster, but it was such a small game...) So I wouldn't compare the ship's bullets to its own ship, but I would compare the bullets and the ship to the asteroids, baddies etc. Likewise, I might compare the powerups to the player, but not to the enemies. It really doesn't matter, but that's the main principle.

Now for an RPG, you might have similar layers and compare them against eachother, but it would more complicated, no doubt.

Take for example diablo 2. The allied players can't move through one another, so they are collided against each other, but their spells, projectiles, and other things can pass through everything other than mosters/obstructions. In this system, they may have made a list of friendly projectiles, and not compared it to the lists containing players, but compare the player lists to one another, among everything else.

Does this sort of make sense? All I'm proposing is an organization system, like lists, to function as something like "alliance layers," so bad things bump good things, and good things don't bump other good things.

I guess it's up to you to decide how to make the lists and iterate them.. Of course, there are other ways to do this I'm sure.

One way I could think off the top of my head is just collide EVERYTHING, and have some kind of flags to pick through. Is this an enemy? a blocked passage tile? etc, and handle each accordingly. If you're worried about a lot of duplicated checks, you could always keep a list in every object that makes sure it won't double check a previous collision, but linear searching like that might yield as much speed penalty as just doing the check again (albeit the a double check might produce undesirable results).

In any case, you have to rather predict how much collision will be happening on screen in a "busy" area/time frame, and decide what system would work best for you.

Sorry for the long babble :P

Share this post


Link to post
Share on other sites
thanks a lot for your guys help. i was about to email leavoia, but figured id just post this here instead. anyway, i was gunna start coding this but would like opinions from you guys before i start. i figure my last attempt at this took a week to do before i gave up, this time ill plan a little more.

first, id like to tell you, that object - > wall collision is implemented. ie even have projectile (bullet) - > character collision implemented. since no collision response is needed for this (when a bullet hits you, thats it, the bullets life ends), it was easy to implement bullets colliding with things. but i think id like to throw bullets into this system too, to keep everything grouped togeather, plus right now im doing some sloppy hacks to not check bullets against everything (a bunch of if statements basically, which is ugly).

make a pure virtual class called Collision_Object. have it look like this:


class Collision_Object
{
public:

Collision_Object(){collision_obj_list.push_back(this);}
Collision_Object(const Collision_Object &cpy){collision_obj_list.push_back(this);}
~Collision_Object(){collision_obj_list.remove(this);}

virtual Rect Get_Rect() = 0;

static list<Collision_Object*> collision_obj_list;

static void Cycle();
};





basically, ill keep a "master list" of all collision objects ( the static collision_obj_list). this list will manage itself, IE, all collision objects will register themselves with the list in their contructor, and will remove themselves from the list in their destructur. then ill have another static function which will perform all collision D / reaction, called Cycle.

where Rect is:


struct Rect
{
float x,y,w,h;
};


now have Player, Enemy, and Npc classes inherit from this. for example, i could do this:


Player::Get_Rect()
{
return Rect r(x,y,w,h);
}



now, that i have a "master list" of all collision objects, and can get their Rect info. its time to perform collision. this is where the Collision_Object::Cycle() comes in.


void Collision_Object::Cycle()
{
for(list<Collision_Object*>::iterator i = collision_obj_list.begin(); i != collision_obj_list.end(); i++)
{

for(list<Collision_Object*>::iterator i2 = collision_obj_list.begin(); i2 != collision_obj_list.end(); i2++)
{
if(i == i2)
continue;

do_schtuff_here();

}
}
}






ok, this is as far as i can figure out. right now ill check each object against each other object (except themselves, hence the continue statement). but obviously i dont want to keep it like that, but for now just getting it working is all im concerned about. been thinking about it for a little while and just cant figure out how to do the proper collision detection / reaction. well, detection is easy, just use bounding box to see if the rectangles over-lap. its the reaction i dont understand. how do i re-position the objects so it appears they never collided in the first place? i just dont get that part. also thinking about it more, Collision_Object will probably need to know more then just the Rect, since it will have to at the least re-set the objects position, you know? maybe give the RO a virtual Set_Position() function also.

thanks for any help!!!

Share this post


Link to post
Share on other sites
void Collision_Object::Cycle() {
for(list<Collision_Object*>::iterator i = collision_obj_list.begin(); i != collision_obj_list.end(); i++)
{
for(list<Collision_Object*>::iterator i2 = collision_obj_list.begin(); i2 != collision_obj_list.end(); i2++)
{
if(i == i2)
continue;
do_schtuff_here();
}
}
}



should be

void Collision_Object::Cycle() {
for(list<Collision_Object*>::iterator i = collision_obj_list.begin(); i != collision_obj_list.end(); i++)
{
for(list<Collision_Object*>::iterator i2 = collision_obj_list.begin(); i2 != collision_obj_list.end(); i2++)
{
if( (*i) < (*i2)) { do_schtuff_here(); }
}
}
}



That will save you a lot of trouble. Refer to my earlier post. Also find a zip in your email.

Share this post


Link to post
Share on other sites
hey everyone,

leavoia's source code he sent me was a little over-whealming. well, really over-whealming =). basically, i just need to figure out how to respond to a collision. if 2 bounding boxes collide, how do i responde (ie move them) to it so that it looks like they never collided? keep in mind this can be 2 moving characters... surely there must be someone here who can describe to me how to do this ? thanks for any help!!

[Edited by - graveyard filla on August 22, 2004 3:33:50 PM]

Share this post


Link to post
Share on other sites
Your email account is throwing errors, so here is my partial reply. also note that this subject can be found elsewhere on the forum if you search. It's a pop topic.

------------------

2 boxes overlap. To test their "overlapness", you already know. But for
response, there are a million ways to handle that. Ideally, you want the
response code to be a virtual function.

virtual RespondToCollision( collision_data -or- CollisionObject* );

That is harder than it looks, but if you are only working with boxes, it's a
piece of cake.

First of all, the reason it is a virtual is because not all objects will react
the same way of course. A land mine will explode on contact. Exploding is
it's reaction. A player will repell, an enemy will do damage, a wall of
spikes will inflict damage as well.

If you simply want to repell two objects away from each other, assuming you
already know they collide, find out which edges of the two objects are
closest. Either

- Object A's left edge with Object B's right edge, or
- Object A's right edge with Object B's left edge

same goes for the top and bottom. Find the difference between the two edges
and move each object in the other direction by exactly half that difference
(half for each). Something like that.

You need to decide if the penetration is more vertical or horizontal . If it's
more vertical, move away vertically. same for horizontal. If you do both,
you'll end up with the corners of the two boxes always touching and that's
not quite what you want.

The other cheaper way is the "reset" trick. You'll see this on some games
where you walk into a wall and the whole figure "stutters" back and forth
really quick. What happens is that you move the player and if the player
collides with another object, you reset to the previous pre-moving position.
The reason it's inelegant is that it doesn't work well for fast moving
objects and doesn't allow for "sliding".

For a lot for information, especially if you want to get into 2d polygon
collision, here is some good stuph from Oliii:

Important linky

Share this post


Link to post
Share on other sites
hey leavoia,

im actually making some progress for the first time in awhile! anyway... i got collision working but only when one of the 2 characters are standing still. when both characters are moving, all hells breaks loose. i pretty much just bounce around the screen when i collide with both objects moving. im not sure what im doing wrong. one thing i should note, is it seems to work fine if i collide more on the x axis when both objects are moving. but if the collision is more on the Y axis, it gets screwy.

in psuedo code, this is what i do


-if 2 objects collide.

-first, make 4 pointers - Collision_Object *left, *right, *top, *bottom.
this represents the 2 object which is to the left, to the right, above, or below the other object.

-calculate which object is left, right and top, bottom.

-calculate which way they intersect more. if they intersect more on the Y axis, use the top/bottom pointers
-check if the top guy is the one moving, if so, move him to the edge of the bottom guy
-else if the bottom guy is moving, move him to the edge of the top guy
-else they are both moving. find a middle point and meet there

-else they intersect more on the X axis, so use the left/right pointers
-check if the left guy is moving, if so move him to the edge of the right guy
-else if the right guy is moving, move him to the edge of the left guy
-else they both are moving, meet in the middle.



this system seems to work fine, as long as only one of the 2 objects are moving. if the else if() is executed, IE, both objects are moving, i seem to just bounce around the screen. heres the code:


void Collision_Object::Cycle()
{
for(list<Collision_Object*>::iterator i = collision_objs.begin(); i != collision_objs.end(); i++)
{
for(list<Collision_Object*>::iterator i2 = collision_objs.begin(); i2 != collision_objs.end(); i2++)
{

if(! ( (*i) < (*i2) ) )
continue;

//the left and right collision object in this case
Collision_Object *left , *right , *top , *bottom;

//grab their rect's
Rect o1 = (*i)->Get_Rect();
Rect o2 = (*i2)->Get_Rect();

//if they are colliding, keep going, else continue....
if(!Is_Colliding(o1,o2))
continue;

//find out which is left or right
if(o1.x < o2.x)
{
left = (*i);
right = (*i2);
}
else
{
left = (*i2);
right = (*i);
}

//find out which is the top or bottom
if(o1.y < o2.y)
{
top = (*i);
bottom = (*i2);
}
else
{
top = (*i2);
bottom = (*i);
}

//now, here we calculate which axis they intersect more on. this is the box whos walls are made up of the 2 boxes intersecting
/* _____
| |
__|____|
| |_i__| <------ the box with the i in it is the intersection box. if the width of this box
|____| is bigger then its height, that means the boxes intersect more on the Y axis
*/


float x_intersect = abs( (left->Get_Rect().x + left->Get_Rect().w) - right->Get_Rect().x );
float y_intersect = abs( (top->Get_Rect().y + top->Get_Rect().h ) - bottom->Get_Rect().y);


if(x_intersect < y_intersect)
{
//if the left guy is moving, but the right guy isnt, we have to re-position the guy on the left to the edge
//of the guy on the right. if they are both moving, have them meet in the middle
if(left->Is_Moving() && (!right->Is_Moving()))
left->Set_Position(right->Get_Rect().x - left->Get_Rect().w,left->Get_Rect().y);

else if( (!left->Is_Moving() && right->Is_Moving())) //else if the guy on the right is moving
right->Set_Position(left->Get_Rect().x + left->Get_Rect().w,right->Get_Rect().y);

else if( left->Is_Moving() && right->Is_Moving())
{

float mid = ((left->Get_Rect().x + left->Get_Rect().w) - right->Get_Rect().x) / 2.0f;

left->Set_Position(left->Get_Rect().x - mid,right->Get_Rect().y);
right->Set_Position(right->Get_Rect().x + mid,right->Get_Rect().y);

}

}
else //else they are intersecting more on the Y axis. so do Y reaction
{

//now for top / bottom

//if the guy on top is moving
if(top->Is_Moving() && (!bottom->Is_Moving()))
top->Set_Position(top->Get_Rect().x,bottom->Get_Rect().y - top->Get_Rect().h );

//else if the guy on the bottom is moving
else if( (!top->Is_Moving() && bottom->Is_Moving()))
bottom->Set_Position(bottom->Get_Rect().x,top->Get_Rect().y + top->Get_Rect().h);

else if( top->Is_Moving() && bottom->Is_Moving())
{ //both objects moving -
float mid = ( (top->Get_Rect().y + top->Get_Rect().h) + bottom->Get_Rect().y) / 2.0f;

top->Set_Position(mid - top->Get_Rect().h,top->Get_Rect().x);
bottom->Set_Position(mid,top->Get_Rect().x);
}

}//end else they are intersecting more on Y axis

}//end inner for loop

} //end outer for loop

} //end Collision_Object::Cycle()












please let me know if im even doing any of this right. like i said, it seems to work perfectly if only one of the characters are moving... this is the high-light of that code that is messed up, the part where if( both are moving)


else if( left->Is_Moving() && right->Is_Moving())
{

float mid = ((left->Get_Rect().x + left->Get_Rect().w) - right->Get_Rect().x) / 2.0f;

left->Set_Position(left->Get_Rect().x - mid,right->Get_Rect().y);

right->Set_Position(right->Get_Rect().x + mid,right->Get_Rect().y);

}


------------and if they are intersecting more on the Y ---------


else if( top->Is_Moving() && bottom->Is_Moving())
{ //both objects moving -
float mid = ( (top->Get_Rect().y + top->Get_Rect().h) + bottom->Get_Rect().y) / 2.0f;

top->Set_Position(mid - top->Get_Rect().h,top->Get_Rect().x);

bottom->Set_Position(mid,top->Get_Rect().x);
}






like i said, the side to side collision , IE the top part of the code i just pasted, seems to work fine (although not perfect). its when the collision is on the Y axis and both characters are moving, is when things get messy. that part of the code is the bottom portion of the code i just pasted.

thanks again... BTW, using the < operater, thats very clever man. makes things very simple and never checks 2 things against each other twice. thanks again for any help!

[Edited by - graveyard filla on August 22, 2004 7:30:07 PM]

Share this post


Link to post
Share on other sites
for my game, i'm using movement angles and vectors. For your game it should be fixed directions, so what you can do is just find the direction your guys are moving and "reverse" by however much it takes to get them out of the collision penetration. That might be easier.

Share this post


Link to post
Share on other sites
hmmm.. not sure what you mean, but i think i got it working for the most part.

now, about optimizing and design..

what do you think? as it is now, every Collision_Object is checked against every other CO. now as it stands now, i only put characters into this system. my projectiles (so far bullet, flame, and rocket) manage their own collision. basically, i have a "master list" of all enemies, and i have the player's pointer too.

my Projectile class has 4 functions to deal with this:

Wall_Collision()
Richochet();

Object_Collide();
Hit_Target();

so, each frame of the bullet's life, inside his Update() (Poll) function, i do this:


-check if i hit a wall via Wall_Collision()
-if i hit, call Richochet() (this display particle effect)
-figure out if my target is an enemy / player
-if its an enemy, loop through all enemies in the master list looking for collision via Object_Collide()
-if i hit, call Hit_Target(). this does damage and stuff also
-if its a player, check if i hit the player. call Hit_Target if so


so basically, do you think its sloppy for my projectiles to handle their own collision internally, seperate from the Collision_Object system? should i throw bullets and stuff into this system as well? keep in mind my game is tile based, so collision objects only check themselves against other collision objects, and they would have to do wall collision seperate, inside thier own update(). not to mention character to character collision would never need a Richochet() effect.

thanks for anymore help!

Share this post


Link to post
Share on other sites
Here is sorta the plan i'm using. You need to seperate your collision objects into basic groups like World, Player, Enemy, Player Weapon, Enemy Weapon, NonAligned, and use the "Dispatch" technique.

Each of these needs to react to the others differently. So each of these classes needs to have a function to handle all the others. Each class also implements a default reaction. So that you can inherit CollisionEnemy and still get all the same "enemy" reactions that the CollisionEnemy class has. However, the common base class CollisionObject has a function to handle all of these subcatagories:

Class CollisionObject {
// generic version, uses "Dispatch" technique
bool Collide( CollisionObject* obj ) {
obj->Collide(this);
}

// overloaded specific versions
bool Collide( CollisionObjectWorld* obj );
bool Collide( CollisionObjectPlayer* obj );
bool Collide( CollisionObjectEnemy* obj );
bool Collide( CollisionObjectPlayerWeapon* obj );
bool Collide( CollisionObjectEnemyWeapon* obj );
}


The problem is that adding new major catagories is a pain in the butt (because all inherited classes will need to be modded), but if you don't add any new groups (and you shouldn't need to if well designed), you've got custom reaction code for each major type.

However you don't know which type a vanilla CollisionObject is without using RTTI (and we are not going to either). So you call a function on one object which simply defers to the appropriate specific function of the other object. This works because an object always knows it's own type but not the other's. So instead of YOU telling ME what kind of object you want, I'M telling YOU what kind of object i am. See?

Now you can do this:

If ( CollisionHappensBetween(A,B) ) {
A->Collide(B);
}


Which calls the generic version of the Collide() function, which then defers to the other object's specific Collide() function which contains the appropriate reaction code.

Pretty slick if you ask me.

Share this post


Link to post
Share on other sites
Hm, briefly, I'll explain the layering approach I've been spouting off, if it's of any consequence.

I used to use a mac library called SpriteWorld (www.spriteworld.org). The library itself had a collision system that was based on layers. I find the system to be quite elegant. Though probably far from perfect, it almost always solves most basic collision situations. You could even assign a different level of collision accuracy for each layer, if I recall.

Anyway, when you made a sprite, you'd just drop it into a collision layer (custom data type), and you'd be done with it. There was a callback function that would send the type of object that collided with the sprite, so you could react to it accordingly, making it so you could obviously collide with many different types of objects.

For my asteroids/shooter game I did a similar thing, but with not so much depth. I knew exactly what layers I needed and just hard coded them. I suppose I could have made a custom CollisionLayer class and a class handler to cycle and collide all objects, but that level of detail wasn't necessary at the time.

I do think it's possible to make a system similar to Leia's last purposal, but make it type safe so it functions off of entities and generic objects, rather than type specifics. Or no specific datatype, at all, really.

Also, I've been toying with the idea of using ClanLib's (the API I primarily develop with) signals and slots to handle intersections on the fly, and have no iterating collision routines (would be very fast), however, I can't think of how I might do that at this time.

Though ClanLib has built in outline intersections, so I'm not sure I have anything to worry about at all :) You could read about that more here. I haven't messed with it at all yet, so know little about it.

ClanLib Collision Detection

Of course when I work on my routines in the future I'll be able to tackle this problem in depth, but for now it's all speculation.

Edit: my clumsy fingers...

Share this post


Link to post
Share on other sites
seems pretty nice... so you think i should get rid of my Projectiles collision scheme and instead adopt this system? the weird thing is that Wall collision will still be done seperately from all this. IE, a player and bullet will be a Collision_Object, but inside of that Player::Update and Bullet::Update(), i will still check for collisions with walls. since walls is done different as i use tiles, it has to be seperate, no ? do you think this is weird / bad ?

also, i think ill take catch's suggestion and make seperate lists. similar to the Layers effect with the polling engine. it will look like this:


class Collision_Object
{
public:

enum Collision_Group
{
PLAYER,
NPC,
ENEMY,
PROJECTILE,

NUM_OF_CGS
};



Collision_Object() : collision_objs(NUM_OF_CGS){} //
Collision_Object(const Collision_Object &cpy): collision_objs(NUM_OF_CGS){}
virtual ~Collision_Object(){}

virtual Rect Get_Rect() = 0;
virtual bool Is_Moving() = 0;
virtual void Set_AbsX(float x) = 0;
virtual void Set_AbsY(float y) = 0;

static vector< list<Collision_Object*> > collision_objs;
static void Cycle();
static bool Is_Colliding(const Rect &r1,const Rect &r2);
static void Register(Collision_Object *obj,Collision_Group layer) { collision_objs[layer].push_back(obj);}


};






do you see what im doing here? i will use a layered system, each vector contains a list of collision objects. each list is a layer. i will use the Enum's to index into the vector.

this brings 2 design questions i have. since ill have things on different layers now, that means that i can no longer have the constructor to this class simply add the object to the master list, since each collision_object could very well be in a different list then another.

that means that instead of adding myself to the list automatically in the constructor. instead, ill use the Register() function to register a C_O in the proper layer they belong to. this brings 2 options though:

1) similar to the Polling engine, each time i create a collision object, ill register the pointer with the engine. but this seems

2) instead of registering() each time a pointer is created, i would do it in the constructor for that specific class. so it will be a mix of what i have now and the Polling engine.

so, instead of calling Register() each time i create an object, i was thinking i could just put it in the contructors. for example, i could do this inside the Player constructor:


Player::Player()
{
Collision_Object::Register(this, PLAYER);
}






this way objects will still be registered "automatically" by their constructor, AND i coul have layers.

the weird thing is, why dont i do this with the polling system too then? why am i registering every single object when its created? if i adopt this system with collision objects, you think i should do the same with the polling engine, right? i cant have 2 very similar systems be slightly different, especially if this one is nicer then the old one. i think having the constructor register the object with the world is cleaner then having to do it manually, i mean what if i forget? so you think i should go with this system, then switch the polling engine to have objects register themselves in the constructor of the objects too ?

after this is set up, i would then only check groups against groups that made sence. IE, i would check bullets against all the other groups (but not themselves), players against NPC's / enemys, and then NPC's Enemy's against each other. this would prety much be doing the same exact thing as im doing now though, in fact, the only thing i would be doing is NOT checking bullets against themselves. so is this system even worth it? actually, im gunna do it anyway since its not much extra work.

thanks for anymore help.

Share this post


Link to post
Share on other sites
Quote:

IE, a player and bullet will be a Collision_Object, but inside of that Player::Update and Bullet::Update(), i will still check for collisions with walls. since walls is done different as i use tiles, it has to be seperate, no ? do you think this is weird / bad ?


If you're using a traditional tiling system, it would need to be separate from the entity collision, I would think. As for your projectiles and what not go, ideally they should be all function on the same collision system, lest you over complicate things. Generally speaking, it's probably not a good idea to have several systems performing the same thing. Debugging would be a nightmare ;)

See if you can't consolidate everything into one system. Since tiles are usually fundamentally treated different than sprites, logically they would probably need to be separated anyway. So you would have "tile collision" or "entity collision." Though I think it might be possible to merge the two.

Perhaps making a generic entity (no visual data, doesn't move - just a "region") and creating it in the location of the tile when you place the tile. Then it would function like a normal entity and could be processed to react or have an effect on other entities (players, projectiles), but not need to be draw or otherwise updated.

It's impossible to say how that might fit into your system, but it might be possible.

Share this post


Link to post
Share on other sites
Quote:
the weird thing is, why dont i do this with the polling system too then? why am i registering every single object when its created? if i adopt this system with collision objects, you think i should do the same with the polling engine, right? i cant have 2 very similar systems be slightly different, especially if this one is nicer then the old one. i think having the constructor register the object with the world is cleaner then having to do it manually, i mean what if i forget? so you think i should go with this system, then switch the polling engine to have objects register themselves in the constructor of the objects too ?


That is a good point. The only reason i do not do this is: Would there ever be a time when you would want a polling object NOT registered, i.e. "off camera" or "in waiting"? I can foresee that i might want or need something like that in the future, so i made registration external. That at least gives me the option.

Quote:
after this is set up, i would then only check groups against groups that made sence. IE, i would check bullets against all the other groups (but not themselves), players against NPC's / enemys, and then NPC's Enemy's against each other. this would prety much be doing the same exact thing as im doing now though, in fact, the only thing i would be doing is NOT checking bullets against themselves. so is this system even worth it? actually, im gunna do it anyway since its not much extra work.


Depends on the number of bullets naturally. But you are right, it might be a lot of unnecessary work. The advice i'm giving you is based on my system which goes to great lengths to throw out as many checks as possible since i will have hundreds of collision objects at a time. All my world objects are collidables too, not like your tiles which are already nicely structured into an array.

My system throws out collision checks with the following:

- by space. i only check local objects. You are using tiles, though and this should not be an issue.

- by group. i actually keep a type flag on each object and have a 2D function pointer table that pairs groupings. Pairs which do not have a collision function between them do not get checked.

- by activity. I check only active objects. I do not check static world objects against other non-moving objects. This technique actually throws out a LOT of checks for my game.

- by status. I have included a "checkme" flag in case i do not wish to check collisions (invincibility perhaps)


You might just try the "chevk everybody against everybody" method and see if your system slows down. If it's a problem, do it another way. If it's not, why overcomplicate it?

Share this post


Link to post
Share on other sites

This topic is 4863 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.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this