Documentation
¶
Index ¶
- func AddComp(w *World, e Entity, c Component)
- func DelComp(w *World, e Entity, c Component)
- func DelEntity(w *World, e Entity)
- func GetComp[C any](w *World, e Entity, c Component) (data *C)
- func HasComp(w *World, e Entity, c Component) bool
- func SetComp[C any](w *World, e Entity, c Component, data C)
- func Type(w *World, e Entity, nameComp Component) string
- type Archetype
- type ArchetypeEdge
- type CachedQuery
- type Component
- type ComponentMeta
- type Entity
- type EntityRecord
- type Filter
- type IDManager
- type Storage
- type Table
- type Types
- type World
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func DelComp ¶
DelComp removes the Component of an Entity. If the Entity doesn't have the Component, nothing will happen.
func GetComp ¶
GetComp gets the data of a Component of an Entity. If the Entity doesn't have the Component, nil will be returned.
Types ¶
type ArchetypeEdge ¶
type ArchetypeEdge struct {
// contains filtered or unexported fields
}
type CachedQuery ¶
type CachedQuery struct {
// contains filtered or unexported fields
}
CachedQuery is cached filter
func (*CachedQuery) Free ¶
func (q *CachedQuery) Free(w *World)
func (*CachedQuery) Run ¶
func (q *CachedQuery) Run(h func(entities []Entity, data []any))
type Component ¶
type Component Entity
A Component is a type of which instances can be added and removed to entities. Each component can be added only once to an entity.
--flecs.dev
func NewComponent ¶
NewComponent creates a new Component in the World. The data type associated with the Component will be bind when the first data is set.
type ComponentMeta ¶
type Entity ¶
type Entity uint64
An Entity is a unique thing in the world, and is represented by a 64-bit id. Entities can be created and deleted. If an entity is deleted, it is no longer considered "alive".
A world can contain up to 4 billion alive entities. Entity identifiers contain a few bits that make it possible to check whether an entity is alive or not.
--flecs.dev
Example (Basic) ¶
type (
Position struct{ x, y float64 }
Walking struct{}
)
w := ecs.NewWorld()
name := ecs.NewComponent(w)
ecs.SetComp(w, ecs.Entity(name), name, "Name")
position := ecs.NewComponent(w)
ecs.SetComp(w, ecs.Entity(position), name, "Position")
walking := ecs.NewComponent(w)
ecs.SetComp(w, ecs.Entity(walking), name, "Walking")
// Create an entity with name Bob
bob := ecs.NewEntity(w)
ecs.SetComp(w, bob, name, "Bob")
// The set operation finds or creates a component, and sets it.
ecs.SetComp(w, bob, position, Position{10, 20})
// The add operation adds a component without setting a value. This is
// useful for tags, or when adding a component with its default value.
ecs.SetComp(w, bob, walking, Walking{})
// Get the value for the Position component
pos := ecs.GetComp[Position](w, bob, position)
fmt.Printf("{%f, %f}\n", pos.x, pos.y)
// Overwrite the value of the Position component
ecs.SetComp(w, bob, position, Position{20, 30})
// Create another named entity
alice := ecs.NewEntity(w)
ecs.SetComp(w, alice, name, "Alice")
ecs.SetComp(w, alice, position, Position{10, 20})
ecs.SetComp(w, alice, walking, Walking{})
// Print all the Components the entity has. This will output:
// Position, Walking, (Identifier,Name)
fmt.Printf("[%s]\n", ecs.Type(w, alice, name))
// Iterate all entities with Position
ecs.QueryAll(position).Run(w, func(entities []ecs.Entity, data []any) {
p := *data[0].(*[]Position)
for i, e := range entities {
entityName := ecs.GetComp[string](w, e, name)
fmt.Printf("%s: {%f, %f}\n", *entityName, p[i].x, p[i].y)
}
})
// DelComp tag
ecs.DelComp(w, alice, walking)
Output: {10.000000, 20.000000} [Name, Position, Walking] Bob: {20.000000, 30.000000} Alice: {10.000000, 20.000000}
type EntityRecord ¶
type Filter ¶
func QueryAll ¶
Example ¶
w := ecs.NewWorld()
// Create 10 entities.
var entities [10]ecs.Entity
for i := range entities {
entities[i] = ecs.NewEntity(w)
}
// Create 2 Components.
c1 := ecs.NewComponent(w)
c2 := ecs.NewComponent(w)
// Add Components to entities.
for i, e := range entities[:5] {
ecs.SetComp(w, e, c1, i)
}
for i, e := range entities[3:7] {
ecs.SetComp(w, e, c2, i+3)
}
// Current layout:
//
// entity:[0 1 2 3 4 5 6 7 8 9]
// c1: [0 1 2 3 4 ]
// c2: [ 3 4 5 6 ]
// c1&c2: [ 3 4 ]
// CachedQuery all entities which have both c1 and c2.
ecs.QueryAll(c1, c2).Run(w, func(entities []ecs.Entity, data []any) {
// The type of the data's element is `Table[T]`,
// which can be converted to `[]T` only after type assertion.
fmt.Println(*data[0].(*[]int))
})
Output: [3 4]
Example (Iter) ¶
w := ecs.NewWorld()
// Create 10 entities.
var entities [10]ecs.Entity
for i := range entities {
entities[i] = ecs.NewEntity(w)
}
// Create 2 Components.
c1 := ecs.NewComponent(w)
c2 := ecs.NewComponent(w)
// Add Components to entities.
for i, e := range entities[:5] {
ecs.SetComp(w, e, c1, i)
}
for i, e := range entities[3:7] {
ecs.SetComp(w, e, c2, i+3)
}
// Current layout:
//
// entity:[0 1 2 3 4 5 6 7 8 9]
// c1: [0 1 2 3 4 ]
// c2: [ 3 4 5 6 ]
// c1&c2: [ 3 4 ]
// CachedQuery all entities which have both c1 and c2.
for entity, components := range ecs.QueryAll(c1, c2).Iter(w) {
// The type of the data's element is `Table[T]`,
// which can be converted to `[]T` only after type assertion.
fmt.Println(entity, components)
}
Output: 3 [3 3] 4 [4 4]
func QueryAny ¶
Example ¶
w := ecs.NewWorld()
// Create 10 entities.
var entities [10]ecs.Entity
for i := range entities {
entities[i] = ecs.NewEntity(w)
}
// Create 2 Components.
c1 := ecs.NewComponent(w)
c2 := ecs.NewComponent(w)
// Add Components to entities.
for i, e := range entities[:5] {
ecs.SetComp(w, e, c1, int32(i))
}
for i, e := range entities[3:7] {
ecs.SetComp(w, e, c2, int64(i+3))
}
// Current layout:
//
// entity:[0 1 2 3 4 5 6 7 8 9]
// c1: [0 1 2 3 4 ]
// c2: [ 3 4 5 6 ]
// c1&c2: [ 3 4 ]
// CachedQuery all entities which have c1 or c2.
var results []string
ecs.QueryAny(c1, c2).Run(w, func(entities []ecs.Entity, data []any) {
// The type of the data's element is `Table[T]`,
// which can be converted to `[]T` only after type assertion.
var sb strings.Builder
fmt.Fprintf(&sb, "%v:", entities)
if data[0] != nil {
fmt.Fprintf(&sb, " c1: [%v]", *data[0].(*[]int32))
}
if data[1] != nil {
fmt.Fprintf(&sb, " c2: [%v]", *data[1].(*[]int64))
}
results = append(results, sb.String())
})
sort.Strings(results)
fmt.Print(strings.Join(results, "\n"))
Output: [0 1 2]: c1: [[0 1 2]] [3 4]: c1: [[3 4]] c2: [[3 4]] [5 6]: c2: [[5 6]]
Example (Cache_iter) ¶
w := ecs.NewWorld()
// Create 10 entities.
var entities [10]ecs.Entity
for i := range entities {
entities[i] = ecs.NewEntity(w)
}
// Create 2 Components.
c1 := ecs.NewComponent(w)
c2 := ecs.NewComponent(w)
// Cache query
query := ecs.QueryAny(c1, c2).Cache(w)
// Add Components to entities.
for i, e := range entities[:5] {
ecs.SetComp(w, e, c1, int32(i))
}
for i, e := range entities[3:7] {
ecs.SetComp(w, e, c2, int64(i+3))
}
// Current layout:
//
// entity:[0 1 2 3 4 5 6 7 8 9]
// c1: [0 1 2 3 4 ]
// c2: [ 3 4 5 6 ]
// c1&c2: [ 3 4 ]
// CachedQuery all entities which have c1 or c2.
var results []string
for entity, data := range query.Iter {
// The type of the data's element is `Table[T]`,
// which can be converted to `[]T` only after type assertion.
results = append(results, fmt.Sprintf("e%v: [c1: %v c2: %v]", entity, data[0], data[1]))
}
sort.Strings(results)
fmt.Print(strings.Join(results, "\n"))
Output: e0: [c1: 0 c2: <nil>] e1: [c1: 1 c2: <nil>] e2: [c1: 2 c2: <nil>] e3: [c1: 3 c2: 3] e4: [c1: 4 c2: 4] e5: [c1: <nil> c2: 5] e6: [c1: <nil> c2: 6]
Example (Iter) ¶
w := ecs.NewWorld()
// Create 10 entities.
var entities [10]ecs.Entity
for i := range entities {
entities[i] = ecs.NewEntity(w)
}
// Create 2 Components.
c1 := ecs.NewComponent(w)
c2 := ecs.NewComponent(w)
// Add Components to entities.
for i, e := range entities[:5] {
ecs.SetComp(w, e, c1, int32(i))
}
for i, e := range entities[3:7] {
ecs.SetComp(w, e, c2, int64(i+3))
}
// Current layout:
//
// entity:[0 1 2 3 4 5 6 7 8 9]
// c1: [0 1 2 3 4 ]
// c2: [ 3 4 5 6 ]
// c1&c2: [ 3 4 ]
// CachedQuery all entities which have c1 or c2.
var results []string
for entity, data := range ecs.QueryAny(c1, c2).Iter(w) {
// The type of the data's element is `Table[T]`,
// which can be converted to `[]T` only after type assertion.
results = append(results, fmt.Sprintf("e%v: [c1: %v c2: %v]", entity, data[0], data[1]))
}
sort.Strings(results)
fmt.Print(strings.Join(results, "\n"))
Output: e0: [c1: 0 c2: <nil>] e1: [c1: 1 c2: <nil>] e2: [c1: 2 c2: <nil>] e3: [c1: 3 c2: 3] e4: [c1: 4 c2: 4] e5: [c1: <nil> c2: 5] e6: [c1: <nil> c2: 6]
func (Filter) Cache ¶
func (f Filter) Cache(w *World) (q *CachedQuery)
type IDManager ¶
The IDManager is an internal structure which is used to generate/recycle entity IDs.
type Types ¶
type Types []ComponentMeta
Types is list of Components. It's sorted and able to be hashed. Allowing us to find the archetype by the hash of its type.
type World ¶
type World struct {
IDManager
// The default archetype for newly created entities, which contains no Components.
Zero *Archetype
// All entities in the World, including Components.
// Records their archetype's pointer and the index of the Comps belonging to the entity.
Entities map[Entity]*EntityRecord
// All archetypes in the World.
// The key of the map is the hash of the archetype's Types.
// And the value is the archetype's pointer.
Archetypes map[uint64]*Archetype
// This field stores maps for each component.
// Each map contains a list of archetypes that have the component.
// And the component's corresponding Storage index in the archetype.
//
// We can check if an archetype has a component by looking up the map.
//
// For any Component c and archetype a:
// col, ok := Components[c][a]
// If ok == true, then archetype a has component c, otherwise it doesn't.
// And if col == -1, archetype a has component c but doesn't contain any data,
// otherwise the col is the index of the component's Storage in the archetype.
Components map[Component]map[*Archetype]int
// For high performance, we cache the queries.
// But these caches will get outdated when new archetypes are created.
// We register all queries created here, and update them when new archetypes are created.
Queries Table[*CachedQuery]
// contains filtered or unexported fields
}
The World is the container for all ECS data. It stores the entities and their Components, does queries and runs systems.
--flecs.dev