donburi

package module
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Jan 21, 2022 License: CC0-1.0, MIT Imports: 7 Imported by: 196

README

donburi Donburi

Donburi is just another Entity Component System library for Ebiten inpired by legion.

It aims to be a feature rich and high performance ECS Library.

Contents

Features

  • It introduces the concept of archetype, which allows us to query entities very efficiently based on the components layout.
  • It is possible to combine And, Or, and Not conditions to perform complex queries for components.
  • It avoids reflection on every frame and uses unsafe.Pointer for performance.
  • Ability to dynamically add or remove components from an entity

There are many features that need to be added in the future (e.g., parent-child relationship, event-notification system etc).

Examples

To check all examples, visit this page.

The bunnymark example was adapted from mizu's code, which is made by sedyh.

Installation

go get github.com/yohamta/donburi

Getting Started

Worlds
import "github.com/yohamta/donburi"

world := donburi.NewWorld()

Entities can be inserted via either Create (for a single entity) or CreateMany (for a collection of entities with the same component types). The world will create a unique ID for each entity upon insertion that you can use to refer to that entity later.

// Component is any struct that holds some kind of data.
type PositionData struct {
  X, Y float64
}

type VelocityData struct {
  X, Y float64
}

// ComponentType represents kind of component which is used to create or query entities.
var Position = donburi.NewComponentType(PositionData{})
var Velocity = donburi.NewComponentType(VelocityData{})

// Create an entity by specifying components that the entity will have.
// Component data will be initialized by default value of the struct.
entity = world.Create(Position, Velocity);

// You can use entity (it's a wrapper of int64) to get an Entry object from World
// which allows you to access the components that belong to the entity.
entry := world.Entry(entity)
position := (*component.PositionData)(entry.Component(component.Position))
velocity := (*component.VelocityData)(entry.Component(component.Velocity))
position.X += velocity.X
position.Y += velocity.y
Queries

Queries allow for high performance and expressive iteration through the entities in a world, to find out what types of components are attached to it, to get component references, or to add and remove components.

You can search for entities which have all of a set of components.

// You can define a query by declaring what componet you want to find.
query := query.NewQuery(filter.Contains(component.Position, component.Velocity))

// You can then iterate through the entity found in the world
query.EachEntity(w, func(entry *donburi.Entry) {
  // An entry is an accessor to entity and its components.
  var position *component.PositionData = (*component.PositionData)(entry.Component(component.Position))
  var velocity *component.VelocityData = (*component.VelocityData)(entry.Component(component.Velocity))
  
  position.X += velocity.X
  position.Y += velocity.Y
})

There are other type of query filters such as And, Or, Exact and Not. You can combine them to find the target entities.

For example:

// This query retrieves entities that have an NpcTag and no Position component.
query := query.NewQuery(filter.And(
  filter.Contains(NpcTag),
  filter.Not(filter.Contains(Position))))
Systems

As of today, there is no function for the concept of a "System" in ECS. It is assumed that operations are performed on entities using queries.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var NewComponentType = component.NewComponentType

NewComponentType creates a new component type. The function is used to create a new component of the type. It receives a function that returns a pointer to a new component.

View Source
var Null = entity.Null

Null represents a invalid entity which is zero.

Functions

This section is empty.

Types

type ComponentType

type ComponentType = component.ComponentType

ComponentType represents a component type. It is used to add components to entities, and to filter entities based on their components. It contains a function that returns a pointer to a new component.

func NewTag

func NewTag() *ComponentType

NewTag is an utility to create a tag component. Which is just an component that contains no data.

type Entity

type Entity = entity.Entity

Entity is identifier of an entity. Entity is just a wrapper of uint64.

type Entry

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

Entry is a struct that contains an entity and a location in an archetype.

func (*Entry) AddComponent

func (e *Entry) AddComponent(ctype *component.ComponentType, components ...unsafe.Pointer)

AddComponent adds the component to the entity.

func (*Entry) Archetype

func (e *Entry) Archetype() *storage.Archetype

Archetype returns the archetype.

func (*Entry) Component

func (e *Entry) Component(ctype *component.ComponentType) unsafe.Pointer

Component returns the component.

func (*Entry) Entity

func (e *Entry) Entity() Entity

Entity returns the entity.

func (*Entry) RemoveComponent

func (e *Entry) RemoveComponent(ctype *component.ComponentType)

RemoveComponent removes the component from the entity.

func (*Entry) SetComponent

func (e *Entry) SetComponent(ctype *component.ComponentType, component unsafe.Pointer)

SetComponent sets the component.

type StorageAccessor

type StorageAccessor struct {
	// Index is the search index for the world.
	Index *storage.SearchIndex
	// Components is the component storage for the world.
	Components *storage.Components
	// Archetypes is the archetype storage for the world.
	Archetypes []*storage.Archetype
}

StorageAccessor is an accessor for the world's storage.

type World

type World interface {
	// Id returns the unique identifier for the world.
	Id() WorldId
	// Create creates a new entity with the specified components.
	Create(components ...*component.ComponentType) Entity
	// CreateMany creates a new entity with the specified components.
	CreateMany(n int, components ...*component.ComponentType) []Entity
	// Entry returns an entry for the specified entity.
	Entry(entity Entity) *Entry
	// Remove removes the specified entity.
	Remove(entity Entity)
	// Valid returns true if the specified entity is valid.
	Valid(e Entity) bool
	// Len returns the number of entities in the world.
	Len() int
	// StorageAccessor returns an accessor for the world's storage.
	// It is used to access components and archetypes by queries.
	StorageAccessor() StorageAccessor
}

World is a collection of entities and components.

func NewWorld

func NewWorld() World

NewWorld creates a new world.

type WorldId

type WorldId int

WorldId is a unique identifier for a world.

Directories

Path Synopsis
example
bunnymark command
examples
bunnymark module
bunnymark_ecs module
platformer module
internal

Jump to

Keyboard shortcuts

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