2009-04-15 2 views
1

저는 며칠 동안 머리 속에이 문제를 타격했습니다. 그래서 나는 만족스런 결론을 내리지 못했고, 그래서 나는 자신의 의견에 대해 SO 직원에게 물어볼 것이라고 생각했습니다. 내가 일하고있는 게임의 경우, herehere과 같이 Component Object Model을 사용하고 있습니다. 사실 꽤 잘 돌아가고 있지만 현재의 스토리지 솔루션은 제한적으로 변하고 있습니다 (클래스 이름 또는 임의의 "패밀리"이름으로 만 구성 요소를 요청할 수 있음). 내가 원하는 것은 주어진 타입을 요청하고 그 타입의 모든 컴포넌트 나 타입에서 파생 된 타입을 반복하는 것입니다.구조용 계층 구조 구성 요소 스토리지

이 점을 고려하여 먼저 기본 클래스 유형을 파생 형식을 통해이 순서로 저장하는 간단한 RTTI 체계를 구현했습니다. 즉, 스프라이트에 대한 RTTI는 component :: renderable :: sprite가됩니다. 이렇게하면 B의 모든 요소를 ​​단순히 비교하여 유형 A가 B 유형에서 파생되었는지를 쉽게 유형을 비교할 수 있습니다. 즉, component :: renderable :: sprite는 component :: renderable에서 파생되지만 component :: timer에서 파생되지 않습니다. 간단하고 효과적이며 이미 구현되었습니다.

내가 지금 원하는 것은 계층 구조를 나타내는 방식으로 구성 요소를 저장하는 방법입니다.

 component 
    /  \ 
    timer   renderable 
/   / \ 
shotTimer sprite  particle 

내가 그 유형의 모든 구성 요소의 목록을 저장하는 것입니다 각 노드에서 : 마음에 오는 첫번째 것은 그래서 같은 노드로 유형을 사용하는 나무입니다. 그런 식으로 "component :: renderable"노드를 요청하면 파생 된 유형에 상관없이 모든 렌더링 가능 구성 요소에 액세스 할 수있게됩니다.

for_each(renderable.begin(), renderable.end(), renderFunc); 

