问题
I am making a physics engine in c# / XNA, I have three basic objects...
Sphere Cube Plane
that are all derived from
GameObject
I store all my objects in a list of GameObjects and I would like to loop through this list and be able to call a CheckCollision function that will go to the correct function for each pair of objects
eg
go is a Sphere,
go2 is a Sphere
if(CheckCollision(go, go2))
{
//do stuff
}
bool CheckCollision(Sphere one, Sphere two)
{
//Check Sphere to Sphere
}
bool CheckCollision(Sphere sphere, Plane plane)
{
//Check Sphere to Plane
}
and I would like it to just go to the correct function withour having to use if checks.
Thank you.
回答1:
You could use virtual dispatch:
abstract class GameObject
{
abstract bool CheckCollision (GameObject other);
abstract bool CheckCollision (Sphere other);
abstract bool CheckCollision (Cube other);
abstract bool CheckCollision (Plane other);
}
class Sphere : GameObject
{
override bool CheckCollision (GameObject other) { return other.CheckCollision(this); }
override bool CheckCollision (Sphere other) { /* ... implementation ... */ }
override bool CheckCollision (Cube other) { /* ... implementation ... */ }
override bool CheckCollision (Plane other) { /* ... implementation ... */ }
}
class Cube : GameObject
{
override bool CheckCollision (GameObject other) { return other.CheckCollision(this); }
override bool CheckCollision (Sphere other) { /* ... implementation ... */ }
override bool CheckCollision (Cube other) { /* ... implementation ... */ }
override bool CheckCollision (Plane other) { /* ... implementation ... */ }
}
class Plane : GameObject
{
override bool CheckCollision (GameObject other) { return other.CheckCollision(this); }
override bool CheckCollision (Sphere other) { /* ... implementation ... */ }
override bool CheckCollision (Cube other) { /* ... implementation ... */ }
override bool CheckCollision (Plane other) { /* ... implementation ... */ }
}
EDIT
Consider what happens when you have this:
GameObject go1 = new Sphere();
GameObject go2 = new Cube();
bool collision = go1.CheckCollision(go2);
- The call goes to the abstract GameObject.CheckCollision(GameObject) method on the sphere.
- Virtual dispatch means that we go to Sphere.CheckCollision(GameObject)
- Sphere.CheckCollision(GameObject) calls the abstract GameObject.CheckCollision(Sphere) method on the cube.
- Virtual dispatch means that we go to Cube.CheckCollision(Sphere)!
Therefore, no type-checking if
statements are necessary.
EDIT 2
See Eric Lippert's answer at https://stackoverflow.com/a/2367981/385844; the first option -- the visitor pattern -- is essentially the approach outlined above. Eric's other answer at https://stackoverflow.com/a/9069976/385844 also discusses this issue.
回答2:
I fear that this is not possible, unless you approximate your shapes with polygons, which would allow a generic approach. If you work with the exact mathematical representations then you will need to have special solutions for the different pairings. If you give numbers to the different shape types (1, 2, 3) you could represent a pair with 10* go.Number + go2.Number
and use this number in a switch statement.
Note also that your approach has an O(n^2) performance where n
is the number of objects. Consider using a more appropriate data structure than a list. K-D-trees are often used in order to store objects in a k-dimensional space. They are often used in conjunction with bounding boxes of the graphical objects. Each object would have a method or property yielding a bounding box. K-D-trees would reduce the number of required collision checks. See k-d tree on Wikipedia.
来源:https://stackoverflow.com/questions/9164612/using-generic-functions-for-collision-detection-in-c-sharp-xna