kiwi-ecs 0.0.2 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b17b772e56b3533bac84c71c609eb8544908667c4cac99725327399d1fd44fed
4
- data.tar.gz: d8669b034e3db56f038919b60aa8f7f2b36eb6b98e7f12d22f533ac2c2680454
3
+ metadata.gz: 3c28c74f941f35abc3fe5ae1d565f8942f7676b01341e4c3efeef7969dcb1512
4
+ data.tar.gz: 6ac603e29b87be9c27da787dc330291f8c6bc8ce28e8807e4b8d36294609638e
5
5
  SHA512:
6
- metadata.gz: f5e2f0b3770ffe2eeebd64f590aec863fc8074f4ec1331578f1a7f5ee42ac69e8ca257c3cf9717f8e7b43c876dbe80f946e9e74045e0a4efa9feaeb78b8b05c7
7
- data.tar.gz: a42b7f00ee919b7cd1d37f70c0a19f1b217d429f604f67e0a99734c4de4336d7bcecea9235e244fb884c93288f06df38c9b9e4a453520e7ce86809c92ad5a6e0
6
+ metadata.gz: db0833836918141ec6f231b943c9c2fb6455e232c6d451cb46b80ff949eb245a164d037dfd984054af69019bf717ebe380734c6a74a1493db429623ed22825d1
7
+ data.tar.gz: a1d9e6d195d65505ea25f21f5cc98224c4bf4729adaca7fb4a0fa9725a74e3748956853d7fda3e22d6108eab4d98651a612a10b847784f8bee3c99f47f3bd7b3
data/README.md ADDED
@@ -0,0 +1,145 @@
1
+ # Kiwi
2
+
3
+ Kiwi is a versatile entity component system focussing on fast iteration and a nice api.
4
+
5
+ To get started, read the [usage guide](#usage) below.
6
+
7
+ [![Tests](https://github.com/Jomy10/kiwi-ecs-ruby/actions/workflows/tests.yml/badge.svg)](https://github.com/Jomy10/kiwi-ecs-ruby/actions/workflows/tests.yml)
8
+
9
+ ## Installation
10
+
11
+ The library is available from [ruby gems](https://rubygems.org/gems/kiwi-ecs):
12
+
13
+ ```sh
14
+ gem install kiwi-ecs
15
+ ```
16
+
17
+ To use it in your ruby source files:
18
+
19
+ ```ruby
20
+ require 'kiwi-ecs'
21
+ ```
22
+
23
+ ## Usage
24
+
25
+ ### The world
26
+
27
+ The world is the main object that controls the ecs.
28
+
29
+ ```ruby
30
+ world = Kiwi::World.new
31
+ ```
32
+
33
+ ### Components
34
+
35
+ Creating a component is as simple as declaring a struct:
36
+
37
+ ```ruby
38
+ Position = Struct.new :x, :y
39
+ ```
40
+
41
+ Classes can also be used instead of structs
42
+
43
+ ```ruby
44
+ class Velocity
45
+ attr_accessor :x
46
+ attr_accessor :y
47
+ end
48
+ ```
49
+
50
+ ### Entities
51
+
52
+ An entity is spawned with a set of components:
53
+
54
+ ```ruby
55
+ entityId = world.spawn(Position.new(10, 10))
56
+
57
+ world.spawn(Position.new(3, 5), Velocity.new(1.5, 0.0))
58
+ ```
59
+
60
+ The `world.spawn(*components)` function will return the id of the spawned entity.
61
+
62
+ Killing an entity can be done using `world.kill(entityId)`:
63
+
64
+ ```ruby
65
+ world.kill(entityId)
66
+ ```
67
+
68
+ ### Systems
69
+
70
+ #### Queries
71
+
72
+ Queries can be constructed as follows:
73
+
74
+ ```ruby
75
+ # Query all position componentss
76
+ world.query(Position) do |pos|
77
+ puts pos
78
+ end
79
+
80
+ # Query all entities having a position and a velocity component, and their entity ids
81
+ world.query_with_ids(Position, Velocity) do |id, pos, vel|
82
+ # ...
83
+ end
84
+ ```
85
+
86
+ ### Flags
87
+
88
+ Entities can be tagged using flags
89
+
90
+ #### Defining flags
91
+
92
+ A flag is an integer
93
+
94
+ ```ruby
95
+ module Flags
96
+ Player = 0
97
+ Enemy = 1
98
+ end
99
+ ```
100
+
101
+ #### Setting flags
102
+
103
+ ```ruby
104
+ id = world.spawn
105
+
106
+ world.set_flag(id, Flags::Player)
107
+ ```
108
+
109
+ #### Removing a flag
110
+
111
+ ```ruby
112
+ world.remove_flag(id, Flags::Player)
113
+ ```
114
+
115
+ #### Checking wether an entity has a flag
116
+
117
+ ```ruby
118
+ world.has_flag(id, Flags::Player)
119
+ ```
120
+
121
+ #### Filtering queries with flags
122
+
123
+ ```ruby
124
+ world.query_with_ids(Pos)
125
+ .filter do |id, pos|
126
+ world.has_flag(id, Flags::Player)
127
+ end
128
+ .each do |id, pos|
129
+ # Do something with the filtered query
130
+ end
131
+ ```
132
+
133
+ The `hasFlags` function is also available for when you want to check multiple flags.
134
+
135
+ ## Road map
136
+
137
+ - [ ] System groups
138
+
139
+ ## Contributing
140
+
141
+ Contributors are welcome to open an issue requesting new features or fixes or opening a pull request for them.
142
+
143
+ ## License
144
+
145
+ The library is licensed under LGPLv3.
data/lib/arch_store.rb CHANGED
@@ -1,5 +1,9 @@
1
1
  require_relative 'archetype'
2
2
 
3
+ module Kiwi
4
+ # Internal methods not meant for outside use
5
+ module Internal
6
+
3
7
  class ArchStore
4
8
  # [[Integer]:Integer]
5
9
  attr_accessor :compMap
@@ -28,3 +32,6 @@ class ArchStore
28
32
  end
29
33
  end
30
34
  end
35
+
36
+ end
37
+ end
data/lib/archetype.rb CHANGED
@@ -1,93 +1,97 @@
1
1
  ComponentColumn = Struct.new(:components)
2
2
 
3
- class Archetype
4
- # @params [Array<Integer>] componentIds
5
- def initialize(componentIds)
6
- # [Integer(componentId): ComponentColumn]
7
- @components = componentIds.map do |compId|
8
- [compId, ComponentColumn.new([])]
9
- end.to_h
10
- @availableEntityRows = []
11
- @entities = []
12
- end
13
-
14
- # @return [int]
15
- def new_arch_row_id(entityId)
16
- id = @availableEntityRows.pop
17
- if id != nil
18
- @entities[id] = entityId
19
- return id
20
- else
21
- id = @entities.size
22
- @entities.push entityId
23
- return id
24
- end
25
- end
26
-
27
- def set_component(archRowId, component)
28
- compCol = @components[component.class.object_id]
29
- if compCol.components.size <= archRowId
30
- compCol.components.push component
31
- else
32
- compCol.components[archRowId] = component
33
- end
34
- end
35
-
36
- def get_component(archRowId, componentId)
37
- return @components[componentId].components[archRowId]
38
- end
39
-
40
- def has_component(componentId)
41
- return @components[componentId] != nil
42
- end
3
+ module Kiwi
4
+ module Internal
5
+ class Archetype
6
+ # @params [Array<Integer>] componentIds
7
+ def initialize(componentIds)
8
+ # [Integer(componentId): ComponentColumn]
9
+ @components = componentIds.map do |compId|
10
+ [compId, ComponentColumn.new([])]
11
+ end.to_h
12
+ @availableEntityRows = []
13
+ @entities = []
14
+ end
43
15
 
44
- def remove_entity(archRowId)
45
- @availableEntityRows.push(archRowId)
46
- @entities[archRowId] = nil
47
- end
16
+ # @return [int]
17
+ def new_arch_row_id(entityId)
18
+ id = @availableEntityRows.pop
19
+ if id != nil
20
+ @entities[id] = entityId
21
+ return id
22
+ else
23
+ id = @entities.size
24
+ @entities.push entityId
25
+ return id
26
+ end
27
+ end
48
28
 
49
- # @return [[Component, EntityId]]
50
- def active_components(componentIds)
51
- # [comp1a, comp1b]
52
- # [comp2a, comp2b]
53
- # ...
54
- components = componentIds
55
- .map do |compId|
56
- @components[compId].components
29
+ def set_component(archRowId, component)
30
+ compCol = @components[component.class.object_id]
31
+ if compCol.components.size <= archRowId
32
+ compCol.components.push component
33
+ else
34
+ compCol.components[archRowId] = component
35
+ end
57
36
  end
58
- compCount = componentIds.size
59
37
 
60
- @entities
61
- .each_with_index
62
- .filter do |entId, _|
63
- entId != nil
38
+ def get_component(archRowId, componentId)
39
+ return @components[componentId].components[archRowId]
64
40
  end
65
- .map do |_, rowIdx|
66
- (0...compCount).map do |compRowId|
67
- components[compRowId][rowIdx]
68
- end
41
+
42
+ def has_component(componentId)
43
+ return @components[componentId] != nil
69
44
  end
70
- end
71
45
 
72
- def components_and_ids(componentIds)
73
- # [comp1a, comp1b]
74
- # [comp2a, comp2b]
75
- # ...
76
- components = componentIds
77
- .map do |compId|
78
- @components[compId].components
46
+ def remove_entity(archRowId)
47
+ @availableEntityRows.push(archRowId)
48
+ @entities[archRowId] = nil
79
49
  end
80
- compCount = componentIds.size
81
50
 
82
- @entities
83
- .each_with_index
84
- .filter do |entId, _|
85
- entId != nil
51
+ # @return [[Component, EntityId]]
52
+ def active_components(componentIds)
53
+ # [comp1a, comp1b]
54
+ # [comp2a, comp2b]
55
+ # ...
56
+ components = componentIds
57
+ .map do |compId|
58
+ @components[compId].components
59
+ end
60
+ compCount = componentIds.size
61
+
62
+ @entities
63
+ .each_with_index
64
+ .filter do |entId, _|
65
+ entId != nil
66
+ end
67
+ .map do |_, rowIdx|
68
+ (0...compCount).map do |compRowId|
69
+ components[compRowId][rowIdx]
70
+ end
71
+ end
86
72
  end
87
- .map do |entId, rowIdx|
88
- [entId, *(0...compCount).map do |compRowId|
89
- components[compRowId][rowIdx]
90
- end]
73
+
74
+ def components_and_ids(componentIds)
75
+ # [comp1a, comp1b]
76
+ # [comp2a, comp2b]
77
+ # ...
78
+ components = componentIds
79
+ .map do |compId|
80
+ @components[compId].components
81
+ end
82
+ compCount = componentIds.size
83
+
84
+ @entities
85
+ .each_with_index
86
+ .filter do |entId, _|
87
+ entId != nil
88
+ end
89
+ .map do |entId, rowIdx|
90
+ [entId, *(0...compCount).map do |compRowId|
91
+ components[compRowId][rowIdx]
92
+ end]
93
+ end
91
94
  end
95
+ end
92
96
  end
93
97
  end
data/lib/bitmap.rb CHANGED
@@ -1,3 +1,6 @@
1
+ module Kiwi
2
+ module Internal
3
+
1
4
  # TODO: actual bitmap implementation
2
5
  class Bitmap
3
6
  def initialize
@@ -30,3 +33,6 @@ class Bitmap
30
33
  end
31
34
  end
32
35
  end
36
+
37
+ end
38
+ end
data/lib/entity.rb CHANGED
@@ -1,6 +1,9 @@
1
1
  require 'set'
2
2
  require_relative 'bitmap'
3
3
 
4
+ module Kiwi
5
+ module Internal
6
+
4
7
  Entity = Struct.new(:archId, :archRow)
5
8
 
6
9
  class EntityStore
@@ -100,3 +103,6 @@ class EntityStore
100
103
  end
101
104
  end
102
105
  end
106
+
107
+ end
108
+ end
data/lib/query.rb CHANGED
@@ -1,3 +1,5 @@
1
+ module Kiwi
2
+ module Internal
1
3
  module Query
2
4
  # @return [enumerator<Integer>]
3
5
  def query_ids
@@ -54,3 +56,5 @@ module Query
54
56
  end
55
57
  end
56
58
  end
59
+ end
60
+ end
data/lib/world.rb CHANGED
@@ -2,63 +2,65 @@ require_relative 'entity'
2
2
  require_relative 'arch_store'
3
3
  require_relative 'query'
4
4
 
5
- class World
6
- def initialize
7
- @entityStore = EntityStore.new
8
- @archStore = ArchStore.new
9
- end
5
+ module Kiwi
6
+ class World
7
+ def initialize
8
+ @entityStore = Kiwi::Internal::EntityStore.new
9
+ @archStore = Kiwi::Internal::ArchStore.new
10
+ end
10
11
 
11
- def spawn(*components)
12
- compIds = components.map { |c| c.class.object_id }.sort
13
- archId = @archStore.get_archetype_id(compIds)
14
- entId = @entityStore.new_id
15
- archetype = @archStore.get(archId)
16
- archRowId = archetype.new_arch_row_id(entId)
17
- @entityStore.spawn(entId, archId, archRowId)
18
- for component in components
19
- archetype.set_component(archRowId, component)
12
+ def spawn(*components)
13
+ compIds = components.map { |c| c.class.object_id }.sort
14
+ archId = @archStore.get_archetype_id(compIds)
15
+ entId = @entityStore.new_id
16
+ archetype = @archStore.get(archId)
17
+ archRowId = archetype.new_arch_row_id(entId)
18
+ @entityStore.spawn(entId, archId, archRowId)
19
+ for component in components
20
+ archetype.set_component(archRowId, component)
21
+ end
22
+ return entId
20
23
  end
21
- return entId
22
- end
23
24
 
24
- def get_component(entityId, componentType)
25
- entity = @entityStore.get(entityId)
26
- archetype = @archStore.get(entity.archId)
27
- archetype.get_component(entity.archRow, componentType.object_id)
28
- end
25
+ def get_component(entityId, componentType)
26
+ entity = @entityStore.get(entityId)
27
+ archetype = @archStore.get(entity.archId)
28
+ archetype.get_component(entity.archRow, componentType.object_id)
29
+ end
29
30
 
30
- def kill(entityId)
31
- entity = @entityStore.get entityId
32
- @entityStore.kill(entityId)
33
- archetype = @archStore.get(entity.archId)
34
- archetype.remove_entity(entity.archRow)
35
- end
31
+ def kill(entityId)
32
+ entity = @entityStore.get entityId
33
+ @entityStore.kill(entityId)
34
+ archetype = @archStore.get(entity.archId)
35
+ archetype.remove_entity(entity.archRow)
36
+ end
36
37
 
37
- def entity_count
38
- return @entityStore.entity_count
39
- end
38
+ def entity_count
39
+ return @entityStore.entity_count
40
+ end
40
41
 
41
- def has_component(entityId, componentType)
42
- entity = @entityStore.get(entityId)
43
- archetype = @archStore.get(entity.archId)
44
- return archetype.has_component(componentType.object_id)
45
- end
42
+ def has_component(entityId, componentType)
43
+ entity = @entityStore.get(entityId)
44
+ archetype = @archStore.get(entity.archId)
45
+ return archetype.has_component(componentType.object_id)
46
+ end
46
47
 
47
- def has_flag(entityId, flagId)
48
- return @entityStore.has_flag entityId, flagId
49
- end
48
+ def has_flag(entityId, flagId)
49
+ return @entityStore.has_flag entityId, flagId
50
+ end
50
51
 
51
- def has_flags(entityId, *flagIds)
52
- return flagIds.filter { |flagId| !@entityStore.has_flag entityId, flagId }.count == 0
53
- end
52
+ def has_flags(entityId, *flagIds)
53
+ return flagIds.filter { |flagId| !@entityStore.has_flag entityId, flagId }.count == 0
54
+ end
54
55
 
55
- def set_flag(entityId, flagId)
56
- @entityStore.set_flag(entityId, flagId)
57
- end
56
+ def set_flag(entityId, flagId)
57
+ @entityStore.set_flag(entityId, flagId)
58
+ end
58
59
 
59
- def remove_flag(entityId, flagId)
60
- @entityStore.remove_flag(entityId, flagId)
61
- end
60
+ def remove_flag(entityId, flagId)
61
+ @entityStore.remove_flag(entityId, flagId)
62
+ end
62
63
 
63
- include Query
64
+ include Kiwi::Internal::Query
65
+ end
64
66
  end
metadata CHANGED
@@ -1,158 +1,25 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kiwi-ecs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonas Everaert
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
  date: 2023-08-11 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: |
14
- # Kiwi
15
-
16
- Kiwi is a versatile entity component system focussing on fast iteration and a nice api.
17
-
18
- To get started, read the [usage guide](#usage) below.
19
-
20
- [![Tests](https://github.com/Jomy10/kiwi-ecs-ruby/actions/workflows/tests.yml/badge.svg)](https://github.com/Jomy10/kiwi-ecs-ruby/actions/workflows/tests.yml)
21
-
22
- ## Installation
23
-
24
- This library is currently not on ruby gems, but will arrive shortly.
25
-
26
- To use it now, simple `git clone https://github.com/jomy10/kiwi-ecs-ruby`.
27
-
28
- Then incude the world.rb file in your ruby files like so:
29
-
30
- ```ruby
31
- require_relative 'kiwi-ecs-ruby/src/world.rb'
32
- ```
33
-
34
- ## Usage
35
-
36
- ### The world
37
-
38
- The world is the main object that controls the ecs.
39
-
40
- ```ruby
41
- world = World.new
42
- ```
43
-
44
- ### Components
45
-
46
- Creating a component is as simple as declaring a struct:
47
-
48
- ```ruby
49
- Position = Struct.new :x, :y
50
- ```
51
-
52
- Classes can also be used instead of structs
53
-
54
- ```ruby
55
- class Velocity
56
- attr_accessor :x
57
- attr_accessor :y
58
- end
59
- ```
60
-
61
- ### Entities
62
-
63
- An entity is spawned with a set of components:
64
-
65
- ```ruby
66
- entityId = world.spawn(Position.new(10, 10))
67
-
68
- world.spawn(Position.new(3, 5), Velocity.new(1.5, 0.0))
69
- ```
70
-
71
- The `world.spawn(*components)` function will return the id of the spawned entity.
72
-
73
- Killing an entity can be done using `world.kill(entityId)`:
74
-
75
- ```ruby
76
- world.kill(entityId)
77
- ```
78
-
79
- ### Systems
80
-
81
- #### Queries
82
-
83
- Queries can be constructed as follows:
84
-
85
- ```ruby
86
- # Query all position componentss
87
- world.query(Position) do |pos|
88
- puts pos
89
- end
90
-
91
- # Query all entities having a position and a velocity component, and their entity ids
92
- world.query_with_ids(Position, Velocity) do |id, pos, vel|
93
- # ...
94
- end
95
- ```
96
-
97
- ### Flags
98
-
99
- Entities can be tagged using flags
100
-
101
- #### Defining flags
102
-
103
- A flag is an integer
104
-
105
- ```ruby
106
- module Flags
107
- Player = 0
108
- Enemy = 1
109
- end
110
- ```
111
-
112
- #### Setting flags
113
-
114
- ```ruby
115
- id = world.spawn
116
-
117
- world.set_flag(id, Flags::Player)
118
- ```
119
-
120
- #### Removing a flag
121
-
122
- ```ruby
123
- world.remove_flag(id, Flags::Player)
124
- ```
125
-
126
- #### Checking wether an entity has a flag
127
-
128
- ```ruby
129
- world.has_flag(id, Flags::Player)
130
- ```
131
-
132
- #### Filtering queries with flags
133
-
134
- ```ruby
135
- # TODO
136
- ```
137
-
138
- The `hasFlags` function is also available for when you want to check multiple flags.
139
-
140
- ## Road map
141
-
142
- - [ ] System groups
143
-
144
- ## Contributing
145
-
146
- Contributors are welcome to open an issue requesting new features or fixes or opening a pull request for them.
147
-
148
- ## License
149
-
150
- The library is licensed under LGPLv3.
151
- email:
13
+ description: |-
14
+ == Description
15
+ Kiwi is a versatile entity component system that is focussed on fast iteration and a nice api
16
+ email:
152
17
  executables: []
153
18
  extensions: []
154
- extra_rdoc_files: []
19
+ extra_rdoc_files:
20
+ - README.md
155
21
  files:
22
+ - README.md
156
23
  - lib/arch_store.rb
157
24
  - lib/archetype.rb
158
25
  - lib/bitmap.rb
@@ -164,7 +31,7 @@ homepage: https://github.com/jomy10/kiwi-ecs-ruby
164
31
  licenses:
165
32
  - LGPL-3.0-or-later
166
33
  metadata: {}
167
- post_install_message:
34
+ post_install_message:
168
35
  rdoc_options: []
169
36
  require_paths:
170
37
  - lib
@@ -179,8 +46,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
179
46
  - !ruby/object:Gem::Version
180
47
  version: '0'
181
48
  requirements: []
182
- rubygems_version: 3.3.3
183
- signing_key:
49
+ rubygems_version: 3.3.26
50
+ signing_key:
184
51
  specification_version: 4
185
52
  summary: An entity component system with a nice api, fit for a variety of use cases
186
53
  test_files: []