-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #15 from yohamta/fix-issue14
Fix a bug in moving components between archetypes
- Loading branch information
Showing
21 changed files
with
661 additions
and
319 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package storage | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/yohamta/donburi/internal/component" | ||
) | ||
|
||
func TestMatchesLayout(t *testing.T) { | ||
var ( | ||
ca = component.NewComponentType(struct{}{}) | ||
cb = component.NewComponentType(struct{}{}) | ||
) | ||
|
||
cmps := []*component.ComponentType{ca, cb} | ||
archetype := NewArchetype(0, NewLayout(cmps)) | ||
if !archetype.LayoutMatches(cmps) { | ||
t.Errorf("archetype should match the layout") | ||
} | ||
} | ||
|
||
func TestPushEntity(t *testing.T) { | ||
var ( | ||
ca = component.NewComponentType(struct{}{}) | ||
cb = component.NewComponentType(struct{}{}) | ||
) | ||
|
||
cmps := []*component.ComponentType{ca, cb} | ||
archetype := NewArchetype(0, NewLayout(cmps)) | ||
|
||
archetype.PushEntity(0) | ||
archetype.PushEntity(1) | ||
archetype.PushEntity(2) | ||
|
||
if len(archetype.Entities()) != 3 { | ||
t.Errorf("archetype should have 3 entities") | ||
} | ||
|
||
archetype.SwapRemove(1) | ||
if len(archetype.Entities()) != 2 { | ||
t.Errorf("archetype should have 2 entities") | ||
} | ||
|
||
expected := []int{0, 2} | ||
for i, entity := range archetype.Entities() { | ||
if int(entity) != expected[i] { | ||
t.Errorf("archetype should have entity %d", expected[i]) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
package storage | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/yohamta/donburi/internal/component" | ||
) | ||
|
||
func TestComponents(t *testing.T) { | ||
type ComponentData struct { | ||
ID string | ||
} | ||
var ( | ||
ca = component.NewComponentType(ComponentData{}) | ||
cb = component.NewComponentType(ComponentData{}) | ||
) | ||
|
||
components := NewComponents() | ||
|
||
tests := []*struct { | ||
layout *Layout | ||
archIdx ArchetypeIndex | ||
compIdx ComponentIndex | ||
ID string | ||
}{ | ||
{ | ||
NewLayout([]*component.ComponentType{ca}), | ||
0, | ||
0, | ||
"a", | ||
}, | ||
{ | ||
NewLayout([]*component.ComponentType{ca, cb}), | ||
1, | ||
1, | ||
"b", | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
tt.compIdx = components.PushComponents(tt.layout.Components(), tt.archIdx) | ||
} | ||
|
||
for _, tt := range tests { | ||
for _, comp := range tt.layout.Components() { | ||
st := components.Storage(comp) | ||
if !st.Contains(tt.archIdx, tt.compIdx) { | ||
t.Errorf("storage should contain the component at %d, %d", tt.archIdx, tt.compIdx) | ||
} | ||
dat := (*ComponentData)(st.Component(tt.archIdx, tt.compIdx)) | ||
dat.ID = tt.ID | ||
} | ||
} | ||
|
||
target := tests[0] | ||
storage := components.Storage(ca) | ||
|
||
var srcArchIdx ArchetypeIndex = target.archIdx | ||
var dstArchIdx ArchetypeIndex = 1 | ||
|
||
components.MoveComponent(ca, srcArchIdx, target.compIdx, dstArchIdx) | ||
|
||
if storage.Contains(srcArchIdx, target.compIdx) { | ||
t.Errorf("storage should not contain the component at %d, %d", target.archIdx, target.compIdx) | ||
} | ||
if components.componentIndices[srcArchIdx] != -1 { | ||
t.Errorf("component index should be -1 at %d but %d", srcArchIdx, components.componentIndices[srcArchIdx]) | ||
} | ||
|
||
newCompIdx := components.componentIndices[dstArchIdx] | ||
if !storage.Contains(dstArchIdx, newCompIdx) { | ||
t.Errorf("storage should contain the component at %d, %d", dstArchIdx, target.compIdx) | ||
} | ||
|
||
dat := (*ComponentData)(storage.Component(dstArchIdx, newCompIdx)) | ||
if dat.ID != target.ID { | ||
t.Errorf("component should have ID %s", target.ID) | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package storage | ||
|
||
import ( | ||
"github.com/yohamta/donburi/filter" | ||
"github.com/yohamta/donburi/internal/component" | ||
) | ||
|
||
type ArchetypeIterator struct { | ||
current int | ||
values []ArchetypeIndex | ||
} | ||
|
||
func (it *ArchetypeIterator) HasNext() bool { | ||
return it.current < len(it.values) | ||
} | ||
|
||
func (it *ArchetypeIterator) Next() ArchetypeIndex { | ||
val := it.values[it.current] | ||
it.current++ | ||
return val | ||
} | ||
|
||
// Index is a structure that indexes archetypes by their component types. | ||
type Index struct { | ||
layouts [][]*component.ComponentType | ||
iterator *ArchetypeIterator | ||
} | ||
|
||
// NewIndex creates a new search index. | ||
func NewIndex() *Index { | ||
return &Index{ | ||
layouts: [][]*component.ComponentType{}, | ||
iterator: &ArchetypeIterator{ | ||
current: 0, | ||
}, | ||
} | ||
} | ||
|
||
// Push adds an archetype to the search index. | ||
func (idx *Index) Push(layout *Layout) { | ||
idx.layouts = append(idx.layouts, layout.Components()) | ||
} | ||
|
||
// SearchFrom searches for archetypes that match the given filter from the given index. | ||
func (idx *Index) SearchFrom(f filter.LayoutFilter, start int) *ArchetypeIterator { | ||
idx.iterator.current = 0 | ||
idx.iterator.values = []ArchetypeIndex{} | ||
for i := start; i < len(idx.layouts); i++ { | ||
if f.MatchesLayout(idx.layouts[i]) { | ||
idx.iterator.values = append(idx.iterator.values, ArchetypeIndex(i)) | ||
} | ||
} | ||
return idx.iterator | ||
} | ||
|
||
// Search searches for archetypes that match the given filter. | ||
func (idx *Index) Search(filter filter.LayoutFilter) *ArchetypeIterator { | ||
return idx.SearchFrom(filter, 0) | ||
} |
Oops, something went wrong.