kiwi-ecs 0.0.3 → 0.1.1

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: 2ecb91b181779636d95d7c72fb3e8bcb6713498253b03ea8dc033a9e99027f59
4
- data.tar.gz: 1e06daecfa95b5ecd6f3a6faca0a3b4385dd501ceed81ab9b6816ba62cc327df
3
+ metadata.gz: 6c92559b41133eb2dc4efeb25ae91bce5ddc356eed0b4164cbc284b5c8ca4eac
4
+ data.tar.gz: b213c479a15483424f08617bf5fb7c5b0895c8866804f4adaa0912068e6d1819
5
5
  SHA512:
6
- metadata.gz: 05a2f1676d8883b1e0bdbecd4138e5c424482bedd23a945a815444c86eae88c692b769ebe8cbbfc00910b47ba4219bed79bce5e6c4f678c71de784a5e4078869
7
- data.tar.gz: '08a375f932ad364d8194bd97cfd71578eaad9631e8e989c76bfb9dbd33cdacc83c93ba6afd740ee2dc3c80e79fb7576c2c213d912fffee0285ddf155fa85c54f'
6
+ metadata.gz: 23611a5577855aa6f67245e195942009d08535c82d4bfb5d737bc3d8c9ff9914a09cdc66c5ff920e90cbdc02038b221d8fabdc5111fd20c60bb1e94a4a185d86
7
+ data.tar.gz: 2adf271c5166619053826369b1458abd4b44d679f02f394f1e6da6cfef86dcb82db67f03d841e7747bd55942fd26b4e64aefa07b7f9f5de2ab30ea030f062aff
data/README.md CHANGED
@@ -27,7 +27,7 @@ require 'kiwi-ecs'
27
27
  The world is the main object that controls the ecs.
28
28
 
29
29
  ```ruby
30
- world = World.new
30
+ world = Kiwi::World.new
31
31
  ```
32
32
 
33
33
  ### Components
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
- ComponentColumn = Struct.new(:components)
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
1
+ module Kiwi
2
+ module Internal
3
+ ComponentColumn = Struct.new(:components)
4
+
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/kiwi-ecs.rb CHANGED
@@ -5,14 +5,14 @@
5
5
  # Copyright (C) 2023 Jonas Everaert
6
6
  #
7
7
  # This program is free software: you can redistribute it and/or modify
8
- # it under the terms of the GNU General Public License as published by
8
+ # it under the terms of the GNU Lesser General Public License as published by
9
9
  # the Free Software Foundation, either version 3 of the License, or
10
10
  # (at your option) any later version.
11
11
  #
12
12
  # This program is distributed in the hope that it will be useful,
13
13
  # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
14
  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- # GNU General Public License for more details.
15
+ # GNU Lesser General Public License for more details.
16
16
  #
17
17
  # You should have received a copy of the GNU General Public License
18
18
  # along with this program. If not, see <https://www.gnu.org/licenses/>.
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
@@ -23,6 +25,12 @@ module Query
23
25
  .active_components(componentIds)
24
26
  end
25
27
 
28
+ if componentType.size == 1
29
+ result = result.map do |c|
30
+ c[0]
31
+ end
32
+ end
33
+
26
34
  if block_given?
27
35
  result.each do |a|
28
36
  yield a
@@ -54,3 +62,5 @@ module Query
54
62
  end
55
63
  end
56
64
  end
65
+ end
66
+ 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,17 +1,19 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kiwi-ecs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonas Everaert
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-08-11 00:00:00.000000000 Z
11
+ date: 2023-08-13 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: Kiwi is a versatile entity component system that is focussed on fast
14
- iteration and a nice api
13
+ description: |-
14
+ == Description
15
+
16
+ ["Kiwi is a versatile entity component system focussing on fast iteration and a nice api.\n", "\n", "To get started, read the [usage guide](#usage) below.\n", "\n", "[![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)\n", "\n", "## Installation\n", "\n", "The library is available from [ruby gems](https://rubygems.org/gems/kiwi-ecs):\n", "\n", "```sh\n", "gem install kiwi-ecs\n", "```\n", "\n", "To use it in your ruby source files:\n", "\n", "```ruby\n", "require 'kiwi-ecs'\n", "```\n", "\n", "## Usage\n", "\n", "### The world\n", "\n", "The world is the main object that controls the ecs.\n", "\n", "```ruby\n", "world = Kiwi::World.new\n", "```\n", "\n", "### Components\n", "\n", "Creating a component is as simple as declaring a struct:\n", "\n", "```ruby\n", "Position = Struct.new :x, :y\n", "```\n", "\n", "Classes can also be used instead of structs\n", "\n", "```ruby\n", "class Velocity\n", " attr_accessor :x\n", " attr_accessor :y\n", "end\n", "```\n", "\n", "### Entities\n", "\n", "An entity is spawned with a set of components:\n", "\n", "```ruby\n", "entityId = world.spawn(Position.new(10, 10))\n", "\n", "world.spawn(Position.new(3, 5), Velocity.new(1.5, 0.0))\n", "```\n", "\n", "The `world.spawn(*components)` function will return the id of the spawned entity.\n", "\n", "Killing an entity can be done using `world.kill(entityId)`:\n", "\n", "```ruby\n", "world.kill(entityId)\n", "```\n", "\n", "### Systems\n", "\n", "#### Queries\n", "\n", "Queries can be constructed as follows:\n", "\n", "```ruby\n", "# Query all position componentss\n", "world.query(Position) do |pos|\n", " puts pos\n", "end\n", "\n", "# Query all entities having a position and a velocity component, and their entity ids\n", "world.query_with_ids(Position, Velocity) do |id, pos, vel|\n", " # ...\n", "end\n", "```\n", "\n", "### Flags\n", "\n", "Entities can be tagged using flags\n", "\n", "#### Defining flags\n", "\n", "A flag is an integer\n", "\n", "```ruby\n", "module Flags\n", " Player = 0\n", " Enemy = 1\n", "end\n", "```\n", "\n", "#### Setting flags\n", "\n", "```ruby\n", "id = world.spawn\n", "\n", "world.set_flag(id, Flags::Player)\n", "```\n", "\n", "#### Removing a flag\n", "\n", "```ruby\n", "world.remove_flag(id, Flags::Player)\n", "```\n", "\n", "#### Checking wether an entity has a flag\n", "\n", "```ruby\n", "world.has_flag(id, Flags::Player)\n", "```\n", "\n", "#### Filtering queries with flags\n", "\n", "```ruby\n", "world.query_with_ids(Pos)\n", " .filter do |id, pos|\n", " world.has_flag(id, Flags::Player)\n", " end\n", " .each do |id, pos|\n", " # Do something with the filtered query\n", " end\n", "```\n", "\n", "The `hasFlags` function is also available for when you want to check multiple flags.\n", "\n", "## Road map\n", "\n", "- [ ] System groups\n", "\n", "## Contributing\n", "\n", "Contributors are welcome to open an issue requesting new features or fixes or opening a pull request for them.\n", "\n", "## License\n", "\n", "The library is licensed under LGPLv3.\n"]
15
17
  email:
16
18
  executables: []
17
19
  extensions: []