Skip to content

Commit ba79e83

Browse files
authored
Remove dependency to Ebitengine (#122)
* chore: remove dependency to ebitengine * add .idea to .gitignore * update examples for bumping up dependencies * update readme
1 parent db59a18 commit ba79e83

File tree

15 files changed

+143
-242
lines changed

15 files changed

+143
-242
lines changed

.gitignore

+4-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@
1717
# VSCode
1818
.vscode
1919

20+
# Goland
21+
.idea
22+
2023
# Mac
2124
.DS_Store
2225

23-
vendor
26+
vendor

README.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
<img src="https://github.com/yohamta/donburi/actions/workflows/test.yaml/badge.svg" /> [![Go Reference](https://pkg.go.dev/badge/github.com/yohamta/donburi.svg)](https://pkg.go.dev/github.com/yohamta/donburi)
44

5-
Donburi is just another Entity Component System library for Ebitengine inspired by [legion](https://github.com/amethyst/legion).
5+
Donburi is an Entity Component System library for Go / Ebitengine inspired by [legion](https://github.com/amethyst/legion).
66

7-
It aims to be a feature rich and high performance [ECS](https://en.wikipedia.org/wiki/Entity_component_system) Library.
7+
It aims to be a feature rich and high-performance [ECS](https://en.wikipedia.org/wiki/Entity_component_system) Library.
88

99
## Contents
1010

@@ -34,6 +34,7 @@ It aims to be a feature rich and high performance [ECS](https://en.wikipedia.org
3434
- It avoids reflection for performance.
3535
- Ability to dynamically add or remove components from an entity.
3636
- Type-safe APIs powered by Generics
37+
- Zero dependencies
3738
- Provides [Features](#features) that are common in game dev (e.g., `math`, `transform`, `hieralchy`, `events`, etc) built on top of the ECS architecture.
3839

3940
## Examples

ecs/ecs.go

+6-11
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package ecs
22

33
import (
4-
"github.com/hajimehoshi/ebiten/v2"
54
"github.com/yohamta/donburi"
65
"github.com/yohamta/donburi/filter"
76
)
@@ -51,7 +50,8 @@ func (ecs *ECS) AddSystem(s System) *ECS {
5150
return ecs
5251
}
5352

54-
func (ecs *ECS) AddRenderer(l LayerID, r Renderer) *ECS {
53+
// AddRenderer adds a renderer.
54+
func (ecs *ECS) AddRenderer(l LayerID, r any) *ECS {
5555
ecs.getLayer(l).addRenderer(r)
5656
return ecs
5757
}
@@ -65,17 +65,17 @@ func (ecs *ECS) Update() {
6565
}
6666

6767
// DrawLayer executes all draw systems of the specified layer.
68-
func (ecs *ECS) DrawLayer(l LayerID, screen *ebiten.Image) {
69-
ecs.getLayer(l).draw(ecs, screen)
68+
func (ecs *ECS) DrawLayer(l LayerID, arg any) {
69+
ecs.getLayer(l).draw(ecs, arg)
7070
}
7171

7272
// Draw executes all draw systems.
73-
func (ecs *ECS) Draw(screen *ebiten.Image) {
73+
func (ecs *ECS) Draw(arg any) {
7474
for _, l := range ecs.layers {
7575
if l == nil {
7676
continue
7777
}
78-
l.draw(ecs, screen)
78+
l.draw(ecs, arg)
7979
}
8080
}
8181

@@ -116,8 +116,3 @@ func (ecs *ECS) getLayer(layerID LayerID) *Layer {
116116
}
117117
return ecs.layers[layerID]
118118
}
119-
120-
func (ecs *ECS) addRenderer(l LayerID, r Renderer) *ECS {
121-
ecs.getLayer(l).addRenderer(r)
122-
return ecs
123-
}

ecs/ecs_test.go

+9-10
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package ecs
33
import (
44
"testing"
55

6-
"github.com/hajimehoshi/ebiten/v2"
76
"github.com/yohamta/donburi"
87
"github.com/yohamta/donburi/filter"
98
)
@@ -23,7 +22,7 @@ func TestECS(t *testing.T) {
2322

2423
for _, sys := range systems {
2524
ecs.AddSystem(sys.system.Update)
26-
ecs.addRenderer(sys.layer, sys.system.Draw)
25+
ecs.AddRenderer(sys.layer, sys.system.Draw)
2726
}
2827

2928
ecs.Update()
@@ -48,7 +47,7 @@ func TestECS(t *testing.T) {
4847
}
4948
}
5049

51-
ecs.Draw(ebiten.NewImage(1, 1))
50+
ecs.Draw("test")
5251

5352
drawTests := []struct {
5453
system *testSystem
@@ -99,10 +98,10 @@ func TestECSLayer(t *testing.T) {
9998

10099
for _, sys := range systems {
101100
ecs.AddSystem(sys.system.Update)
102-
ecs.addRenderer(sys.layer, sys.system.Draw)
101+
ecs.AddRenderer(sys.layer, sys.system.Draw)
103102
}
104103

105-
ecs.DrawLayer(0, ebiten.NewImage(1, 1))
104+
ecs.DrawLayer(0, "test")
106105

107106
if systems[0].system.QueryCountDraw != 1 {
108107
t.Errorf("expected query count draw %d, got %d", 1, systems[0].system.QueryCountDraw)
@@ -118,9 +117,9 @@ func TestEmptyDefaultLayer(t *testing.T) {
118117

119118
TestLayer := LayerID(1)
120119

121-
ecs.AddRenderer(TestLayer, func(ecs *ECS, image *ebiten.Image) {})
120+
ecs.AddRenderer(TestLayer, func(ecs *ECS, arg string) {})
122121

123-
ecs.Draw(ebiten.NewImage(1, 1))
122+
ecs.Draw("test")
124123
}
125124

126125
var (
@@ -131,7 +130,7 @@ var (
131130
type testSystem struct {
132131
UpdatedIndex int
133132
DrawedIndex int
134-
DrawImage *ebiten.Image
133+
DrawArg string
135134
UpdateCount int
136135
DrawCount int
137136
Query *donburi.Query
@@ -150,9 +149,9 @@ func (ts *testSystem) Update(ecs *ECS) {
150149
}
151150
}
152151

153-
func (ts *testSystem) Draw(ecs *ECS, image *ebiten.Image) {
152+
func (ts *testSystem) Draw(ecs *ECS, arg string) {
154153
ts.DrawedIndex = testDrawedIndex
155-
ts.DrawImage = image
154+
ts.DrawArg = arg
156155
ts.DrawCount++
157156

158157
testDrawedIndex++

ecs/layer.go

+34-9
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,54 @@ package ecs
22

33
import (
44
"fmt"
5+
"reflect"
56

6-
"github.com/hajimehoshi/ebiten/v2"
77
"github.com/yohamta/donburi"
88
)
99

1010
type Layer struct {
1111
*layer
12-
renderers []Renderer
12+
renderers map[string][]any
1313
}
1414

1515
func newLayer(l *layer) *Layer {
16-
return &Layer{l, []Renderer{}}
16+
return &Layer{l, make(map[string][]any)}
1717
}
1818

19-
func (l *Layer) draw(e *ECS, i *ebiten.Image) {
20-
screen := i
21-
for _, s := range l.renderers {
22-
s(e, screen)
19+
func keyForType(typ reflect.Type) string {
20+
return fmt.Sprintf("%s/%s", typ.PkgPath(), typ.Name())
21+
}
22+
23+
func invoke(fn any, e *ECS, arg any) {
24+
v := reflect.ValueOf(fn)
25+
v.Call([]reflect.Value{reflect.ValueOf(e), reflect.ValueOf(arg)})
26+
}
27+
28+
func (l *Layer) draw(e *ECS, arg any) {
29+
key := keyForType(reflect.TypeOf(arg))
30+
for _, fn := range l.renderers[key] {
31+
invoke(fn, e, arg)
2332
}
2433
}
2534

26-
func (l *Layer) addRenderer(r Renderer) {
27-
l.renderers = append(l.renderers, r)
35+
func (l *Layer) addRenderer(r any) {
36+
// check renderer type is func(*ECS, any)
37+
typ := reflect.TypeOf(r)
38+
if typ.Kind() != reflect.Func {
39+
panic("renderer must be a function")
40+
}
41+
if typ.NumIn() != 2 {
42+
panic("renderer must have 2 arguments")
43+
}
44+
if typ.In(0) != reflect.TypeOf(&ECS{}) {
45+
panic("first argument must be *ECS")
46+
}
47+
if typ.NumOut() != 0 {
48+
panic("renderer must not have return values")
49+
}
50+
// add renderer
51+
key := keyForType(typ.In(1))
52+
l.renderers[key] = append(l.renderers[key], r)
2853
}
2954

3055
var (

ecs/system.go

+4-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
package ecs
22

3-
import (
4-
"github.com/hajimehoshi/ebiten/v2"
5-
)
6-
73
// UpdateSystem is a system that updates the world.
84
type System func(ecs *ECS)
95

106
// DrawSystem is a system that draws the world.
11-
type Renderer func(ecs *ECS, screen *ebiten.Image)
7+
type RendererWithArg[T Arg] func(ecs *ECS, arg *T)
8+
9+
// Arg is an argument of the renderer.
10+
type Arg interface{}

examples/bunnymark/go.mod

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
module github.com/yohamta/donburi/examples/bunnymark
22

3-
go 1.19
3+
go 1.21
44

55
replace github.com/yohamta/donburi => ../../
66

77
require (
8-
github.com/hajimehoshi/ebiten/v2 v2.5.3
8+
github.com/hajimehoshi/ebiten/v2 v2.6.6
99
github.com/jaypipes/ghw v0.10.0
1010
github.com/yohamta/donburi v0.0.0-00010101000000-000000000000
11-
golang.org/x/image v0.7.0
11+
golang.org/x/image v0.12.0
1212
)
1313

1414
require (
1515
github.com/StackExchange/wmi v1.2.1 // indirect
16-
github.com/ebitengine/purego v0.3.0 // indirect
16+
github.com/ebitengine/purego v0.6.0 // indirect
1717
github.com/ghodss/yaml v1.0.0 // indirect
1818
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20221017161538-93cebf72946b // indirect
1919
github.com/go-ole/go-ole v1.2.6 // indirect
@@ -23,9 +23,9 @@ require (
2323
github.com/mitchellh/go-homedir v1.1.0 // indirect
2424
github.com/pkg/errors v0.9.1 // indirect
2525
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56 // indirect
26-
golang.org/x/mobile v0.0.0-20230301163155-e0f57694e12c // indirect
27-
golang.org/x/sync v0.1.0 // indirect
28-
golang.org/x/sys v0.6.0 // indirect
26+
golang.org/x/mobile v0.0.0-20230922142353-e2f452493d57 // indirect
27+
golang.org/x/sync v0.3.0 // indirect
28+
golang.org/x/sys v0.12.0 // indirect
2929
gopkg.in/yaml.v2 v2.4.0 // indirect
3030
howett.net/plist v1.0.0 // indirect
3131
)

examples/bunnymark/go.sum

+13
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
55
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
66
github.com/ebitengine/purego v0.3.0 h1:BDv9pD98k6AuGNQf3IF41dDppGBOe0F4AofvhFtBXF4=
77
github.com/ebitengine/purego v0.3.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
8+
github.com/ebitengine/purego v0.6.0 h1:Yo9uBc1x+ETQbfEaf6wcBsjrQfCEnh/gaGUg7lguEJY=
9+
github.com/ebitengine/purego v0.6.0/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ=
810
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
911
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
1012
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20221017161538-93cebf72946b h1:GgabKamyOYguHqHjSkDACcgoPIz3w0Dis/zJ1wyHHHU=
@@ -15,6 +17,8 @@ github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiU
1517
github.com/hajimehoshi/bitmapfont/v2 v2.2.3 h1:jmq/TMNj352V062Tr5e3hAoipkoxCbY1JWTzor0zNps=
1618
github.com/hajimehoshi/ebiten/v2 v2.5.3 h1:jizHI6ig5YnNP+wyERJvhDabz4lkhJn06bhIgHWJwUo=
1719
github.com/hajimehoshi/ebiten/v2 v2.5.3/go.mod h1:mnHSOVysTr/nUZrN1lBTRqhK4NG+T9NR3JsJP2rCppk=
20+
github.com/hajimehoshi/ebiten/v2 v2.6.6 h1:E5X87Or4VwKZIKjeC9+Vr4ComhZAz9h839myF4Q21kc=
21+
github.com/hajimehoshi/ebiten/v2 v2.6.6/go.mod h1:gKgQI26zfoSb6j5QbrEz2L6nuHMbAYwrsXa5qsGrQKo=
1822
github.com/jaypipes/ghw v0.10.0 h1:UHu9UX08Py315iPojADFPOkmjTsNzHj4g4adsNKKteY=
1923
github.com/jaypipes/ghw v0.10.0/go.mod h1:jeJGbkRB2lL3/gxYzNYzEDETV1ZJ56OKr+CSeSEym+g=
2024
github.com/jaypipes/pcidb v1.0.0 h1:vtZIfkiCUE42oYbJS0TAq9XSfSmcsgo9IdxSm9qzYU8=
@@ -40,9 +44,13 @@ golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9t
4044
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
4145
golang.org/x/image v0.7.0 h1:gzS29xtG1J5ybQlv0PuyfE3nmc6R4qB73m6LUUmvFuw=
4246
golang.org/x/image v0.7.0/go.mod h1:nd/q4ef1AKKYl/4kft7g+6UyGbdiqWqTP1ZAbRoV7Rg=
47+
golang.org/x/image v0.12.0 h1:w13vZbU4o5rKOFFR8y7M+c4A5jXDC0uXTdHYRP8X2DQ=
48+
golang.org/x/image v0.12.0/go.mod h1:Lu90jvHG7GfemOIcldsh9A2hS01ocl6oNO7ype5mEnk=
4349
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
4450
golang.org/x/mobile v0.0.0-20230301163155-e0f57694e12c h1:Gk61ECugwEHL6IiyyNLXNzmu8XslmRP2dS0xjIYhbb4=
4551
golang.org/x/mobile v0.0.0-20230301163155-e0f57694e12c/go.mod h1:aAjjkJNdrh3PMckS4B10TGS2nag27cbKR1y2BpUxsiY=
52+
golang.org/x/mobile v0.0.0-20230922142353-e2f452493d57 h1:Q6NT8ckDYNcwmi/bmxe+XbiDMXqMRW1xFBtJ+bIpie4=
53+
golang.org/x/mobile v0.0.0-20230922142353-e2f452493d57/go.mod h1:wEyOn6VvNW7tcf+bW/wBz1sehi2s2BZ4TimyR7qZen4=
4654
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
4755
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
4856
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
@@ -56,6 +64,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
5664
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
5765
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
5866
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
67+
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
68+
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
5969
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
6070
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
6171
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -66,6 +76,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
6676
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
6777
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
6878
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
79+
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
80+
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
6981
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
7082
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
7183
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
@@ -75,6 +87,7 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
7587
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
7688
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
7789
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
90+
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
7891
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
7992
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
8093
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=

examples/bunnymark_ecs/go.mod

+7-8
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,30 @@
11
module github.com/yohamta/donburi/examples/bunnymark_ecs
22

3-
go 1.19
3+
go 1.21
44

55
replace github.com/yohamta/donburi => ../../
66

77
require (
8-
github.com/hajimehoshi/ebiten/v2 v2.5.3
8+
github.com/hajimehoshi/ebiten/v2 v2.6.6
99
github.com/jaypipes/ghw v0.10.0
1010
github.com/yohamta/donburi v0.0.0-00010101000000-000000000000
11-
golang.org/x/image v0.7.0
11+
golang.org/x/image v0.12.0
1212
)
1313

1414
require (
1515
github.com/StackExchange/wmi v1.2.1 // indirect
16-
github.com/ebitengine/purego v0.3.0 // indirect
16+
github.com/ebitengine/purego v0.6.0 // indirect
1717
github.com/ghodss/yaml v1.0.0 // indirect
18-
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20221017161538-93cebf72946b // indirect
1918
github.com/go-ole/go-ole v1.2.6 // indirect
2019
github.com/jaypipes/pcidb v1.0.0 // indirect
2120
github.com/jezek/xgb v1.1.0 // indirect
2221
github.com/kr/text v0.2.0 // indirect
2322
github.com/mitchellh/go-homedir v1.1.0 // indirect
2423
github.com/pkg/errors v0.9.1 // indirect
2524
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56 // indirect
26-
golang.org/x/mobile v0.0.0-20230301163155-e0f57694e12c // indirect
27-
golang.org/x/sync v0.1.0 // indirect
28-
golang.org/x/sys v0.6.0 // indirect
25+
golang.org/x/mobile v0.0.0-20230922142353-e2f452493d57 // indirect
26+
golang.org/x/sync v0.3.0 // indirect
27+
golang.org/x/sys v0.12.0 // indirect
2928
gopkg.in/yaml.v2 v2.4.0 // indirect
3029
howett.net/plist v1.0.0 // indirect
3130
)

0 commit comments

Comments
 (0)