add ecs function to find entities with components

This commit is contained in:
Miroslav Vasilev 2024-05-16 00:36:41 +03:00
parent 6af69a9169
commit 3c83d97a34
2 changed files with 70 additions and 4 deletions

View file

@ -25,10 +25,28 @@ func (e *ECSError) Error() string {
/* ==================================================== */ /* ==================================================== */
/* ====================== Types ======================= */ /* ================== ComponentType =================== */
type ComponentType uint64 type ComponentType uint64
func TypeFrom(powerOf2 uint64) (ComponentType, *ECSError) {
if powerOf2 > 63 {
return 0, ecsError("Failure: Provided number is too high ( component types must be represented by a power of 2, up to 63 )")
}
t := uint64(0)
for i := range powerOf2 {
t *= i
}
return ComponentType(t), nil
}
/* ==================================================== */
/* ====================== Types ======================= */
type SystemOrder uint8 type SystemOrder uint8
type EntityId uint64 type EntityId uint64
@ -119,7 +137,8 @@ func (ent *BasicEntity) ContainedComponents() ComponentMask {
return ComponentMask(ent.containedComponents) return ComponentMask(ent.containedComponents)
} }
func (ent *BasicEntity) AddComponent(c Component) { func (ent *BasicEntity) addComponent(c Component) {
ent.containedComponents = ent.containedComponents.CombinedWithType(c.Type())
ent.components[c.Type()] = c ent.components[c.Type()] = c
} }
@ -217,6 +236,18 @@ func (w *World) RegisterComponentType(t ComponentType, name string) (err *ECSErr
return nil return nil
} }
func (w *World) FindEntitiesWithComponents(comps ComponentMask) []*BasicEntity {
ents := make([]*BasicEntity, 16)
for _, v := range w.entities {
if v.ContainsComponents(comps) {
ents = append(ents, v)
}
}
return ents
}
func (w *World) AddComponentToEntity(ent *BasicEntity, comp Component) (modifiedEntity *BasicEntity, err *ECSError) { func (w *World) AddComponentToEntity(ent *BasicEntity, comp Component) (modifiedEntity *BasicEntity, err *ECSError) {
if !w.registeredComponentTypes.Contains(comp.Type()) { if !w.registeredComponentTypes.Contains(comp.Type()) {
return nil, ecsError("Failure: Attempting to add unknown component to an entity.") return nil, ecsError("Failure: Attempting to add unknown component to an entity.")
@ -226,7 +257,7 @@ func (w *World) AddComponentToEntity(ent *BasicEntity, comp Component) (modified
return nil, ecsError("Failure: Entity already contains component") return nil, ecsError("Failure: Entity already contains component")
} }
ent.AddComponent(comp) ent.addComponent(comp)
if w.components[comp.Type()] == nil { if w.components[comp.Type()] == nil {
w.components[comp.Type()] = make([]Component, 0) w.components[comp.Type()] = make([]Component, 0)

View file

@ -267,7 +267,7 @@ func TestBasicEntity_AddComponent(t *testing.T) {
containedComponents: tt.fields.containedComponents, containedComponents: tt.fields.containedComponents,
components: tt.fields.components, components: tt.fields.components,
} }
ent.AddComponent(tt.args.c) ent.addComponent(tt.args.c)
}) })
} }
} }
@ -740,3 +740,38 @@ func TestWorld_Input(t *testing.T) {
}) })
} }
} }
func TestWorld_FindEntitiesWithComponents(t *testing.T) {
type fields struct {
registeredComponentTypes ComponentMask
registeredComponentNames map[ComponentType]string
entities map[EntityId]*BasicEntity
components map[ComponentType][]Component
systems []System
}
type args struct {
comps ComponentMask
}
tests := []struct {
name string
fields fields
args args
want []*BasicEntity
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
w := &World{
registeredComponentTypes: tt.fields.registeredComponentTypes,
registeredComponentNames: tt.fields.registeredComponentNames,
entities: tt.fields.entities,
components: tt.fields.components,
systems: tt.fields.systems,
}
if got := w.FindEntitiesWithComponents(tt.args.comps); !reflect.DeepEqual(got, tt.want) {
t.Errorf("World.FindEntitiesWithComponents() = %v, want %v", got, tt.want)
}
})
}
}