CPU 캐시를 최대한 활용할 수 있도록 데이터를 배치해 메모리 접근 속도를 높인다.
#include <cassert>
class Entity {
public:
void update();
void activeRender(int index);
void deactiveRender(int index);
private:
const int MAX_ENTITIES = 10;
//객체포인터를 사용하는 것보다 컴포넌트를 배열로 만드는 것이 캐시미스가 적게 일어나 50배정도 더 빠르다.
AIComponent* aiComponents = new AIComponent[MAX_ENTITIES];
PhysicsComponent* physicsComponents = new PhysicsComponent[MAX_ENTITIES];
int numActive_;
//배열에서 활성화된 것들을 앞쪽에 모아두기
RenderComponent* renderComponents = new RenderComponent[MAX_ENTITIES];
};
//빈번하게 쓰이는 코드
class AIComponent {
public:
void update() {}
private:
Animation* animation_;
double energy_;
Vector goalPos;
LootDrop* loot_;
};
// 한 번만 쓰이는 코드 : 죽었을 때 전리품 드랍
class LootDrop {
friend class AIComponent;
LootType drop_;
int minDrops_;
int masDrops_;
double chanceOfDrop_;
};
class PhysicsComponent {
public:
void update() {}
};
class RenderComponent {
public:
void render() {}
};
void Entity::update() {
while (!gameOver)
{
for (int i = 0; i < MAX_ENTITIES; i++)
{
aiComponents[i].update();
}
for (int i = 0; i < MAX_ENTITIES; i++)
{
physicsComponents[i].update();
}
for (int i = 0; i < numActive_; i++)
{
renderComponents[i].render();
}
}
}
void Entity::activeRender(int index){
//비활성화된 원소여야 한다.
assert(index >= numActive_);
// 새로 활성화된 원소를 비활성 원소 중 맨 앞에 있는 것과 바꿔서 활성 원소 중에서 맨 뒤에 가게 한다.
RenderComponent temp = renderComponents[numActive_];
renderComponents[numActive_] = renderComponents[index];
renderComponents[index] = temp;
// 이제 활성화 원소가 하나 늘었다.
++numActive_;
}
void Entity::deactiveRender(int index) {
//활성화된 원소여야 한다.
assert(index < numActive_);
// 이제 비활성화 원소가 하나 늘었다.
--numActive_;
// 새로 활성화된 원소를 비활성 원소 중 맨 앞에 있는 것과 바꿔서 활성 원소 중에서 맨 뒤에 가게 한다.
RenderComponent temp = renderComponents[numActive_];
renderComponents[numActive_] = renderComponents[index];
renderComponents[index] = temp;
}