kiwi-ecs 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: []