Categorygithub.com/kostayne/ecs
repository
2.1.0+incompatible
Repository: https://github.com/kostayne/ecs.git
Documentation: pkg.go.dev

# Packages

No description provided by the author
No description provided by the author
No description provided by the author

# README

Kostayne ECS

GitHub Tag GitHub License GitHub Actions Workflow Status GitHub top language

This package provides a basic implementation of Entity Component System pattern. ECS separates logic from data, which makes the app more scalable and flexible. It's ideal for complex games or simulations.

Definitions

Entity - a unique object in the world, it has no any logic.

Component - a piece of data that can be attached to an entity.

System - a set of logic that can be applied to the entity.

TOC

Usage

Define components

First, we'll define a simple component (component.go):

package example

type PositionComponent struct {
	X float64
	Y float64
}

func (c *PositionComponent) Type() string {
	return "position"
}

func MakePositionComponent(x, y float64) *PositionComponent {
	return &PositionComponent{
		X: x,
		Y: y,
	}
}

Define systems

Next, we'll define a simple system (system.go):

package example

import (
	"github.com/kostayne/ecs/core"
)

type MovementSystem struct{}

func (s *MovementSystem) GetType() string {
	return "sys_movement"
}

// Hooks
func (s *MovementSystem) Setup(es *core.EntityStore) {}
func (s *MovementSystem) Cleanup(es *core.EntityStore) {}

// Params
func (s *MovementSystem) GetPriority() int   { return 0 }
func (s *MovementSystem) GetFrequency() uint { return 0 }

// Main logic
func (s *MovementSystem) Process(es *core.EntityStore, dt time.Duration) {
	finder := core.MakeFinder(es)
	entities := finder.Has("position").GetMany()

	for _, e := range entities {
		comp := *e.GetOne("position")
		pos := comp.(*PositionComponent)

		// one line version
		// pos := (*e.GetOne("position")).(*PositionComponent)

		pos.X += 1
		pos.Y += 2
	}
}

func MakeMovementSystem() *MovementSystem {
	return &MovementSystem{}
}

Start the app

Finally, we'll start the app (app.go):

package example

import (
	"fmt"

	"github.com/kostayne/ecs/core"
)

func main() {
	ecs := core.MakeECS()

	// create component & system instances
	moveSys := MakeMovementSystem()
	posComp := MakePositionComponent(0, 0)

	// add them to ecs
	player := ecs.EntityStore.New(posComp)
	ecs.SystemStore.Add(moveSys)

	ecs.Setup()

	// run the main loop
	for i := 0; i < 5; i++ {
		ecs.Process()
		fmt.Printf("XY: (%v, %v)\n", posComp.X, posComp.Y)
	}

	ecs.Cleanup()
}

Wiki

To find out more, see the documentation.

ECS

ECS is a core data structure that holds all entities and their components.

type ECS struct {
	EntityStore EntityStore
	SystemStore SystemStore
}

EntityStore

Use entity store to manage entities.

Manage entities

entity := ecs.EntityStore.New()
ecs.EntityStore.Remove(entity.Id())
ecs.EntityStore.GetAll(entity.Id())

Manage components

ecs.EntityStore.GetComponentsById(entity.Id())
ecs.EntityStore.AddTo(entity.Id(), MakePositionComponent(0, 0))
ecs.EntityStore.RemoveFrom(entity.Id(), "position")

Finder

Finder is a helper that allows to find entities by components or arbitrary criteria.

--- Finder Interface ---

type FinderI interface {
	Get() Entity
	GetMany() []Entity
	Has(components ...string) *FinderI
	Where(predicate func(*Entity) bool) *FinderI
}

--- Finder Constructor ---

ecs := core.MakeECS()

finder := core.MakeFinder(&ecs.SystemStore)

--- Finder Methods ---

Finder.Has(components ...string) *Finder

Returns a finder with entities that have provided components.

entities := finder.Has("position", "velocity").GetMany()

Finder.Where(predicate func(*Entity) bool) *Finder

Returns a finder with entities that match provided predicate.

func isEntityOnTheRight(e *Entity) bool {
	pos := (*e.GetOne("position")).(*PositionComponent)
	return pos.X > 0
}

entities := finder.Where(isEntityOnTheRight).GetMany()

Finder.GetOne() *Entity

Returns a single matched entity.

player := finder.Has("character_controller").GetOne()

Finder.GetMany() []*Entity

Returns a list of matched entities.

weapons := finder.Has("weapon").GetMany()