Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add examples for FilterX, QueryX and other Xes #165

Merged
merged 5 commits into from
Mar 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@

- Implements archetype graph for faster lookup on transitions (#104)
- Optimizes query creation with 50% speedup (#144)
- Optimize component operations with average 20% speedup (#146)
- Optimizes component operations with average 20% speedup (#146)

### Bugfixes

Expand Down
118 changes: 105 additions & 13 deletions ecs/examples_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,6 @@ package ecs_test

import "github.com/mlange-42/ark/ecs"

type Position struct {
X, Y float64
}

type Velocity struct {
X, Y float64
}

type Grid struct {
Width int
Height int
}

func NewGrid(width, height int) Grid {
return Grid{
Width: width,
Expand All @@ -25,3 +12,108 @@ func NewGrid(width, height int) Grid {
func (g *Grid) Get(x, y int) ecs.Entity {
return ecs.Entity{}
}

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

// A simple filter for components (non-exclusive).
simpleFilter := ecs.NewFilter2[Position, Velocity](&world)

// A simple filter with an additional (unused) and an excluded component.
complexFilter := ecs.NewFilter2[Position, Velocity](&world).
With(ecs.C[Altitude]()).
Without(ecs.C[ChildOf]())

// A cached/registered filter, with an additional (unused) component.
cachedFilter := ecs.NewFilter2[Position, Velocity](&world).
With(ecs.C[Altitude]()).
Register()

// Create a query from a filter, and iterate it.
query := simpleFilter.Query()
for query.Next() {
// ...
}

_, _ = complexFilter, cachedFilter
// Output:
}

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

// A simple filter.
filter := ecs.NewFilter2[Position, Velocity](&world)

// Create a fresh query before iterating.
query := filter.Query()
for query.Next() {
// Access components of the current entity.
pos, vel := query.Get()
// Access the current entity itself.
entity := query.Entity()
// ...
_, _, _ = pos, vel, entity
}
// Output:
}

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

// Create a component mapper.
mapper := ecs.NewMap[Position](&world)

// Create an entity.
entity := mapper.NewEntity(&Position{X: 100, Y: 100})

// Remove component from the entity.
mapper.Remove(entity)
// Add component to the entity.
mapper.Add(entity, &Position{X: 100, Y: 100})
// Output:
}

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

// Create a component mapper.
mapper := ecs.NewMap2[Position, Velocity](&world)

// Create an entity.
entity := mapper.NewEntity(&Position{X: 100, Y: 100}, &Velocity{X: 1, Y: -1})

// Remove components from the entity.
mapper.Remove(entity)
// Add components to the entity.
mapper.Add(entity, &Position{X: 100, Y: 100}, &Velocity{X: 1, Y: -1})
// Output:
}

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

// Create a component mapper.
mapper := ecs.NewMap[Altitude](&world)

// Create an exchange helper.
// Adds Position and Velocity, removes Altitude.
exchange := ecs.NewExchange2[Position, Velocity](&world).
Removes(ecs.C[Altitude]())

// Create an entity with an Altitude component.
entity := mapper.NewEntity(&Altitude{Z: 10_000})

// Remove Altitude and add Position and Velocity.
exchange.Exchange(entity, &Position{X: 100, Y: 100}, &Velocity{X: 1, Y: -1})

// Create another entity.
entity = mapper.NewEntity(&Altitude{Z: 10_000})

// Remove Altitude.
exchange.Remove(entity)

// Add Position and Velocity.
exchange.Add(entity, &Position{X: 100, Y: 100}, &Velocity{X: 1, Y: -1})
// Output:
}
14 changes: 14 additions & 0 deletions ecs/exchange_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 25 additions & 0 deletions ecs/filter_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions ecs/generate/exchange.go.template
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ import "unsafe"
// to set components to be removed.
//
// Instances should be created during initialization and stored, e.g. in systems.
{{- if ne . 2 }}
//
// See [Exchange2] for a usage example.
{{- end}}
type Exchange{{.}}{{$generics}} struct {
world *World
ids []ID
Expand Down
5 changes: 5 additions & 0 deletions ecs/generate/filter.go.template
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,13 @@ package ecs
{{- end}}

// Filter{{.}} is a filter for {{.}} components.
// Used to create [Query{{.}}] iterators.
//
// Instances should be created during initialization and stored, e.g. in systems.
{{- if ne . 2 }}
//
// See [Filter2] for a usage example.
{{- end}}
type Filter{{.}}{{$generics}} struct {
world *World
ids []ID
Expand Down
4 changes: 4 additions & 0 deletions ecs/generate/maps.go.template
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ import "unsafe"
// Map{{.}} is a mapper to access {{.}} components of an entity.
//
// Instances should be created during initialization and stored, e.g. in systems.
{{- if ne . 2 }}
//
// See [Map2] for a usage example.
{{- end}}
type Map{{.}}{{$generics}} struct {
world *World
ids []ID
Expand Down
6 changes: 5 additions & 1 deletion ecs/generate/query.go.template
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,13 @@ type cursor struct {
{{- end}}

// Query{{.}} is a query for {{.}} components.
// Use a [NewFilter{{.}}] to create one.
// Use a [Filter{{.}}] to create one.
//
// Queries are one-time use iterators and must be re-created each time before iterating.
{{- if ne . 2 }}
//
// See [Query2] for a usage example.
{{- end}}
type Query{{.}}{{$generics}} struct {
world *World
filter *filter
Expand Down
Loading
Loading