some basic entity and component structure
parent
4e2aa1ac98
commit
d94d6bc8f3
|
@ -1,7 +1,4 @@
|
|||
namespace Encompass
|
||||
{
|
||||
public abstract class Component
|
||||
{
|
||||
public int EntityID { get; set; }
|
||||
}
|
||||
public abstract class Component {}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Encompass {
|
||||
internal class ComponentManager {
|
||||
private Dictionary<uint, List<Component>> entityIDToComponents = new Dictionary<uint, List<Component>>();
|
||||
|
||||
private Dictionary<Type, List<Component>> activeComponents = new Dictionary<Type, List<Component>>();
|
||||
private Dictionary<Type, List<Component>> inactiveComponents = new Dictionary<Type, List<Component>>();
|
||||
|
||||
private List<Component> componentsToActivate = new List<Component>();
|
||||
private List<Component> componentsToDeactivate = new List<Component>();
|
||||
private List<Component> componentsToRemove = new List<Component>();
|
||||
|
||||
internal TComponent CreateComponent<TComponent>(uint entityID) where TComponent : Component, new() {
|
||||
var component = new TComponent();
|
||||
|
||||
if (!entityIDToComponents.ContainsKey(entityID)) {
|
||||
entityIDToComponents.Add(entityID, new List<Component>());
|
||||
}
|
||||
|
||||
entityIDToComponents[entityID].Add(component);
|
||||
|
||||
if (!activeComponents.ContainsKey(typeof(TComponent))) {
|
||||
activeComponents.Add(typeof(TComponent), new List<Component>());
|
||||
inactiveComponents.Add(typeof(TComponent), new List<Component>());
|
||||
}
|
||||
|
||||
MarkForActivation(component);
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
internal IEnumerable<Component> GetComponentsByEntity(uint entityID) {
|
||||
return entityIDToComponents[entityID];
|
||||
}
|
||||
|
||||
internal IEnumerable<TComponent> GetActiveComponentsByType<TComponent>() where TComponent : Component {
|
||||
return activeComponents[typeof(TComponent)].Cast<TComponent>();
|
||||
}
|
||||
|
||||
internal IEnumerable<TComponent> GetComponentsByEntityAndType<TComponent>(uint entityID) where TComponent : Component {
|
||||
var entity_components = GetComponentsByEntity(entityID);
|
||||
var active_components_by_type = GetActiveComponentsByType<TComponent>();
|
||||
return entity_components.Intersect(active_components_by_type).Cast<TComponent>();
|
||||
}
|
||||
|
||||
internal bool EntityHasComponentOfType<TComponent>(uint entityID) where TComponent : Component {
|
||||
return GetComponentsByEntityAndType<TComponent>(entityID).Any();
|
||||
}
|
||||
|
||||
internal void RemoveAllComponentsFromEntity(uint entityID) {
|
||||
var components = GetComponentsByEntity(entityID);
|
||||
|
||||
foreach (var component in components) {
|
||||
activeComponents[component.GetType()].Remove(component);
|
||||
inactiveComponents[component.GetType()].Remove(component);
|
||||
}
|
||||
|
||||
entityIDToComponents.Remove(entityID);
|
||||
}
|
||||
|
||||
internal void MarkForActivation(Component component) {
|
||||
componentsToActivate.Add(component);
|
||||
}
|
||||
|
||||
internal void MarkForRemoval(Component component) {
|
||||
componentsToRemove.Add(component);
|
||||
}
|
||||
|
||||
internal void ActivateComponents() {
|
||||
foreach (var component in componentsToActivate) {
|
||||
activeComponents[component.GetType()].Add(component);
|
||||
inactiveComponents[component.GetType()].Remove(component);
|
||||
}
|
||||
|
||||
componentsToActivate.Clear();
|
||||
}
|
||||
|
||||
internal void RemoveComponents() {
|
||||
foreach (var component in componentsToRemove) {
|
||||
activeComponents[component.GetType()].Remove(component);
|
||||
inactiveComponents[component.GetType()].Remove(component);
|
||||
}
|
||||
|
||||
componentsToRemove.Clear();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,41 +6,21 @@ namespace Encompass
|
|||
{
|
||||
public class Entity
|
||||
{
|
||||
public readonly static List<Component> Empty = new List<Component>();
|
||||
public readonly uint id;
|
||||
|
||||
public readonly int id;
|
||||
private ComponentManager componentManager;
|
||||
|
||||
private readonly Dictionary<Type, List<Component>> componentBag = new Dictionary<Type, List<Component>>();
|
||||
private readonly Dictionary<Type, List<Component>> activeComponents = new Dictionary<Type, List<Component>>();
|
||||
|
||||
public Entity(int id) {
|
||||
internal Entity(uint id, ComponentManager componentManager) {
|
||||
this.id = id;
|
||||
this.componentManager = componentManager;
|
||||
}
|
||||
|
||||
public TComponent AddComponent<TComponent>() where TComponent : Component, new() {
|
||||
TComponent component = new TComponent();
|
||||
|
||||
if (!componentBag.ContainsKey(typeof(TComponent))) {
|
||||
var componentList = new List<Component>();
|
||||
var activeComponentList = new List<Component>();
|
||||
componentBag.Add(typeof(TComponent), componentList);
|
||||
activeComponents.Add(typeof(TComponent), activeComponentList);
|
||||
componentList.Add(component);
|
||||
activeComponentList.Add(component);
|
||||
} else {
|
||||
componentBag[typeof(TComponent)].Add(component);
|
||||
activeComponents[typeof(TComponent)].Add(component);
|
||||
}
|
||||
|
||||
return component;
|
||||
return componentManager.CreateComponent<TComponent>(id);
|
||||
}
|
||||
|
||||
public IEnumerable<TComponent> GetComponents<TComponent>() where TComponent : Component {
|
||||
if (activeComponents.ContainsKey(typeof(TComponent))) {
|
||||
return activeComponents[typeof(TComponent)].Cast<TComponent>();
|
||||
} else {
|
||||
return Enumerable.Empty<TComponent>();
|
||||
}
|
||||
return componentManager.GetComponentsByEntityAndType<TComponent>(id);
|
||||
}
|
||||
|
||||
public TComponent GetComponent<TComponent>() where TComponent : Component {
|
||||
|
@ -48,8 +28,11 @@ namespace Encompass
|
|||
}
|
||||
|
||||
public bool HasComponent<TComponent>() where TComponent : Component {
|
||||
return activeComponents.ContainsKey(typeof(TComponent)) &&
|
||||
activeComponents[typeof(TComponent)].Count != 0;
|
||||
return componentManager.EntityHasComponentOfType<TComponent>(id);
|
||||
}
|
||||
|
||||
internal void RemoveAllComponents() {
|
||||
componentManager.RemoveAllComponentsFromEntity(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Encompass {
|
||||
internal class EntityManager {
|
||||
private uint nextID = 1;
|
||||
|
||||
private List<Entity> entities = new List<Entity>();
|
||||
private Dictionary<uint, Entity> IDToEntity = new Dictionary<uint, Entity>();
|
||||
|
||||
private List<Entity> entitiesMarkedForDestroy = new List<Entity>();
|
||||
|
||||
private ComponentManager componentManager;
|
||||
|
||||
public EntityManager(
|
||||
ComponentManager componentManager
|
||||
) {
|
||||
this.componentManager = componentManager;
|
||||
}
|
||||
|
||||
public Entity CreateEntity() {
|
||||
return new Entity(NextID(), componentManager);
|
||||
}
|
||||
|
||||
public Entity GetEntity(uint id) {
|
||||
return this.IDToEntity[id];
|
||||
}
|
||||
|
||||
public void MarkForDestroy(Entity entity) {
|
||||
entitiesMarkedForDestroy.Add(entity);
|
||||
}
|
||||
|
||||
internal void DestroyMarkedEntities() {
|
||||
foreach (var entity in entitiesMarkedForDestroy) {
|
||||
entity.RemoveAllComponents();
|
||||
}
|
||||
}
|
||||
|
||||
private uint NextID() {
|
||||
var id = this.nextID;
|
||||
this.nextID++;
|
||||
return id;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Encompass {
|
||||
public class World {
|
||||
EntityManager entityManager;
|
||||
ComponentManager componentManager;
|
||||
|
||||
public World() {
|
||||
this.componentManager = new ComponentManager();
|
||||
this.entityManager = new EntityManager(componentManager);
|
||||
}
|
||||
|
||||
public void Update() {
|
||||
componentManager.ActivateComponents();
|
||||
componentManager.RemoveComponents();
|
||||
}
|
||||
|
||||
public Entity CreateEntity() {
|
||||
return entityManager.CreateEntity();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,12 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<RootNamespace>Encompass</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="encompass-cs.sln" />
|
||||
<Content Include="Entity.cs" />
|
||||
<Content Include="Component.cs" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<RootNamespace>Encompass</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="encompass-cs.sln" />
|
||||
<Content Include="Entity.cs" />
|
||||
<Content Include="Component.cs" />
|
||||
<Content Include="World.cs" />
|
||||
<Content Include="EntityManager.cs" />
|
||||
<Content Include="ComponentManager.cs" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -12,25 +12,21 @@ namespace Encompass
|
|||
|
||||
public class EntityTest
|
||||
{
|
||||
/*
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
}
|
||||
*/
|
||||
|
||||
[Test]
|
||||
public void AddComponent()
|
||||
{
|
||||
var entity = new Entity(0);
|
||||
var world = new World();
|
||||
var entity = world.CreateEntity();
|
||||
|
||||
var mockComponent = entity.AddComponent<MockComponent>();
|
||||
mockComponent.myString = "hello";
|
||||
mockComponent.myInt = 3;
|
||||
|
||||
world.Update();
|
||||
|
||||
Assert.IsTrue(entity.HasComponent<MockComponent>());
|
||||
Assert.AreEqual(3, entity.GetComponent<MockComponent>().myInt);
|
||||
Assert.AreEqual("hello", entity.GetComponent<MockComponent>().myString);
|
||||
Assert.AreEqual(0, entity.GetComponent<MockComponent>().EntityID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue