的。因此,让我们用概述初始化collisionMap的两种方法来结束。
就不得不永远留着它。如果我们想在游戏运行过程中增加、删除或修改碰撞处理函数,将怎么样?不提供。
但是是可以做到的。我们可以将映射表放入一个类,并由它提供动态修改映射关系的
成员函数。例如:
class CollisionMap {public:
typedef void (*HitFunctionPtr)(GameObject&, GameObject&);
void addEntry(const string& type1,
const string& type2,
HitFunctionPtr collisionFunction,
bool symmetric = true); // see below
void removeEntry(const string& type1, const string& type2);
HitFunctionPtr lookup(const string& type1, const string& type2);
static CollisionMap& theCollisionMap();
// these functions are private to prevent the creation of multiple maps
CollisionMap();
CollisionMap(const CollisionMap&);
};
这个类允许我们在映射表中进行增加和删除操作,以及根据类型名对查找相应的碰撞
处理函数。限制CollisionMap对象的个数为1,因为我们的系统中只有一个映射表。 (更复杂的游戏需要多张映射表是可以想象到的。 )最后,它允许我们简化在映射表中增加对称性的碰撞(也就是说,类型T1的对象撞击T2的对象和T2的对象撞击T1的对象,其效果是相同的。 )的过程,它自动增加对称的映射关系,只要addEntry被调用时可选参数symmetric 被设为true。
void shipAsteroid(GameObject& spaceShip, GameObject& asteroid);
CollisionMap::theCollisionMap().addEntry("SpaceShip", "Asteroid", &shipAsteroid);
CollisionMap::theCollisionMap().addEntry("SpaceShip", "SpaceStation", &shipStation;
void asteroidStation(GameObject& asteroid, GameObject& spaceStation);
CollisionMap::theCollisionMap().addEntry("Asteroid", "SpaceStation", &asteroidStation);...
在构造函数中进行确认。这将导致在运行期的一个小小的性能开销。另外一个方法是创建一个RegisterCollisionFunction 类:
class RegisterCollisionFunction {
public:
RegisterCollisionFunction(
const string& type1,
const string& type2,
CollisionMap::HitFunctionPtr collisionFunction,
bool symmetric = true) {
CollisionMap::theCollisionMap().addEntry(type1, type2, collisionFunction, symmetric);
}
};
RegisterCollisionFunction cf1("SpaceShip", "Asteroid", &shipAsteroid);
RegisterCollisionFunction cf2("SpaceShip", "SpaceStation", &shipStation);
...
int main(int argc, char * argv[])
{
...
}
被调用前就加入映射表了。如果以后增加了一个派生类
class Satellite: public GameObject{
...
};
void satelliteShip(GameObject& satellite, GameObject& spaceShip);
void satelliteAsteroid(GameObject& satellite, GameObject& asteroid);
RegisterCollisionFunction cf4("Satellite", "SpaceShip", &satelliteShip);
RegisterCollisionFunction cf5("Satellite", "Asteroid", &satelliteAsteroid);
这不会改变实现多重调度没有完美解决方法的事实。 但它使得容易提供数据给基于map的实现,如果我们认为这种实现最接近我们的需要的话。