四、自行仿真虚函数表格(使用非成员函数的碰撞处理函数)
//GameObject.h
#ifndef GAMEOBJECT_H
#define GAMEOBJECT_H
class GameObject{ //抽象基类
public:
virtual ~GameObject() = 0;
};
class SpaceShip : public GameObject{ //宇宙飞船类
public:
virtual ~SpaceShip();
};
class SpaceStation : public GameObject{ //太空站类
public:
virtual ~SpaceStation();
};
class Asteroid : public GameObject{ //小行星类
public:
virtual ~Asteroid();
};
class UnkonwnCollision{//异常类
public:
UnkonwnCollision(GameObject& whatWeHit1, GameObject& whatWeHit2);
};
#endif
//GameObject.cpp
#include"GameObject.h"
#include<iostream>
GameObject::~GameObject(){}
SpaceShip::~SpaceShip(){}
SpaceStation:: ~SpaceStation(){}
Asteroid::~Asteroid(){}
UnkonwnCollision::UnkonwnCollision(GameObject& whatWeHit1, GameObject& whatWeHit2){
std::cout << "异常类" << std::endl;
}
//collision.h
#ifndef COLLISION_H
#define COLLISION_H
#include "GameObject.h"
#include<string>
#include<map>
#include<iostream>
namespace{
//主要的碰撞处理函数
void shipStation(GameObject& spaceShip, GameObject& spaceStation){
std::cout << "SpaceShip<=>SpaceStation" << std::endl;
}
void shipAsteroid(GameObject& spaceShip, GameObject& asteroid){
std::cout << "SpaceShip<=>Asteroid" << std::endl;
}
void stationAsteroid(GameObject& spaceStation, GameObject& asteroid){
std::cout << "SpaceStation<=>Asteroid" << std::endl;
}
void shipShip(GameObject& spaceShip1, GameObject& spaceShip2){
std::cout << "SpaceShip<=>SpaceShip" << std::endl;
}
void stationStation(GameObject& spaceStation1, GameObject& spaceStation2){
std::cout << "SpaceStation<=>SpaceStation" << std::endl;
}
void asteroidAsteroid(GameObject& asteroid1, GameObject& asteroid2){
std::cout << "Asteroid<=>Asteroid" << std::endl;
}
//对称版本
void stationShip(GameObject& spaceStation, GameObject& spaceShip){
shipStation(spaceShip, spaceStation);
}
void asteroidShip(GameObject& asteroid, GameObject& spaceShip){
shipAsteroid(spaceShip, asteroid);
}
void asteroidStation(GameObject& asteroid, GameObject& spaceStation){
stationAsteroid(spaceStation, asteroid);
}
typedef void(*HitFunctionPtr)(GameObject&, GameObject&); //指向碰撞函数的函数指针
//函数表的类型:每项关联了碰撞函数两个参数的动态类型名和碰撞函数本身
typedef std::map<std::pair<std::string,std::string>, HitFunctionPtr> HitMap;
std::pair<std::string, std::string> makeStringPair(const char* s1,const char* s2);
HitMap* initializeCollisionMap(); 建立函数表
//在函数表中查找需要的碰撞函数
HitFunctionPtr lookup(const std::string& class1, const std::string& class2);
}
void processCollision(GameObject& object1, GameObject& object2){
//根据参数的动态类型查找相应碰撞函数
HitFunctionPtr phf = lookup(typeid(object1).name(), typeid(object2).name());
if (phf)
phf(object1, object2); //调用找到的碰撞处理函数来进行碰撞处理
else
throw UnkonwnCollision(object1, object2); //没有找到则抛出异常
}
namespace{
std::pair<std::string, std::string> makeStringPair(const char* s1, const char* s2){
return std::pair<std::string, std::string>(s1, s2);
}
}
namespace{
HitMap* initializeCollisionMap(){ //创建并初始化虚函数表
HitMap *phm = new HitMap; //创建函数表
//初始化函数表
(*phm)[makeStringPair(typeid(SpaceShip).name(),
typeid(SpaceStation).name())] = &shipStation;
(*phm)[makeStringPair(typeid(SpaceShip).name(),
typeid(Asteroid).name())] = &shipAsteroid;
(*phm)[makeStringPair(typeid(SpaceShip).name(),
typeid(SpaceShip).name())] = &shipAsteroid;
(*phm)[makeStringPair(typeid(SpaceStation).name(),
typeid(Asteroid).name())] = &shipAsteroid;
(*phm)[makeStringPair(typeid(SpaceStation).name(),
typeid(SpaceShip).name())] = &shipStation;
(*phm)[makeStringPair(typeid(SpaceStation).name(),
typeid(SpaceStation).name())] = &shipAsteroid;
(*phm)[makeStringPair(typeid(Asteroid).name(),
typeid(SpaceShip).name())] = &shipAsteroid;
(*phm)[makeStringPair(typeid(Asteroid).name(),
typeid(SpaceStation).name())] = &asteroidStation;
(*phm)[makeStringPair(typeid(Asteroid).name(),
typeid(Asteroid).name())] = &asteroidAsteroid;
return phm;
}
}
namespace{
//根据参数类型名在函数表中查找需要的碰撞函数
HitFunctionPtr lookup(std::string const& class1,
std::string const& class2){
//用智能指针指向返回的函数表,为静态,表示只能有一个函数表
static std::auto_ptr<HitMap> collisionMap(initializeCollisionMap());
HitMap::iterator mapEntry = collisionMap->find(make_pair(class1, class2));
if (mapEntry == collisionMap->end())
return 0; //没找到,则返回空指针
return (*mapEntry).second; //找到则返回关联的碰撞函数
}
}
#endif
//main.cpp
#include"Collision.h"
using namespace std;
int main(){
SpaceShip sp;
SpaceStation ss;
Asteroid ad;
processCollision(sp, ss);
processCollision(sp, ad);
processCollision(sp, sp);
cout << "-----------" << endl;
processCollision(ss, sp);
processCollision(ss, ad);
processCollision(ss, ss);
cout << "-----------" << endl;
processCollision(ad, sp);
processCollision(ad, ss);
processCollision(ad, ad);
system("pause");
return 0;
}
五、自行仿真虚函数表格(使用非成员函数的碰撞处理函数)
//GameObject.h
#ifndef GAMEOBJECT_H
#define GAMEOBJECT_H
class GameObject{ //抽象基类
public:
virtual ~GameObject() = 0;
};
class SpaceShip : public GameObject{ //宇宙飞船类
public:
virtual ~SpaceShip();
};
class SpaceStation : public GameObject{ //太空站类
public:
virtual ~SpaceStation();
};
class Asteroid : public GameObject{ //小行星类
public:
virtual ~Asteroid();
};
class UnkonwnCollision{//异常类
public:
UnkonwnCollision(GameObject& whatWeHit1, GameObject& whatWeHit2);
};
#endif
//GameObject.cpp
#include"GameObject.h"
#include<iostream>
GameObject::~GameObject(){}
SpaceShip::~SpaceShip(){}
SpaceStation:: ~SpaceStation(){}
Asteroid::~Asteroid(){}
UnkonwnCollision::UnkonwnCollision(GameObject& whatWeHit1, GameObject& whatWeHit2){
std::cout << "异常类" << std::endl;
}
//collision.h
#ifndef COLLISION_H
#define COLLISION_H
#include "GameObject.h"
#include<string>
#include<map>
#include<iostream>
//主要的碰撞处理函数
void shipStation(GameObject& spaceShip, GameObject& spaceStation){
std::cout << "SpaceShip<=>SpaceStation" << std::endl;
}
void shipAsteroid(GameObject& spaceShip, GameObject& asteroid){
std::cout << "SpaceShip<=>Asteroid" << std::endl;
}
void stationAsteroid(GameObject& spaceStation, GameObject& asteroid){
std::cout << "SpaceStation<=>Asteroid" << std::endl;
}
void shipShip(GameObject& spaceShip1, GameObject& spaceShip2){
std::cout << "SpaceShip<=>SpaceShip" << std::endl;
}
void stationStation(GameObject& spaceStation1, GameObject& spaceStation2){
std::cout << "SpaceStation<=>SpaceStation" << std::endl;
}
void asteroidAsteroid(GameObject& asteroid1, GameObject& asteroid2){
std::cout << "Asteroid<=>Asteroid" << std::endl;
}
//对称版本
void stationShip(GameObject& spaceStation, GameObject& spaceShip){
shipStation(spaceShip, spaceStation);
}
void asteroidShip(GameObject& asteroid, GameObject& spaceShip){
shipAsteroid(spaceShip, asteroid);
}
void asteroidStation(GameObject& asteroid, GameObject& spaceStation){
stationAsteroid(spaceStation, asteroid);
}
#endif
//CollisionMap.h
#ifndef COLLISIONMAP_H
#define COLLISIONMAP_H
#include "GameObject.h"
#include <string>
#include <memory>
#include <map>
class CollisionMap{ //碰撞函数映射表
public:
typedef void(*HitFunctionPtr)(GameObject&, GameObject&); //指向碰撞函数的函数指针
//函数表的类型:每项关联了碰撞函数两个参数的动态类型名和碰撞函数本身
typedef std::map<std::pair<std::string, std::string>, HitFunctionPtr> HitMap;
//根据参数类型名称向映射表中加入一个碰撞函数
void addEntry(const std::string& type1, const std::string& type2,
HitFunctionPtr collisionFunction, bool symmetric = true);
//根据参数类型名称从映射表中删除一个碰撞函数
void removeEntry(const std::string& type1, const std::string& type2);
//根据参数类型名称在函数映射表中查找需要的碰撞函数
HitFunctionPtr lookup(const std::string& type1, const std::string& type2);
static CollisionMap& theCollisionMap();//返回唯一的一个碰撞函数映射表
private:
std::auto_ptr<HitMap> collisionMap; //函数映射表,用智能指针存储
//构造函数声明为私有,以避免创建多个碰撞函数映射表
CollisionMap();
CollisionMap(const CollisionMap&);
};
CollisionMap::CollisionMap() : collisionMap(new HitMap){}
//根据参数类型名称向映射表中加入一个碰撞函数
void CollisionMap::addEntry(const std::string& type1, const std::string& type2,
HitFunctionPtr collisionFunction, bool symmetric){
if (lookup(type1, type2) == 0) //映射表中没找到时插入相应条目
collisionMap->insert(make_pair(make_pair(type1, type2), collisionFunction));
}
//根据参数类型名称从映射表中删除一个碰撞函数
void CollisionMap::removeEntry(const std::string& type1, const std::string& type2){
if (lookup(type1, type2) != 0) //若找到,则删除该条目
collisionMap->erase(make_pair(type1, type2));
}
//根据参数类型名称在函数映射表中查找需要的碰撞函数
CollisionMap::HitFunctionPtr CollisionMap::lookup(const std::string& type1, const std::string& type2){
HitMap::iterator mapEntry = collisionMap->find(make_pair(type1, type2));
if (mapEntry == collisionMap->end())
return 0; //没找到,则返回空指针
return (*mapEntry).second; //找到则返回关联的碰撞函数
}
//返回唯一的一个碰撞函数映射表
CollisionMap& CollisionMap::theCollisionMap(){
static CollisionMap cm;
return cm;
}
void processCollision(GameObject& object1, GameObject& object2){
//根据参数的动态类型查找相应碰撞函数
CollisionMap::HitFunctionPtr phf = CollisionMap::theCollisionMap().lookup(typeid(object1).name(), typeid(object2).name());
if (phf)
phf(object1, object2); //调用找到的碰撞处理函数来进行碰撞处理
else
throw UnkonwnCollision(object1, object2); //没有找到则抛出异常
}
#endif
//RegisterCollisionFunction.h
#ifndef REGISTERCOLLISONFUNCTION_H
#define REGISTERCOLLISONFUNCTION_H
#include"CollisionMap.h"
#include<string>
class RegisterCollisionFunction{
public:
RegisterCollisionFunction(const std::string& type1, const std::string& type2,
CollisionMap::HitFunctionPtr collisionFunction, bool sysmetric = true){
CollisionMap::theCollisionMap().addEntry(type1, type2, collisionFunction, sysmetric);
}
};
#endif
//main.cpp
#include"Collision.h"
#include"RegisterCollisionFunction.h"
using namespace std;
RegisterCollisionFunction cf1("class SpaceShip", "class SpaceShip", &shipShip);
RegisterCollisionFunction cf2("class SpaceShip", "class SpaceStation", &shipStation);
RegisterCollisionFunction cf3("class SpaceShip", "class Asteroid", &shipAsteroid);
RegisterCollisionFunction cf4("class SpaceStation", "class SpaceStation", &stationStation);
RegisterCollisionFunction cf5("class SpaceStation", "class SpaceShip", &stationShip);
RegisterCollisionFunction cf6("class SpaceStation", "class Asteroid", &stationAsteroid);
RegisterCollisionFunction cf7("class Asteroid", "class Asteroid", &asteroidAsteroid);
RegisterCollisionFunction cf8("class Asteroid", "class SpaceShip", &asteroidShip);
RegisterCollisionFunction cf9("class Asteroid", "class SpaceStation", &asteroidStation);
int main(){
SpaceShip sp;
SpaceStation ss;
Asteroid ad;
processCollision(sp, ss);
processCollision(sp, ad);
processCollision(sp, sp);
cout << "-----------" << endl;
processCollision(ss, sp);
processCollision(ss, ad);
processCollision(ss, ss);
cout << "-----------" << endl;
processCollision(ad, sp);
processCollision(ad, ss);
processCollision(ad, ad);
system("pause");
return 0;
}