28
\$\begingroup\$

Think of a bullet and an enemy, or the player and the floor. If these objects interact, what holds the interaction code?

\$\endgroup\$
2
  • 2
    \$\begingroup\$ Interact in what way? Do you mean collision detection? If so then it's most likely that you would implement both a collision detection class and a collision resolution manager. \$\endgroup\$
    – Zack Brown
    Jun 14, 2013 at 12:56
  • \$\begingroup\$ Partly yes, i'm interested in both the collision and what happens after the collision. Does the bullet check if it's close to the enemy, or the other way around? And what happens after the collision, can a bullet object just tell an enemy object it's got hit? As you can see i'm fairly confused about the whole thing, and it makes for some very hard to read code. \$\endgroup\$
    – ThatOneGuy
    Jun 14, 2013 at 13:27

4 Answers 4

23
\$\begingroup\$

TL;DR:

Your game objects do not know about each other, nor do they perform checks against other objects. You create a collision detection and collision resolution pattern that checks your game objects and performs the appropriate actions to simulate your game physics.

The Good Stuff

From previous attempts at writing collision detection and reading this book, there are two stages for collision detection and collision resolution. The first stage (collision detection) is an early-out pass where you determine if two objects may have a potential collision. Should any two objects form a potential collision, you then pass these objects into the second stage (collision resolution) to run a more fine grained check against the objects and attempt to resolve the collision.

Somewhere in your engine/game, you will hold an array of all the objects in your world. On each frame you would loop though the array and check each object against every other object with a simple bounding box/sphere collision detection.

Pseudocode:

dectectCollisions(objects)
{
    for(objectA in objects)
    {
        for(objectB in objects)
        {
            if(objectA != objectB) //ignore self
            {
                if(BoundingSpheresIntersect(objectA, objectB))
                {
                    collisionResolver.addObjects(objectA, objectB);
                }
            }
        }
    }
}

This kind of loop is rather inefficient but does leave room for improvement via use of spatial partitioning as an early-out for objects that are guaranteed to be too far apart to collide.

After checking the two objects for a potential collision (i.e. both objects are close enough to collide), the objects are passed off to perform a more precise collision detection routine.

Imagine you have two polygons of random shapes and sizes that are close enough to potentially intersect but do not due to their geometry:

Image found via google

Using bounding spheres, these two objects would create a false positive for a potential collision. This is where you would then perform a more thorough pass to determine whether the two objects do actually intersect.

Once you have found a true collision, your collision resolution step would then perform the appropriate action to resolve the objects by applying forces or moments depending on the granularity and needs of your game physics.

With this in mind, you can abstract the entire process of collision detection and resolution so that your objects need not know anything about each other, nor the process required to determine and resolve collisions. The two classes/managers that handle this for you only need to know the basic properties of each object to perform a quick and dirty check for collisions and then a more thorough check should it be required.

\$\endgroup\$
1
  • 2
    \$\begingroup\$ In particular, the Mediator design pattern would be appropriate. The Observer pattern would be a good alternative , which has a very different intent. You can get a pretty good summary of them on this Stackoverflow post. \$\endgroup\$
    – kurtzbot
    Jun 14, 2013 at 17:17
12
\$\begingroup\$

One way Unreal Engine 3 handles it:

The bullet gets a collision message saying it hit something, with an argument telling it what it hit. It can then call objectHit.takeDamage(self). The target then gets the TakeDamage message, with a pointer to the thing that hit it, and takes the appropriate action.

I personally like this approach because it means the bullet can take special actions (like making some sort of explosion effect depending on the type of thing hit) and the target can take special actions depending on the type of bullet.

It's also possible that the bullet knows what it does to targets, and can call function on it, like objectHit.freeze(self). Then the target knows it got hit by something that freezes it, and what kind of object that was.

EDIT: This answer is meant as a general picture of how it can work, since you're probably not working with UE3. :)

\$\endgroup\$
10
\$\begingroup\$

Thief did this very well in the Dark Engine with Sources and Receptrons. An object could have both of these properties, with different types. For example, a Water arrow would have a Source for WaterStim on contact. An explosion would have an AoE FireStim.

When a Water Arrow hits an object, the target object then searches its Receptrons for anything looking for a WaterStim with the appropriate intensity values. Then it executes whatever command is associated with it (in this case, turning a burning torch to an off torch, and emiting a puff of smoke.)

Since the same engine is used in SystemShock2 this is how all the different damage types are handled, different bullets have different Stims set, and different monsters then have Receptrons for the different Stim types and do damage equal to 1*, 2*, 1/2 the intensity depending on if the ammo type is "super effective" or not.

It seemed like a very flexible system as you could add sources and receptrons to objects in the level editor, (to make a one-off door which opens if hit by fire, say.) While you could also tell a receptron to "send script message" if the object had special scripts associated with it.

What you don't want to do is have to hardcode an nXn interaction matrix of all possible objects colliding with all possible objects! BY generalising interactions through standardised messages, you simplify the process.

\$\endgroup\$
1
  • \$\begingroup\$ From a scripting standpoint, this approach seems the most flexible and the most expressive. Very cool. \$\endgroup\$
    – drhayes
    Jun 18, 2013 at 22:51
-2
\$\begingroup\$

One solution is to keep the containers of bullets and players in separate classes, and then have main() function which keeps the frame loop responsible for interaction.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .