ecs

package module
v3.0.8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 9, 2022 License: MIT Imports: 12 Imported by: 0

README

Entity Component System

A fast, zero reflection ECS (no more interface{}). Game Engine agnostic.

Requires Go 1.18

GoDoc

go get github.com/gabstv/ecs/v3

Example:

package mygame

import "github.com/gabstv/ecs/v3"

type Position struct {
	X, Y float64
}

// Pkg is required for the component registry to avoid using reflection
func (_ Position) Pkg() string {
	// ecs uses this string to identify which component registry to use
	return "main.Position" 
}

type Speed struct {
	X, Y float64
}

// Pkg is required for the component registry to avoid using reflection
func (_ Speed) Pkg() string {
	return "main.Speed"
}

func main() {
	world := ecs.NewWorld()

	// speed will be applied here
	exampleSys := ecs.NewSystem2[Position, Speed](1, world)
	exampleSys.Run = func(view *ecs.View2[Position, Speed]) {
		// you can get a reference to global (costly) variables
		// before running the view loop, like obtaining the delta time
		view.Each(func(_ ecs.Entity, pos *Position, speed *Speed) {
			pos.X += speed.X
			pos.Y += speed.Y
		})
	}

	e1 := world.NewEntity()

	ecs.Set(world, e1, Position{
		X: 10,
		Y: 20,
	})
	ecs.Set(world, e1, Speed{
		X: 1,
		Y: .5,
	})

	world.Step() // run all systems once
}

For a more detailed example, check the example folder.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Apply

func Apply[T ComponentType](w *World, e Entity, fn func(*T)) bool

Apply updates the component data for the given entity.

func Contains

func Contains[T ComponentType](w *World, e Entity) bool

Contains returns true if the given entity has the given component.

func Insert

func Insert[T any](s []T, k int, vs ...T) []T

Insert only copies elements in a[i:] once and allocates at most once. But, as of Go toolchain 1.16, due to lacking of optimizations to avoid elements clearing in the "make" call, the verbose way is not always faster.

Future compiler optimizations might implement both in the most efficient ways.

func RegisterGlobalSystem added in v3.0.2

func RegisterGlobalSystem[T ComponentType](info GlobalSystemInfo[T])

RegisterGlobalSystem registers a system to be included on every new world. All worlds initiated with NewWorld() will have this system included.

func RegisterGlobalSystem2 added in v3.0.2

func RegisterGlobalSystem2[T1, T2 ComponentType](info GlobalSystem2Info[T1, T2])

RegisterGlobalSystem2 registers a system to be included on every new world. All worlds initiated with NewWorld() will have this system included.

func RegisterGlobalSystem3 added in v3.0.2

func RegisterGlobalSystem3[T1, T2, T3 ComponentType](info GlobalSystem3Info[T1, T2, T3])

RegisterGlobalSystem3 registers a system to be included on every new world. All worlds initiated with NewWorld() will have this system included.

func RegisterGlobalSystem4 added in v3.0.2

func RegisterGlobalSystem4[T1, T2, T3, T4 ComponentType](info GlobalSystem4Info[T1, T2, T3, T4])

RegisterGlobalSystem4 registers a system to be included on every new world. All worlds initiated with NewWorld() will have this system included.

func Remove

func Remove(w *World, e Entity) bool

Remove removes an entity from the world. It will also remove all components attached to the entity. It returns false if the entity was not found.

func RemoveComponent added in v3.0.1

func RemoveComponent[T ComponentType](w *World, e Entity) bool

RemoveComponent removes the component data for the given entity. It returns false if the component was not found.

func Set

func Set[T ComponentType](w *World, e Entity, data T)

Set replaces or inserts the component data for the given entity. If you junst need to update a value, use Apply() instead.

func SortEntities

func SortEntities(s []Entity)

Types

type ComponentData

type ComponentData[T ComponentType] struct {
	Entity Entity
	Data   T
}

ComponentData holds the data T of an Entity.

type ComponentIndex

type ComponentIndex []ComponentIndexEntry

func (ComponentIndex) ToMap

func (e ComponentIndex) ToMap() map[string]int

type ComponentIndexEntry

type ComponentIndexEntry struct {
	Name  string
	Index int
}

type ComponentStore

type ComponentStore[T ComponentType] struct {
	// contains filtered or unexported fields
}

ComponentStore[T ComponentType] is a component data storage. The component data is stored in a slice ordered by the Entity (ID; ascending).

func GetComponentStore

func GetComponentStore[T ComponentType](w *World) *ComponentStore[T]

GetComponentStore returns the component store for the given component type and world instance.

func (*ComponentStore[T]) Apply

func (c *ComponentStore[T]) Apply(e Entity, fn func(*T)) bool

Apply passes a pointer of the component data to the function fn. This is used to read or update data in the component.

func (*ComponentStore[T]) Contains

func (c *ComponentStore[T]) Contains(e Entity) bool

Contains returns true if the entity has data of this component store.

func (*ComponentStore[T]) MergeJSONData

func (c *ComponentStore[T]) MergeJSONData(e Entity, jd []byte) error

MergeJSONData unmarshals the data into the component type of this component store.

func (*ComponentStore[T]) Remove

func (c *ComponentStore[T]) Remove(e Entity) bool

Remove removes the component data from this component store. It returns true if the component data was found (and then removed).

func (*ComponentStore[T]) Replace

func (c *ComponentStore[T]) Replace(e Entity, data T)

Replace adds or replaces the component data for the given entity.

type ComponentType

type ComponentType interface {
	Pkg() string
}

ComponentType is a data type that has a Pkg() function. It is used to identify a component type. It must be unique per type in a world.

type ComponentWatcher

type ComponentWatcher[T ComponentType] struct {
	ComponentAdded   func(e Entity)
	ComponentRemoved func(e Entity)
	// contains filtered or unexported fields
}

func (*ComponentWatcher[T]) Component

func (wa *ComponentWatcher[T]) Component() *ComponentStore[T]

func (*ComponentWatcher[T]) Destroy

func (wa *ComponentWatcher[T]) Destroy()

type DeserializedComponentData

type DeserializedComponentData struct {
	CI   int            `toml:"ci"` // component index
	Data toml.Primitive `toml:"data"`
}

type DeserializedEntity

type DeserializedEntity struct {
	UUID       uuid.UUID                   `toml:"uuid"`
	Components []DeserializedComponentData `toml:"components"`
}

type DeserializedWorld

type DeserializedWorld struct {
	Entities       []DeserializedEntity `toml:"entities"`
	ComponentIndex ComponentIndex       `toml:"component_index"`
	Enabled        bool                 `toml:"enabled"`
}

type Encoder

type Encoder interface {
	Encode(interface{}) error
}

type Entities

type Entities []Entity

func (Entities) MarshalBinary

func (e Entities) MarshalBinary() ([]byte, error)

func (Entities) MarshalJSON

func (e Entities) MarshalJSON() ([]byte, error)

func (Entities) MarshalText

func (e Entities) MarshalText() (text []byte, err error)

func (*Entities) UnmarshalBinary

func (e *Entities) UnmarshalBinary(data []byte) error

func (*Entities) UnmarshalJSON

func (e *Entities) UnmarshalJSON(b []byte) error

func (*Entities) UnmarshalText

func (e *Entities) UnmarshalText(text []byte) error

type Entity

type Entity uint64

func AddEntityUnique

func AddEntityUnique(cls []Entity, e Entity) []Entity

AddEntityUnique adds an entity to a slice if it is not already in the slice.

func RemoveEntityFromSlice

func RemoveEntityFromSlice(cls []Entity, e Entity) []Entity

RemoveEntityFromSlice removes an entity from a slice. This func is useful when you don't know if the slice is sorted.

func (Entity) MarshalBinary

func (e Entity) MarshalBinary() ([]byte, error)

func (Entity) MarshalJSON

func (e Entity) MarshalJSON() ([]byte, error)

func (Entity) MarshalText

func (e Entity) MarshalText() (text []byte, err error)

func (*Entity) UnmarshalBinary

func (e *Entity) UnmarshalBinary(data []byte) error

func (*Entity) UnmarshalJSON

func (e *Entity) UnmarshalJSON(b []byte) error

func (*Entity) UnmarshalText

func (e *Entity) UnmarshalText(text []byte) error

type Event added in v3.0.5

type Event struct {
	Name string
	Data interface{}
}

type GlobalSystem2Info added in v3.0.2

type GlobalSystem2Info[T1, T2 ComponentType] struct {
	ExecPriority         int
	ExecFlag             int
	ExecBuilder          func(w *World, s *System2[T1, T2]) func(view *View2[T1, T2])
	EntityAddedBuilder   func(w *World, s *System2[T1, T2]) func(e Entity)
	EntityRemovedBuilder func(w *World, s *System2[T1, T2]) func(e Entity)
	Initializer          func(w *World, s *System2[T1, T2])
	Finalizer            func(w *World, s *System2[T1, T2])
	WarmStart            bool
}

GlobalSystem2Info is the arg of RegisterGlobalSystem2

type GlobalSystem3Info added in v3.0.2

type GlobalSystem3Info[T1, T2, T3 ComponentType] struct {
	ExecPriority         int
	ExecFlag             int
	ExecBuilder          func(w *World, s *System3[T1, T2, T3]) func(view *View3[T1, T2, T3])
	EntityAddedBuilder   func(w *World, s *System3[T1, T2, T3]) func(e Entity)
	EntityRemovedBuilder func(w *World, s *System3[T1, T2, T3]) func(e Entity)
	Initializer          func(w *World, s *System3[T1, T2, T3])
	Finalizer            func(w *World, s *System3[T1, T2, T3])
	WarmStart            bool
}

GlobalSystem3Info is the arg of RegisterGlobalSystem3

type GlobalSystem4Info added in v3.0.2

type GlobalSystem4Info[T1, T2, T3, T4 ComponentType] struct {
	ExecPriority         int
	ExecFlag             int
	ExecBuilder          func(w *World, s *System4[T1, T2, T3, T4]) func(view *View4[T1, T2, T3, T4])
	EntityAddedBuilder   func(w *World, s *System4[T1, T2, T3, T4]) func(e Entity)
	EntityRemovedBuilder func(w *World, s *System4[T1, T2, T3, T4]) func(e Entity)
	Initializer          func(w *World, s *System4[T1, T2, T3, T4])
	Finalizer            func(w *World, s *System4[T1, T2, T3, T4])
	WarmStart            bool
}

GlobalSystem4Info is the arg of RegisterGlobalSystem4

type GlobalSystemInfo added in v3.0.2

type GlobalSystemInfo[T ComponentType] struct {
	ExecPriority         int
	ExecFlag             int
	ExecBuilder          func(w *World, s *System[T]) func(view *View[T])
	EntityAddedBuilder   func(w *World, s *System[T]) func(e Entity)
	EntityRemovedBuilder func(w *World, s *System[T]) func(e Entity)
	Initializer          func(w *World, s *System[T])
	Finalizer            func(w *World, s *System[T])
	WarmStart            bool
}

GlobalSystemInfo is the arg of RegisterGlobalSystem

type IComponentStore

type IComponentStore interface {
	Contains(e Entity) bool
	Remove(e Entity) bool
	MergeJSONData(e Entity, jd []byte) error
	// contains filtered or unexported methods
}

IComponentStore is an interface for component stores.

type ISystem

type ISystem interface {
	ID() int
	Execute()
	Priority() int
	Flag() int
}

type ListenerID added in v3.0.5

type ListenerID struct {
	Name string
	ID   int
}

type Printer

type Printer interface {
	Printf(fmt string, args ...interface{})
}
var (
	SerializerLogger Printer
)

type SerializedComponentData

type SerializedComponentData struct {
	CI   int         `toml:"ci"` // component index
	Data interface{} `toml:"data"`
}

type SerializedEntity

type SerializedEntity struct {
	UUID       uuid.UUID     `toml:"uuid"`
	Components []interface{} `toml:"components"`
}

type SerializedWorld

type SerializedWorld struct {
	Entities       []SerializedEntity `toml:"entities"`
	ComponentIndex ComponentIndex     `toml:"component_index"`
	Enabled        bool               `toml:"enabled"`
}

type Sortable

type Sortable[TI comparable, TD any] struct {
	Index TI
	Data  TD
}

type System

type System[T ComponentType] struct {
	Run func(view *View[T])
	// contains filtered or unexported fields
}

func NewSystem

func NewSystem[T ComponentType](priority int, world *World) *System[T]

func (System) Data added in v3.0.2

func (s System) Data() interface{}

func (*System[T]) Execute

func (s *System[T]) Execute()

func (System) Flag

func (s System) Flag() int

func (System) ID

func (s System) ID() int

func (System) Priority

func (s System) Priority() int

func (System) SetData added in v3.0.2

func (s System) SetData(data interface{})

func (System) SetFlag

func (s System) SetFlag(flag int)

func (*System[T]) WarmStart

func (s *System[T]) WarmStart()

WarmStart runs the OnEntityAdded callback for all entities in the world.

type System2

type System2[T1 ComponentType, T2 ComponentType] struct {
	Run func(view *View2[T1, T2])
	// contains filtered or unexported fields
}

func NewSystem2

func NewSystem2[T1 ComponentType, T2 ComponentType](priority int, world *World) *System2[T1, T2]

func (System2) Data added in v3.0.2

func (s System2) Data() interface{}

func (*System2[T1, T2]) Execute

func (s *System2[T1, T2]) Execute()

func (System2) Flag

func (s System2) Flag() int

func (System2) ID

func (s System2) ID() int

func (System2) Priority

func (s System2) Priority() int

func (System2) SetData added in v3.0.2

func (s System2) SetData(data interface{})

func (System2) SetFlag

func (s System2) SetFlag(flag int)

func (*System2[T1, T2]) WarmStart

func (s *System2[T1, T2]) WarmStart()

WarmStart runs the OnEntityAdded callback for all entities in the world.

type System3

type System3[T1 ComponentType, T2 ComponentType, T3 ComponentType] struct {
	Run func(view *View3[T1, T2, T3])
	// contains filtered or unexported fields
}

func NewSystem3

func NewSystem3[T1 ComponentType, T2 ComponentType, T3 ComponentType](priority int, world *World) *System3[T1, T2, T3]

func (System3) Data added in v3.0.2

func (s System3) Data() interface{}

func (*System3[T1, T2, T3]) Execute

func (s *System3[T1, T2, T3]) Execute()

func (System3) Flag

func (s System3) Flag() int

func (System3) ID

func (s System3) ID() int

func (System3) Priority

func (s System3) Priority() int

func (System3) SetData added in v3.0.2

func (s System3) SetData(data interface{})

func (System3) SetFlag

func (s System3) SetFlag(flag int)

func (*System3[T1, T2, T3]) WarmStart

func (s *System3[T1, T2, T3]) WarmStart()

WarmStart runs the OnEntityAdded callback for all entities in the world.

type System4

type System4[T1, T2, T3, T4 ComponentType] struct {
	Run func(view *View4[T1, T2, T3, T4])
	// contains filtered or unexported fields
}

func NewSystem4

func NewSystem4[T1, T2, T3, T4 ComponentType](priority int, world *World) *System4[T1, T2, T3, T4]

func (System4) Data added in v3.0.2

func (s System4) Data() interface{}

func (*System4[T1, T2, T3, T4]) Execute

func (s *System4[T1, T2, T3, T4]) Execute()

func (System4) Flag

func (s System4) Flag() int

func (System4) ID

func (s System4) ID() int

func (System4) Priority

func (s System4) Priority() int

func (System4) SetData added in v3.0.2

func (s System4) SetData(data interface{})

func (System4) SetFlag

func (s System4) SetFlag(flag int)

func (*System4[T1, T2, T3, T4]) WarmStart

func (s *System4[T1, T2, T3, T4]) WarmStart()

WarmStart runs the OnEntityAdded callback for all entities in the world.

type View

type View[T ComponentType] struct {
	// contains filtered or unexported fields
}

func NewView

func NewView[T ComponentType](w *World, onadded, onremoved func(e Entity)) *View[T]

func (*View[T]) Destroy

func (v *View[T]) Destroy() bool

func (*View[T]) Each

func (v *View[T]) Each(fn func(e Entity, d *T))

func (View) Len

func (vc View) Len() int

func (*View[T]) Raw

func (v *View[T]) Raw() []ComponentData[T]

Raw returns the raw component data for this view. WARNING: Use this only for fast copying the slice. Altering the original slice will most likely result in undefined behavior.

func (View) World

func (vc View) World() *World

type View2

type View2[T1 ComponentType, T2 ComponentType] struct {
	// contains filtered or unexported fields
}

func NewView2

func NewView2[T1 ComponentType, T2 ComponentType](w *World, onadded, onremoved func(e Entity)) *View2[T1, T2]

func (*View2[T1, T2]) Destroy

func (v *View2[T1, T2]) Destroy() bool

func (*View2[T1, T2]) Each

func (v *View2[T1, T2]) Each(fn func(e Entity, d1 *T1, d2 *T2))

