Handling Collision Response

A place for people with an interest in developing new shmups.
Post Reply
SleepMachine
Posts: 8
Joined: Tue Nov 15, 2005 11:20 am
Location: Pite, Sweden
Contact:

Handling Collision Response

Post by SleepMachine »

I'm wondering how, in general, collision-response is handled in shmups. I've had quite a few problems with my ideas.

I was thinking that i'd have (somewhat simplified in this example) a base class called Collider that all class that might use collisions will inherit from. All "colliders" will be managed by a class that can tell if two colliders has collided.

The (somewhat advanced) problem for me occurs at this point when i know that two colliders have collided, but i have to know that types they really are. For instance: a collision between my ship and an enemy ship might cause me and the enemy to blow up, but a collision between my bullets and an enemy will only damage the enemy. The responses for collisions of different types my wary a lot more than this though, but i think you get the point.
So, i need to find out the classes of the two colliders.

I saw no good solution for this until i read an article (Item 31 in 'More Effective C++' if someone's interested) about this type of problem (commonly known a double-dispatching).

There are many different uses of RTTI that you can implement to solve this. But they all seem quite complicated or unmanagable (although i can probably pull it off now) for something that seems so simple. How complicated can collision responses in schmups really be if they've been around since the 80's? (That's almost pre-C++, right?)

I hope someone here has some good ideas.
Last edited by SleepMachine on Thu Dec 01, 2005 4:55 pm, edited 1 time in total.
User avatar
shiftace
Posts: 435
Joined: Tue Jan 25, 2005 10:18 pm
Location: yes

Post by shiftace »

Well, you can fake RTTI by adding a member to everything, and let that member store some type info, like maybe enum {player ship, player shot, enemy ship, enemy shot, powerup}. Or you can declare an array of each object type when the program starts, and the fact that they're in different arrays lets you select everything of one type. From there, for every collision type, you just need to check the locations of everything in 2 arrays (hah). I don't know if that's actually what gets done, but I think it maps pretty easily into ASM. I'm inclined to assume most shmups were written in ASM until late '90s.

(Just a thought; I don't know what the Right Thing really is here.)
"Can they really get inside my head?"
"As long as you keep an open mind."
SleepMachine
Posts: 8
Joined: Tue Nov 15, 2005 11:20 am
Location: Pite, Sweden
Contact:

Post by SleepMachine »

shiftace wrote:Well, you can fake RTTI by adding a member to everything, and let that member store some type info, like maybe enum {player ship, player shot, enemy ship, enemy shot, powerup}.
if one would do like this. (in my case add that enum to the collider-class) that would mean that every time i add a new kind of collidable object, i would have to modify that enum, and thus recompile all the classes derived from Collider. That, i'd rather avoid.
shiftace wrote: Or you can declare an array of each object type when the program starts, and the fact that they're in different arrays lets you select everything of one type. From there, for every collision type, you just need to check the locations of everything in 2 arrays (hah). I don't know if that's actually what gets done, but I think it maps pretty easily into ASM. I'm inclined to assume most shmups were written in ASM until late '90s.

(Just a thought; I don't know what the Right Thing really is here.)
This is slightly better. by having a CollisionManager that owns one array of every type of collider in existance could save you from having to re-compile the objects. However, then that manager would need to have functions like
AddCollider(Ship* c)
AddCollider(Bullet* c)
and so forth, for everything. (to put them in their appropriate arrays)

So this manager would have to be updated with atleast a new function or two, to be able to process new types of objects.
It requires some maintenance but is quite a simple solution.

But keep posting ideas! :D i always respect feedback.
User avatar
shiftace
Posts: 435
Joined: Tue Jan 25, 2005 10:18 pm
Location: yes

Post by shiftace »

Now that I have thought about this some more, I wonder if you're making the problem too hard. Are there really going to be a lot of collision types? E.g., if you do have 5 classes that inherit from Collidable, maybe called PlayerShip, PlayerBullet, EnemyShip, EnemyBullet, and Powerup, will there be anything that behaves differently from one of those types?

You don't need to have different types of enemy bullet inherit from Collidable; you could have them inherit from EnemyBullet, or you could make their class be EnemyBullet and then design the EnemyBullet class to have enough state to represent different types of bullet.

In fact, I think this last way might be the best way, since it allows you to specify behaviors in a script file, and you can edit the script file with no extra coding at all. Also, I think it corresponds well to a game engine.
"Can they really get inside my head?"
"As long as you keep an open mind."
SleepMachine
Posts: 8
Joined: Tue Nov 15, 2005 11:20 am
Location: Pite, Sweden
Contact:

Post by SleepMachine »

well, i solved the problem in the way i first described. I totally see your point with me making things harder than it should be, and i don't disagree. i do that sometimes. :)

However, i also wanted the experience in creating a system that is truly scalable. (since i'm a educated game-programmer). I also wanted to understand the difficulties that followed.

:wink:
User avatar
oNyx
Posts: 28
Joined: Wed Dec 14, 2005 12:58 pm

Post by oNyx »

I just keep different things seperated and do collisions based on rules. Like...

player(s) vs enemies
player(s) vs enemy bullets
player(s) vs items
player bullets vs enemies
player bullets vs screen (prune)
enemy bullets vs screen (prune)

Its fast and simple and it also allows you to check how much time you spend with that stuff each frame. This allows you to compare how well different strategies work. Eg it could be worth to try some smarter approach for that player bullets vs enemies bit. Well, eventually... but if you can compare different approaches its easy to decide.
chalky
Posts: 9
Joined: Wed Feb 22, 2006 9:50 am

Post by chalky »

you could have thought about using a void pointer to the object.
User avatar
SAM
Posts: 1788
Joined: Fri Jun 03, 2005 5:27 am
Location: A tiny nameless island in South China Sea

Post by SAM »

Well, old shmups games were written in assember.

For collisions deteaction, you should go this way:

If everthing on screen got a retengular hit box or consist of several retengular hit boxes, thing would be simplier. All enemy, enemy shots, player ship, player shot, on screen item are inhert from a class which got the size and on screen coordate as properties.

Write a function to check for collistion of two retengles.

Then in each film, you only need to detact collision with the player's ship and all player shot.

In loop all enemy, enemy shots & on screen items against the player ship.

Then loop all enemy againest all player shoots.

Sound simple?

I think in the past, the assember age, the progemmers put all that in predefined arrays, so there are limits of on screen bullets.

The only problem I cannot figure out is how control the speed of the game?

If there is too much items on screen, flam rate drops. But if there are too fews, how do you control the speed, so the game won't go over 60 fps?
*Meow* I am as serious as a cat could possible be. *Meow*
User avatar
oNyx
Posts: 28
Joined: Wed Dec 14, 2005 12:58 pm

Post by oNyx »

SAM wrote:[...]
If there is too much items on screen, flam rate drops. But if there are too fews, how do you control the speed, so the game won't go over 60 fps?
Well, with a) throtteling or b) time based movement.

With arcade or console games its none of the above. They simply rely on vsnyc (you cannot exceed the refreshrate).

You cant rely on vsync on PCs, because its up to the driver to handle that (the user can set it to "always off" for example).
Post Reply