(World) Optimized entities handling a lot
Former-commit-id: f05f3bb7bf321d30fd51f504ace95aa0ea9f7f8d
This commit is contained in:
parent
b30298b6ab
commit
3694857d30
|
|
@ -7,9 +7,11 @@
|
||||||
#ifndef NDK_WORLD_HPP
|
#ifndef NDK_WORLD_HPP
|
||||||
#define NDK_WORLD_HPP
|
#define NDK_WORLD_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Core/Bitset.hpp>
|
||||||
#include <Nazara/Core/NonCopyable.hpp>
|
#include <Nazara/Core/NonCopyable.hpp>
|
||||||
#include <NDK/Entity.hpp>
|
#include <NDK/Entity.hpp>
|
||||||
#include <NDK/EntityHandle.hpp>
|
#include <NDK/EntityHandle.hpp>
|
||||||
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace Ndk
|
namespace Ndk
|
||||||
|
|
@ -27,21 +29,32 @@ namespace Ndk
|
||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
|
EntityHandle GetEntity(Entity::Id id);
|
||||||
|
|
||||||
void KillEntity(const EntityHandle& entity);
|
void KillEntity(const EntityHandle& entity);
|
||||||
void KillEntities(const EntityList& list);
|
void KillEntities(const EntityList& list);
|
||||||
|
|
||||||
EntityHandle GetEntity(Entity::Id id);
|
|
||||||
|
|
||||||
bool IsEntityValid(const EntityHandle& entity) const;
|
bool IsEntityValid(const EntityHandle& entity) const;
|
||||||
bool IsEntityIdValid(Entity::Id id) const;
|
bool IsEntityIdValid(Entity::Id id) const;
|
||||||
|
|
||||||
void Update();
|
void Update();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct EntityBlock
|
||||||
|
{
|
||||||
|
EntityBlock(Entity&& e) :
|
||||||
|
entity(std::move(e))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity entity;
|
||||||
|
unsigned int aliveIndex;
|
||||||
|
};
|
||||||
|
|
||||||
std::vector<Entity::Id> m_freeIdList;
|
std::vector<Entity::Id> m_freeIdList;
|
||||||
std::vector<Entity> m_entities;
|
std::vector<EntityBlock> m_entities;
|
||||||
EntityList m_aliveEntities;
|
EntityList m_aliveEntities;
|
||||||
EntityList m_killedEntities;
|
NzBitset<nzUInt64> m_killedEntities;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
// This file is part of the "Nazara Development Kit"
|
// This file is part of the "Nazara Development Kit"
|
||||||
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
|
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
|
||||||
|
|
||||||
|
#include <Nazara/Core/Error.hpp>
|
||||||
|
|
||||||
namespace Ndk
|
namespace Ndk
|
||||||
{
|
{
|
||||||
inline World::EntityList World::CreateEntities(unsigned int count)
|
inline World::EntityList World::CreateEntities(unsigned int count)
|
||||||
|
|
@ -17,7 +19,6 @@ namespace Ndk
|
||||||
|
|
||||||
inline void World::KillEntities(const EntityList& list)
|
inline void World::KillEntities(const EntityList& list)
|
||||||
{
|
{
|
||||||
m_killedEntities.reserve(m_killedEntities.size() + list.size());
|
|
||||||
for (const EntityHandle& entity : list)
|
for (const EntityHandle& entity : list)
|
||||||
KillEntity(entity);
|
KillEntity(entity);
|
||||||
}
|
}
|
||||||
|
|
@ -29,6 +30,6 @@ namespace Ndk
|
||||||
|
|
||||||
inline bool World::IsEntityIdValid(Entity::Id id) const
|
inline bool World::IsEntityIdValid(Entity::Id id) const
|
||||||
{
|
{
|
||||||
return id < m_entities.size() && m_entities[id].IsValid();
|
return id < m_entities.size() && m_entities[id].entity.IsValid();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,13 +31,15 @@ namespace Ndk
|
||||||
m_entities.push_back(Entity(*this, id));
|
m_entities.push_back(Entity(*this, id));
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityHandle entity = m_entities[id].CreateHandle();
|
|
||||||
|
|
||||||
// On initialise l'entité et on l'ajoute à la liste des entités vivantes
|
// On initialise l'entité et on l'ajoute à la liste des entités vivantes
|
||||||
entity->Create();
|
Entity& entity = m_entities[id].entity;
|
||||||
m_aliveEntities.push_back(entity);
|
entity.Create();
|
||||||
|
|
||||||
return entity;
|
EntityHandle handle = entity.CreateHandle();
|
||||||
|
m_aliveEntities.push_back(handle);
|
||||||
|
m_entities[id].aliveIndex = m_aliveEntities.size()-1;
|
||||||
|
|
||||||
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::Clear()
|
void World::Clear()
|
||||||
|
|
@ -49,7 +51,7 @@ namespace Ndk
|
||||||
m_entities.clear();
|
m_entities.clear();
|
||||||
|
|
||||||
m_aliveEntities.clear();
|
m_aliveEntities.clear();
|
||||||
m_killedEntities.clear();
|
m_killedEntities.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::KillEntity(const EntityHandle& entity)
|
void World::KillEntity(const EntityHandle& entity)
|
||||||
|
|
@ -57,13 +59,13 @@ namespace Ndk
|
||||||
///DOC: Ignoré si l'entité est invalide
|
///DOC: Ignoré si l'entité est invalide
|
||||||
|
|
||||||
if (IsEntityValid(entity))
|
if (IsEntityValid(entity))
|
||||||
m_killedEntities.emplace_back(entity);
|
m_killedEntities.UnboundedSet(entity->GetId(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityHandle World::GetEntity(Entity::Id id)
|
EntityHandle World::GetEntity(Entity::Id id)
|
||||||
{
|
{
|
||||||
if (IsEntityIdValid(id))
|
if (IsEntityIdValid(id))
|
||||||
return m_entities[id].CreateHandle();
|
return m_aliveEntities[m_entities[id].aliveIndex];
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NazaraError("Invalid ID");
|
NazaraError("Invalid ID");
|
||||||
|
|
@ -73,33 +75,36 @@ namespace Ndk
|
||||||
|
|
||||||
void World::Update()
|
void World::Update()
|
||||||
{
|
{
|
||||||
if (!m_killedEntities.empty())
|
for (unsigned int i = m_killedEntities.FindFirst(); i != m_killedEntities.npos; i = m_killedEntities.FindNext(i))
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < m_killedEntities.size(); ++i)
|
EntityBlock& block = m_entities[i];
|
||||||
{
|
Entity& entity = block.entity;
|
||||||
const EntityHandle& entity = m_killedEntities[i];
|
|
||||||
|
NazaraAssert(entity.IsValid(), "Entity must be valid");
|
||||||
|
|
||||||
for (unsigned int j = 0; j < m_aliveEntities.size(); ++j)
|
|
||||||
{
|
|
||||||
if (entity == m_aliveEntities[j])
|
|
||||||
{
|
|
||||||
// Remise en file d'attente de l'identifiant d'entité
|
// Remise en file d'attente de l'identifiant d'entité
|
||||||
m_freeIdList.push_back(entity->GetId());
|
m_freeIdList.push_back(entity.GetId());
|
||||||
|
|
||||||
// Destruction de l'entité (invalidation du handle par la même occasion)
|
// Destruction de l'entité (invalidation du handle par la même occasion)
|
||||||
entity->Destroy();
|
entity.Destroy();
|
||||||
|
|
||||||
// Suppression de l'entité des deux tableaux
|
// Nous allons sortir le handle de la liste des entités vivantes
|
||||||
m_aliveEntities.erase(m_aliveEntities.begin() + j);
|
// en swappant le handle avec le dernier handle, avant de pop
|
||||||
m_killedEntities.erase(m_killedEntities.begin() + i);
|
|
||||||
|
|
||||||
// Correction des indices (pour ne pas sauter une case)
|
NazaraAssert(block.aliveIndex < m_aliveEntities.size(), "Alive index out of range");
|
||||||
i--;
|
|
||||||
j--;
|
if (block.aliveIndex < m_aliveEntities.size()-1) // S'il ne s'agit pas du dernier handle
|
||||||
break;
|
{
|
||||||
}
|
EntityHandle& lastHandle = m_aliveEntities.back();
|
||||||
}
|
EntityHandle& myHandle = m_aliveEntities[block.aliveIndex];
|
||||||
}
|
|
||||||
}
|
myHandle = std::move(lastHandle);
|
||||||
|
|
||||||
|
// On n'oublie pas de corriger l'indice associé à l'entité
|
||||||
|
m_entities[myHandle->GetId()].aliveIndex = block.aliveIndex;
|
||||||
|
}
|
||||||
|
m_aliveEntities.pop_back();
|
||||||
|
}
|
||||||
|
m_killedEntities.Reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue