~cpp class GameObject { ... }; class SpaceShip: public GameObject { ... }; class SpaceStation: public GameObject { ... }; class Asteroid: public GameObject { ... };
~cpp void checkForCollision(GameObject& object1, GameObject& object2) { if (theyJustCollided(object1, object2)) { processCollision(object1, object2); } else { ... } }
~cpp dispatch [출발시키다] 다중 프로그래밍 시스템에서 다음에 처리될 작업을 선택하여 실행시키는 것. 즉, 대기 열에서 기다리고 있는 프로세스를 선택하여 중앙 처리 장치의 사용 권한을 부여하는 작업. 출처:한메 myQuickFind 컴용어 사전
~cpp class GameObject { public: virtual void collide(GameObject& otherObject) = 0; ... }; class SpaceShip: public GameObject { public: virtual void collide(GameObject& otherObject); ... };
~cpp // 충돌 객체의 종류를 알수가 없다면, 예외를 던진다. class CollisionWithUnknownObject { // 던질 예외 객체 public: CollisionWithUnknownObject(GameObject& whatWeHit); ... }; void SpaceShip::collide(GameObject& otherObject) { const type_info& objectType = typeid(otherObject); // 충돌의 형을 알아 낸다. if (objectType == typeid(SpaceShip)) { SpaceShip& ss = static_cast<SpaceShip&>(otherObject); SpaceShip-SpaceShip 간의 충돌 수행; } else if (objectType == typeid(SpaceStation)) { SpaceStation& ss = static_cast<SpaceStation&>(otherObject); SpaceShip-SpaceStation 간의 충돌 수행; } else if (objectType == typeid(Asteroid)) { Asteroid& a = static_cast<Asteroid&>(otherObject); SpaceShip-Asteroid 간의 충돌 수행; } else { throw CollisionWithUnknownObject(otherObject); } }
~cpp class SpaceShip; // 이름 선언 class SpaceStation; class Asteroid; class GameObject { public: virtual void collide(GameObject& otherObject) = 0; virtual void collide(SpaceShip& otherObject) = 0; virtual void collide(SpaceStation& otherObject) = 0; virtual void collide(Asteroid& otherobject) = 0; ... }; class SpaceShip: public GameObject { public: virtual void collide(GameObject& otherObject); virtual void collide(SpaceShip& otherObject); virtual void collide(SpaceStation& otherObject); virtual void collide(Asteroid& otherobject); ... };
~cpp void SpaceShip::collide(GameObject& otherObject) { otherObject.collide(*this); }
~cpp void SpaceShip::collide(SpaceShip& otherObject) { SpaceShip-SpaceShip 간의 충돌을 수행한다.; } void SpaceShip::collide(SpaceStation& otherObject) { SpaceShip-SpaceStation 간의 충돌을 수행한다.; } void SpaceShip::collide(Asteroid& otherObject) { SpaceShip-Asteroid 간의 충돌을 수행한다.; }
~cpp class GameObject { public: virtual void collide(GameObject& otherObject) = 0; ... }; class SpaceShip: public GameObject { public: virtual void collide(GameObject& otherObject); virtual void hitSpaceShip(SpaceShip& otherObject); virtual void hitSpaceStation(SpaceStation& otherObject); virtual void hitAsteroid(Asteroid& otherobject); ... }; void SpaceShip::hitSpaceShip(SpaceShip& otherObject) { SpaceShip-SpaceShip 간의 충돌 수행; } void SpaceShip::hitSpaceStation(SpaceStation& otherObject) { SpaceShip-SpaceStation 간의 충돌 수행; } void SpaceShip::hitAsteroid(Asteroid& otherObject) { SpaceShip-Asteroid 간의 충돌 수행; }
~cpp class SpaceShip: public GameObject { private: typedef void (SpaceShip::*HitFunctionPtr)(GameObject&); static HitFunctionPtr lookup(const GameObject& whatWeHit); ... };
~cpp void SpaceShip::collide(GameObject& otherObject) { HitFunctionPtr hfp = lookup(otherObject); // 호출할 함수를 찾는다. if (hfp) { // 함수를 찾았으면 호출한다. (this->*hfp)(otherObject); } else { throw CollisionWithUnknownObject(otherObject); } }
~cpp class SpaceShip: public GameObject { private: typedef void (SpaceShip::*HitFunctionPtr)(GameObject&); typedef map<string, HitFunctionPtr> HitMap; ... }; SpaceShip::HitFunctionPtr SpaceShip::lookup(const GameObject& whatWeHit) { static HitMap collisionMap; ... }
~cpp SpaceShip::HitFunctionPtr SpaceShip::lookup(const GameObject& whatWeHit) { static HitMap collisionMap; // 초기화 관련은 다음 주제에서 살핀다. // 검색 결과의 iterator를 생성한다. (Item 35참고) HitMap::iterator mapEntry= collisionMap.find(typeid(whatWeHit).name()); // 현재 map의 인자들이 있는가 살핀다. if (mapEntry == collisionMap.end()) return 0; // 짝지어진 함수 포인터를 반환한다. return (*mapEntry).second; }
~cpp // An incorrect implementation SpaceShip::HitFunctionPtr SpaceShip::lookup(const GameObject& whatWeHit) { static HitMap collisionMap; collisionMap["SpaceShip"] = &hitSpaceShip; collisionMap["SpaceStation"] = &hitSpaceStation; collisionMap["Asteroid"] = &hitAsteroid; ... }
~cpp class SpaceShip: public GameObject { private: static HitMap initializeCollisionMap(); ... }; SpaceShip::HitFunctionPtr SpaceShip::lookup(const GameObject& whatWeHit) { static HitMap collisionMap = initializeCollisionMap(); ... }
~cpp class SpaceShip: public GameObject { private: static HitMap * initializeCollisionMap(); ... }; SpaceShip::HitFunctionPtr SpaceShip::lookup(const GameObject& whatWeHit) { static auto_ptr<HitMap> collisionMap(initializeCollisionMap()); ... }
~cpp SpaceShip::HitMap * SpaceShip::initializeCollisionMap() { HitMap *phm = new HitMap; (*phm)["SpaceShip"] = &hitSpaceShip; (*phm)["SpaceStation"] = &hitSpaceStation; (*phm)["Asteroid"] = &hitAsteroid; return phm; }
~cpp // 않좋은 생각 SpaceShip::HitMap * SpaceShip::initializeCollisionMap() { HitMap *phm = new HitMap; (*phm)["SpaceShip"] = reinterpret_cast<HitFunctionPtr>(&hitSpaceShip); (*phm)["SpaceStation"] = reinterpret_cast<HitFunctionPtr>(&hitSpaceStation); (*phm)["Asteroid"] = reinterpret_cast<HitFunctionPtr>(&hitAsteroid); return phm; }
~cpp class GameObject { // this is unchanged public: virtual void collide(GameObject& otherObject) = 0; ... }; class SpaceShip: public GameObject { public: virtual void collide(GameObject& otherObject); // 함수의 모든 인자를 GameObject 로 바꾸었다. virtual void hitSpaceShip(GameObject& spaceShip); virtual void hitSpaceStation(GameObject& spaceStation); virtual void hitAsteroid(GameObject& asteroid); ... };
~cpp SpaceShip::HitMap * SpaceShip::initializeCollisionMap() { HitMap *phm = new HitMap; (*phm)["SpaceShip"] = &hitSpaceShip; (*phm)["SpaceStation"] = &hitSpaceStation; (*phm)["Asteroid"] = &hitAsteroid; return phm; }
~cpp void SpaceShip::hitSpaceShip(GameObject& spaceShip) { SpaceShip& otherShip = dynamic_cast<SpaceShip&>(spaceShip); SpaceShip-SpaceShip 간의 충돌 수행; } void SpaceShip::hitSpaceStation(GameObject& spaceStation) { SpaceStation& station = dynamic_cast<SpaceStation&>(spaceStation); SpaceShip-SpaceStation 간의 충돌 수행; } void SpaceShip::hitAsteroid(GameObject& asteroid) { Asteroid& theAsteroid = dynamic_cast<Asteroid&>(asteroid); SpaceShip-Asteroid 간의 충돌 수행; }
~cpp #include "SpaceShip.h" #include "SpaceStation.h" #include "Asteroid.h" namespace { // 이름 없는 namespace(이름 공간)? 아래 설명을 보자. // 충돌 처리 함수 첫번째 void shipAsteroid(GameObject& spaceShip, GameObject& asteroid); void shipStation(GameObject& spaceShip, GameObject& spaceStation); void asteroidStation(GameObject& asteroid, GameObject& spaceStation); ... // 두번째 충돌 처리 함수들, 첫번째 인자를 바꾸어서 delegate 하는 것이다. void asteroidShip(GameObject& asteroid, GameObject& spaceShip) { shipAsteroid(spaceShip, asteroid); } void stationShip(GameObject& spaceStation, GameObject& spaceShip) { shipStation(spaceShip, spaceStation); } void stationAsteroid(GameObject& spaceStation, GameObject& asteroid) { asteroidStation(asteroid, spaceStation); } ... // 형/함수 로 관련 배열 만든느 과정, 설명 부분 참고 typedef void (*HitFunctionPtr)(GameObject&, GameObject&); typedef map< pair<string,string>, HitFunctionPtr > HitMap; pair<string,string> makeStringPair(const char *s1, const char *s2); HitMap * initializeCollisionMap(); HitFunctionPtr lookup(const string& class1, const string& class2); } // namespace 끝 void processCollision(GameObject& object1, GameObject& object2) { HitFunctionPtr phf = lookup(typeid(object1).name(),typeid(object2).name()); if (phf) phf(object1, object2); else throw UnknownCollision(object1, object2); }
~cpp // 두가지의 char* 리터럴로 pair<string,string> 객체를 생성한다. // 이는 initializeCollisionMap에서 사용된다. 반환 인자의 최적화는 Item 20을 참고하라. namespace { // 이름 없는 namespace(이름 공간) 다시? 글에 설명 참고 pair<string,string> makeStringPair(const char *s1, const char *s2) { return pair<string,string>(s1, s2); } } // namespace 끝 namespace { // 아직도 이름없는 namespace(이름공간) ? 글에 설명 참고 HitMap * initializeCollisionMap() { HitMap *phm = new HitMap; (*phm)[makeStringPair("SpaceShip","Asteroid")] = &shipAsteroid; (*phm)[makeStringPair("SpaceShip", "SpaceStation")] = &shipStation; ... return phm; } } // end namespace
~cpp namespace { // 밑에 설명한다 밑어 주세요. HitFunctionPtr lookup(const string& class1, const string& class2) { static auto_ptr<HitMap> collisionMap(initializeCollisionMap()); // make_pair에 관해 글에 설명한다. HitMap::iterator mapEntry = collisionMap->find(make_pair(class1, class2)); if (mapEntry == collisionMap->end()) return 0; return (*mapEntry).second; } } // namespace 끝
~cpp HitMap::iterator mapEntry = collisionMap->find(pair<string,string>(class1, class2));
~cpp void shipAsteroid(GameObject& spaceShip, GameObject& asteroid);
~cpp class CollisionMap { public: typedef void (*HitFunctionPtr)(GameObject&, GameObject&); void addEntry(const string& type1, const string& type2, HitFunctionPtr collisionFunction, bool symmetric = true); // 아래 설명 참고 void removeEntry(const string& type1, const string& type2); HitFunctionPtr lookup(const string& type1, const string& type2); // 이 함수는 map의 참조를 반환한다. Item 26참고 static CollisionMap& theCollisionMap(); private: // 사역으로 묶는 것은 map을 여러게 만드는걸 방지 (Item 26참고) CollisionMap(); CollisionMap(const CollisionMap&); };
~cpp void shipAsteroid(GameObject& spaceShip, GameObject& asteroid); CollisionMap::theCollisionMap().addEntry("SpaceShip", "Asteroid", &shipAsteroid); void shipStation(GameObject& spaceShip, GameObject& spaceStation); CollisionMap::theCollisionMap().addEntry("SpaceShip", "SpaceStation", &shipStation); void asteroidStation(GameObject& asteroid, GameObject& spaceStation); CollisionMap::theCollisionMap().addEntry("Asteroid", "SpaceStation", &asteroidStation);
~cpp class RegisterCollisionFunction { public: RegisterCollisionFunction( const string& type1, const string& type2, CollisionMap::HitFunctionPtr collisionFunction, bool symmetric = true) { CollisionMap::theCollisionMap().addEntry(type1, type2, collisionFunction, symmetric); } };
~cpp RegisterCollisionFunction cf1("SpaceShip", "Asteroid", &shipAsteroid); RegisterCollisionFunction cf2("SpaceShip", "SpaceStation", &shipStation); RegisterCollisionFunction cf3("Asteroid", "SpaceStation", &asteroidStation); ... int main(int argc, char * argv[]) { ... }
~cpp class Satellite: public GameObject { ... };
~cpp void satelliteShip(GameObject& satellite, GameObject& spaceShip); void satelliteAsteroid(GameObject& satellite, GameObject& asteroid);
~cpp RegisterCollisionFunction cf4("Satellite", "SpaceShip", &satelliteShip); RegisterCollisionFunction cf5("Satellite", "Asteroid", &satelliteAsteroid);