을 아래로 렌더링 할에서 전체 트리를 통해 그 반복 처리가 : 문지 내가 이런 식으로 뭔가를 할 수 있도록 반복자와 그 구성 요소에 액세스 할 수 있도록하려는 것입니다. 이 작업은 정말 못생긴 map/vector/tree 노드 구조와 내가했던 곳의 노드 스택을 추적하는 커스텀 포워드 이터레이터를 사용합니다. 모든 것을 구현하는 동안, 나는 더 좋은, 더 명확한 방법이 있어야한다고 느꼈다 ... 나는 단지 하나를 생각할 수 없다. (

그래서 질문은 : 나는 이것을 불필요하게 복잡하게 만든다? 일부 명백한 단순화 내가 누락, 또는 내가 사용한다 구조를 기존의? 아니면이 단지 inheritly 복잡한 문제이며 아마 당신이 어떤 입력을위한 잘 이미?

감사하고 있어요 있어요!

답변

1

다음 빈도를 고려해야합니다.

  • 트리 통과
  • 추가/최적의 솔루션을 결정

    아마도 대신 메이크업 도움이 될 것입니다

  • 얼마나 많은 개체를 더 빈번

을 추적해야합니까 트리에서 요소를 제거 복잡한 트리는 모든 유형의 목록을 가지고 있으며 파생 된 각 유형에 대한 객체에 대한 포인터를 추가합니다.이런 식으로 뭔가 : 유형의 구성 요소이다 오브젝트 :: 렌더링 가능한 :: 스프라이트

myTypeList["component"].insert(&object); 
myTypeList["renderable"].insert(&object); 
myTypeList["sprite"].insert(&object); 

여러 목록의 각 obejct 등록에 의해 다음

map<string,set<componenet *>> myTypeList 

, 그것은 모든에 뭔가를 용이하게 지정된 유형의 객체 및 하위

표준 :
for_each(myTypeList["renderable"].begin(),myTypeList["renderable"].end(),renderFunc); 

참고 설정하고 내 표준 : 맵 구조는 당신이 그것을 사용하는 방법에 따라 최적의 선택이 될 수 없습니다.

아니면 트리 답은 당신이 그들을 필요로 순서에 따라

map<string, set<string> > myTypeList; 
map<string, set<component *> myObjectList; 

myTypeList["component"].insert("component"); 
myTypeList["component"].insert("renderable"); 
myTypeList["component"].insert("sprite"); 
myTypeList["renderable"].insert("renderable"); 
myTypeList["renderable"].insert("sprite"); 
myTypeList["sprite"].insert("sprite"); 

// this isn't quite right, but you get the idea 
struct doForList { 
    UnaryFunction f; 
    doForList(UnaryFunction f): func(f) {}; 
    operator()(string typename) { 
     for_each(myTypeList[typename].begin();myTypeList[typename].end(), func); 
    } 
} 

for_each(myTypeList["renderable"].begin(),myTypeList["renderable"].end(), doForList(myFunc)) 
+0

추가/제거 이상을 트래버스해야하며 상황에 따라 한 번에 수백 ~ 수천 개의 구성 요소를 계획합니다. 나는 당신이 말했던 방법을 고려해 보았지만 여전히 그것을 배제하지는 못했지만 저장 요구 조건에 대한 큰 팬이 아닙니다. 그래도 최선의 선택이 될 수 있습니다. – Toji

+0

당신은 boost :: graph를 보았습니까? – MadCoder

+0

나는 실제로있다. 너무 강하게 생각했지만 일부 빠른 테스트에서 필자가 필요로하는 방식으로 사용했을 때 약간의 성능 저하를 나타냈다. 내가 틀린 것을 사용하고있을 수도 있습니다. 나는 다시 한번 살펴 봐야 할 것이다. – Toji

0

만의 클래스 계층 구조를 저장하는 하이브리드 방식. 당신은 꽤 많이 중위 전순, postorder의 선택, 그리고 있습니다. 따라서 광범위한 첫 번째와 깊은 첫 번째 검색에서 명백한 유사점을 가지며, 일반적으로 당신은 그들을 두드리는 데 어려움을 겪을 것입니다.

이제 문제를 litle로 제한하면 임의 데이터의 트리를 배열로 저장하기위한 여러 가지 구식 알고리즘이 있습니다. 우리는 포트란 시대에 많이 사용했습니다. 그들 중 한 명은 A의 아이들을 A2 (인덱스) (A) * 2, index (A) * 2 + 1에 저장하는 것이 핵심 요령이었습니다. 문제는 트리가 드문 경우 공간을 낭비하고 트리 크기가 배열 크기에 의해 제한된다는 것입니다. 그러나이 권리를 기억하면 간단한 DO 루프로 폭 넓은 순서로 요소를 얻게됩니다.

크 누스 3 권을보십시오. 거기에 그 물건의 톤이 있습니다.

0

기존 구현을위한 코드를보고 싶다면 Cowboy Programming 페이지에서 언급 한 Game Programming Gems 5 기사에는 구성 요소 시스템에 사용 된 코드의 일부 버전이 제거되어 있습니다 (저는 공정한 청크를 만들었습니다). 이 기사에서 설명한 시스템의 설계 및 구현).

코드를 다시 확인해야합니다. 지금 당장은 할 수 없지만, 우리는 당신이 보여주는 방식으로 계층 구조에있는 것들을 나타내지 않았습니다. 구성 요소가 코드에서 클래스 계층 구조로 유지되었지만 런타임 표현은 단순 목록이었습니다. 구성 요소가 방금 구현 한 인터페이스 목록을 선언했습니다. 사용자는 인터페이스 나 구체적인 유형을 쿼리 할 수 ​​있습니다.

예에서 Sprite와 Particle은 RENDERABLE 인터페이스를 구현했다고 선언하고 모든 렌더링 가능 항목에 대해 작업을 수행하려는 경우 활성 구성 요소 목록을 반복하여 각각을 확인합니다. 그것의 얼굴에 대단히 효율적이지는 않지만 실제로는 괜찮 았습니다. 문제가되지 않은 주된 이유는 실제로 매우 일반적인 작업이 아닌 것으로 나타났습니다. 예를 들어 렌더러와 같은 것들은 생성시 렌더링 장면에 추가되었으므로 전역 장면 관리자는 자체 렌더링 가능 객체 목록을 유지 관리 했으므로이를 위해 구성 요소 시스템을 질의 할 필요가 없었습니다. 마찬가지로 phyics 및 충돌 구성 요소와 일종의.