func (View2) Len

func (vc View2) Len() int

func (View2) World

func (vc View2) World() *World

type View3

type View3[T1 ComponentType, T2 ComponentType, T3 ComponentType] struct {
	// contains filtered or unexported fields
}

func NewView3

func NewView3[T1 ComponentType, T2 ComponentType, T3 ComponentType](w *World, onadded, onremoved func(e Entity)) *View3[T1, T2, T3]

func (*View3[T1, T2, T3]) Destroy

func (v *View3[T1, T2, T3]) Destroy() bool

func (*View3[T1, T2, T3]) Each

func (v *View3[T1, T2, T3]) Each(fn func(e Entity, d1 *T1, d2 *T2, d3 *T3))

func (View3) Len

func (vc View3) Len() int

func (View3) World

func (vc View3) World() *World

type View4

type View4[T1 ComponentType, T2 ComponentType, T3 ComponentType, T4 ComponentType] struct {
	// contains filtered or unexported fields
}

func NewView4

func NewView4[T1 ComponentType, T2 ComponentType, T3 ComponentType, T4 ComponentType](w *World, onadded, onremoved func(e Entity)) *View4[T1, T2, T3, T4]

func (*View4[T1, T2, T3, T4]) Destroy

func (v *View4[T1, T2, T3, T4]) Destroy() bool

func (*View4[T1, T2, T3, T4]) Each

func (v *View4[T1, T2, T3, T4]) Each(fn func(e Entity, d1 *T1, d2 *T2, d3 *T3, d4 *T4))

func (View4) Len

func (vc View4) Len() int

func (View4) World

func (vc View4) World() *World

type Viewer

type Viewer interface {
	World() *World
	Len() int
	// contains filtered or unexported methods
}

type World

type World struct {
	// contains filtered or unexported fields
}

func NewEmptyWorld added in v3.0.2

func NewEmptyWorld() *World

NewEmptyWorld creates a new world. A world is not thread safe .I t shouldn't be shared between threads. NewEmptyWorld creates a new world with no systems.

func NewWorld

func NewWorld() *World

NewWorld creates a new world. A world is not thread safe .I t shouldn't be shared between threads. This function also adds the default systems to the world. To create a new world without any systems, use NewEmptyWorld()

func (*World) AllEntities

func (w *World) AllEntities() []Entity

AllEntities returns all entities in the world

func (*World) Data added in v3.0.6

func (w *World) Data() *container.Dictionary[string, interface{}]

func (*World) Enabled

func (w *World) Enabled() bool

func (*World) EntityByUUID

func (w *World) EntityByUUID(id uuid.UUID) (Entity, bool)

EntityByUUID returns the entity with the given UUID If the entity does not exist, an empty entity (0) is returned

func (*World) EntityUUID

func (w *World) EntityUUID(e Entity) uuid.UUID

EntityUUID returns the UUID of the entity If the entity exists, but no UUID is set, a new UUID is generated and set

func (*World) FireEvent added in v3.0.5

func (w *World) FireEvent(eventName string, data interface{})

func (*World) GetGenericComponent

func (w *World) GetGenericComponent(registryName string) IComponentStore

func (*World) IsLoading

func (w *World) IsLoading() bool

func (*World) MarshalTo

func (w *World) MarshalTo(dw io.Writer) error

MarshalTo marshals the world data to a writer

func (*World) NewEntity

func (w *World) NewEntity() Entity

func (*World) OnEvent added in v3.0.5

func (w *World) OnEvent(eventName string, fn func(e Event)) ListenerID

func (*World) Remove added in v3.0.1

func (w *World) Remove(e Entity) bool

Remove removes an Entity. It tries to delete the entity from all the component registries of this world.

func (*World) RemoveListener added in v3.0.5

func (w *World) RemoveListener(id ListenerID)

func (*World) RemoveSystem

func (w *World) RemoveSystem(id int) bool

func (*World) SetEnabled

func (w *World) SetEnabled(v bool)

func (*World) Step

func (w *World) Step()

func (*World) StepF

func (w *World) StepF(flag int)

func (*World) UnmarshalFrom

func (w *World) UnmarshalFrom(dr io.Reader) error

func (*World) UnmarshalFromMeta

func (w *World) UnmarshalFromMeta(md toml.MetaData, prim toml.Primitive) error

Directories

Path Synopsis
example

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL