chione 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/ChangeLog +16 -2
- data/History.md +31 -0
- data/Manifest.txt +4 -0
- data/README.md +18 -11
- data/Rakefile +2 -0
- data/lib/chione.rb +7 -4
- data/lib/chione/archetype.rb +49 -3
- data/lib/chione/aspect.rb +52 -10
- data/lib/chione/component.rb +43 -8
- data/lib/chione/entity.rb +38 -28
- data/lib/chione/fixtures.rb +18 -0
- data/lib/chione/fixtures/entities.rb +32 -0
- data/lib/chione/iterating_system.rb +35 -0
- data/lib/chione/manager.rb +15 -0
- data/lib/chione/mixins.rb +22 -0
- data/lib/chione/system.rb +137 -12
- data/lib/chione/world.rb +155 -38
- data/spec/chione/archetype_spec.rb +14 -0
- data/spec/chione/aspect_spec.rb +90 -0
- data/spec/chione/component_spec.rb +37 -0
- data/spec/chione/entity_spec.rb +17 -24
- data/spec/chione/iterating_system_spec.rb +135 -0
- data/spec/chione/system_spec.rb +224 -27
- data/spec/chione/world_spec.rb +122 -59
- data/spec/spec_helper.rb +3 -0
- metadata +46 -14
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ef14891907c37d8047d88177ab303208f073f8e0e33e940cbf56989a1e45e3ac
|
4
|
+
data.tar.gz: 35eaace97f89719cd01ba69fa437baed47bdfc8bcb84f918ba4c7e0ce08c512e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a2d8877f54851147ce6760c041e302fce3e1e1a55b6d64eaa0122c173b13b61b188d47d3bac630438bac81d25bf5b32b26d9b206ee6129b4513e459564183309
|
7
|
+
data.tar.gz: b085ac2e31c52eeeaee5f9776a1049ba6172c1d05927ea72b8229f8476c080a93cc732e9ab17c12cabc940630a056908c5a48277cb89785e44bf816b31245867
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/ChangeLog
CHANGED
@@ -1,8 +1,22 @@
|
|
1
|
+
2017-06-06 Michael Granger <ged@FaerieMUD.org>
|
2
|
+
|
3
|
+
* lib/chione/aspect.rb, lib/chione/component.rb, lib/chione/entity.rb,
|
4
|
+
lib/chione/manager.rb, lib/chione/mixins.rb, lib/chione/system.rb:
|
5
|
+
Pull up common #inspect functionality into a mixin
|
6
|
+
|
7
|
+
...and use it everywhere.
|
8
|
+
[0eb1e6c25953] [tip]
|
9
|
+
|
10
|
+
* lib/chione/world.rb, spec/chione/world_spec.rb:
|
11
|
+
Added World#remove_system and _manager; publish the instance of
|
12
|
+
/added and /removed events
|
13
|
+
[426735589cee]
|
14
|
+
|
1
15
|
2017-05-31 Michael Granger <ged@FaerieMUD.org>
|
2
16
|
|
3
17
|
* .hgtags:
|
4
18
|
Added tag v0.3.0 for changeset c91f71b3d7d9
|
5
|
-
[06fdcde9eb00] [
|
19
|
+
[06fdcde9eb00] [github/master]
|
6
20
|
|
7
21
|
* .hgsigs:
|
8
22
|
Added signature for changeset 0d453cae95c3
|
@@ -19,7 +33,7 @@
|
|
19
33
|
* lib/chione.rb, lib/chione/archetype.rb, lib/chione/assemblage.rb,
|
20
34
|
spec/chione/archetype_spec.rb:
|
21
35
|
Add more backward-compat for Chione::Assemblage
|
22
|
-
[a2e8b35fb950]
|
36
|
+
[a2e8b35fb950]
|
23
37
|
|
24
38
|
* .gems, Manifest.txt, Rakefile, chione.gemspec, lib/chione.rb,
|
25
39
|
lib/chione/archetype.rb, lib/chione/assemblage.rb,
|
data/History.md
CHANGED
@@ -1,3 +1,34 @@
|
|
1
|
+
## v0.4.0 [2017-12-11] Michael Granger <ged@FaerieMUD.org>
|
2
|
+
|
3
|
+
Enhancements:
|
4
|
+
|
5
|
+
- Add caching and #inserted/#removed callbacks for aspect-membership to Systems.
|
6
|
+
- Add Aspect#archetype and Archetype.from_aspect
|
7
|
+
- Add Aspect#matches? to match individual entities
|
8
|
+
- Add fixtures collection
|
9
|
+
- Normalize entity IDs in the World API
|
10
|
+
- Add constructor arguments to component-creation paths
|
11
|
+
- Add the entity ID to Component's inspect output
|
12
|
+
- Add Chione::IteratingSystem
|
13
|
+
- Entities are thinner and systems make better use of named aspects
|
14
|
+
- Added World#remove_system and _manager; publish the instance of /added and /removed events
|
15
|
+
- Pull up common #inspect functionality into a mixin and use it everywhere.
|
16
|
+
|
17
|
+
Changes:
|
18
|
+
|
19
|
+
- The `every_tick` callback is now only passed the delta and the tick count
|
20
|
+
- Init arguments are passed through to Component.add_component
|
21
|
+
- Add a processing block to Component field declaration
|
22
|
+
- Rename some component-API methods on the World for clarity (with aliases to the old methods)
|
23
|
+
- Add the entity ID to components on registration
|
24
|
+
- Event handler declarations no longer include an aspect.
|
25
|
+
|
26
|
+
Bugfixes:
|
27
|
+
|
28
|
+
- Fix API docs for Chione::System::on
|
29
|
+
|
30
|
+
|
31
|
+
|
1
32
|
## v0.3.0 [2017-05-31] Michael Granger <ged@FaerieMUD.org>
|
2
33
|
|
3
34
|
Changes:
|
data/Manifest.txt
CHANGED
@@ -12,6 +12,9 @@ lib/chione/assemblage.rb
|
|
12
12
|
lib/chione/behaviors.rb
|
13
13
|
lib/chione/component.rb
|
14
14
|
lib/chione/entity.rb
|
15
|
+
lib/chione/fixtures.rb
|
16
|
+
lib/chione/fixtures/entities.rb
|
17
|
+
lib/chione/iterating_system.rb
|
15
18
|
lib/chione/manager.rb
|
16
19
|
lib/chione/mixins.rb
|
17
20
|
lib/chione/system.rb
|
@@ -20,6 +23,7 @@ spec/chione/archetype_spec.rb
|
|
20
23
|
spec/chione/aspect_spec.rb
|
21
24
|
spec/chione/component_spec.rb
|
22
25
|
spec/chione/entity_spec.rb
|
26
|
+
spec/chione/iterating_system_spec.rb
|
23
27
|
spec/chione/manager_spec.rb
|
24
28
|
spec/chione/mixins_spec.rb
|
25
29
|
spec/chione/system_spec.rb
|
data/README.md
CHANGED
@@ -40,24 +40,28 @@ for making it better via email or whatever.
|
|
40
40
|
|
41
41
|
Articles/posts on ECS:
|
42
42
|
|
43
|
-
* http://gameprogrammingpatterns.com/component.html
|
44
|
-
* http://t-machine.org/index.php/2007/09/03/entity-systems-are-the-future-of-mmog-development-part-1
|
45
|
-
* http://www.richardlord.net/blog/what-is-an-entity-framework
|
46
|
-
* http://www.richardlord.net/blog/why-use-an-entity-framework
|
47
|
-
* http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy
|
43
|
+
* <http://gameprogrammingpatterns.com/component.html>
|
44
|
+
* <http://t-machine.org/index.php/2007/09/03/entity-systems-are-the-future-of-mmog-development-part-1/>
|
45
|
+
* <http://www.richardlord.net/blog/what-is-an-entity-framework>
|
46
|
+
* <http://www.richardlord.net/blog/why-use-an-entity-framework>
|
47
|
+
* <http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/>
|
48
48
|
|
49
49
|
Other ECS Frameworks:
|
50
50
|
|
51
|
-
* https://github.com/junkdog/artemis-odb (Java)
|
52
|
-
*
|
53
|
-
*
|
54
|
-
|
51
|
+
* <https://github.com/junkdog/artemis-odb> (Java)
|
52
|
+
* <http://www.richardlord.net/ash/> (ActionScript)
|
53
|
+
* <https://github.com/libgdx/ashley> (Java)
|
54
|
+
* <https://github.com/astrosilverio/braga> (Python)
|
55
|
+
* <https://github.com/seanfisk/ecs> (Python)
|
56
|
+
* <https://github.com/tdavies/Ember2> (ActionScript)
|
57
|
+
* <https://github.com/cpowell/ruby-entity-component-framework> (JRuby)
|
58
|
+
* <https://github.com/alecmce/xember> (ActionScript)
|
55
59
|
|
56
60
|
## Contributing
|
57
61
|
|
58
62
|
You can check out the current development source with Mercurial via its
|
59
|
-
|
60
|
-
|
63
|
+
[project page][bitbucket]. Or if you prefer Git, via
|
64
|
+
[its Github mirror][github].
|
61
65
|
|
62
66
|
After checking out the source, run:
|
63
67
|
|
@@ -98,3 +102,6 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
98
102
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
99
103
|
|
100
104
|
|
105
|
+
[bitbucket]: http://bitbucket.org/ged/chione
|
106
|
+
[github]: https://github.com/ged/chione
|
107
|
+
|
data/Rakefile
CHANGED
@@ -36,6 +36,8 @@ hoespec = Hoe.spec 'chione' do |spec|
|
|
36
36
|
spec.dependency 'pluggability', '~> 0.4'
|
37
37
|
spec.dependency 'uuid', '~> 2.3'
|
38
38
|
spec.dependency 'deprecatable', '~> 1.0'
|
39
|
+
spec.dependency 'fluent_fixtures', '~> 0.6'
|
40
|
+
spec.dependency 'faker', '~> 1.8'
|
39
41
|
|
40
42
|
spec.dependency 'hoe-deveiate', '~> 1.0', :developer
|
41
43
|
spec.dependency 'simplecov', '~> 0.12', :developer
|
data/lib/chione.rb
CHANGED
@@ -12,7 +12,7 @@ module Chione
|
|
12
12
|
extend Loggability
|
13
13
|
|
14
14
|
# Gem version
|
15
|
-
VERSION = '0.
|
15
|
+
VERSION = '0.4.0'
|
16
16
|
|
17
17
|
|
18
18
|
# Loggability API -- set up a log host
|
@@ -26,9 +26,12 @@ module Chione
|
|
26
26
|
autoload :Component, 'chione/component'
|
27
27
|
autoload :Entity, 'chione/entity'
|
28
28
|
autoload :Manager, 'chione/manager'
|
29
|
-
autoload :System, 'chione/system'
|
30
29
|
autoload :World, 'chione/world'
|
31
30
|
|
31
|
+
autoload :System, 'chione/system'
|
32
|
+
autoload :IteratingSystem, 'chione/iterating_system'
|
33
|
+
|
34
|
+
|
32
35
|
##
|
33
36
|
# The global UUID object for generating new UUIDs
|
34
37
|
class << self; attr_reader :uuid ; end
|
@@ -36,9 +39,9 @@ module Chione
|
|
36
39
|
|
37
40
|
|
38
41
|
### Coerce the specified +object+ into a Chione::Component and return it.
|
39
|
-
def self::Component( object )
|
42
|
+
def self::Component( object, init_values={} )
|
40
43
|
return object if object.is_a?( Chione::Component )
|
41
|
-
return Chione::Component.create( object ) if
|
44
|
+
return Chione::Component.create( object, init_values ) if
|
42
45
|
object.is_a?( Class ) || object.is_a?( String ) || object.is_a?( Symbol )
|
43
46
|
raise TypeError, "can't convert %p into Chione::Component" % [ object.class ]
|
44
47
|
end
|
data/lib/chione/archetype.rb
CHANGED
@@ -5,6 +5,7 @@ require 'pluggability'
|
|
5
5
|
require 'loggability'
|
6
6
|
|
7
7
|
require 'chione' unless defined?( Chione )
|
8
|
+
require 'chione/mixins'
|
8
9
|
|
9
10
|
|
10
11
|
# An Archetype mixin for defining factories for common entity configurations.
|
@@ -21,10 +22,29 @@ module Chione::Archetype
|
|
21
22
|
|
22
23
|
### Extension callback -- add archetype functionality to an extended +object+.
|
23
24
|
def self::extended( object )
|
24
|
-
super
|
25
25
|
object.extend( Loggability )
|
26
|
+
# object.extend( Chione::Inspection )
|
27
|
+
object.extend( Chione::MethodUtilities )
|
28
|
+
|
29
|
+
super
|
30
|
+
|
26
31
|
object.log_to( :chione )
|
27
32
|
object.components ||= {}
|
33
|
+
object.singleton_attr_accessor :from_aspect
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
### Create an anonymous Archetype Module that will create entities which match
|
38
|
+
### the specified +aspect+ (Chione::Aspect).
|
39
|
+
def self::from_aspect( aspect )
|
40
|
+
mod = Module.new
|
41
|
+
mod.extend( self )
|
42
|
+
mod.from_aspect = aspect
|
43
|
+
|
44
|
+
aspect.all_of.each( &mod.method(:add) )
|
45
|
+
mod.add( aspect.one_of.first ) unless aspect.one_of.empty?
|
46
|
+
|
47
|
+
return mod
|
28
48
|
end
|
29
49
|
|
30
50
|
|
@@ -57,15 +77,41 @@ module Chione::Archetype
|
|
57
77
|
### Construct a new entity for the specified +world+ with all of the archetype's
|
58
78
|
### components.
|
59
79
|
def construct_for( world )
|
60
|
-
entity = world.
|
80
|
+
entity = world.create_blank_entity
|
61
81
|
self.components.each do |component_type, args|
|
62
82
|
component = component_type.new( *args )
|
63
|
-
|
83
|
+
world.add_component_to( entity, component )
|
64
84
|
end
|
65
85
|
|
66
86
|
return entity
|
67
87
|
end
|
68
88
|
|
89
|
+
|
90
|
+
### Return a human-readable representation of the object suitable for debugging.
|
91
|
+
def inspect
|
92
|
+
return "#<%p:%#016x %s>" % [
|
93
|
+
self.class,
|
94
|
+
self.object_id * 2,
|
95
|
+
self.inspect_details,
|
96
|
+
]
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
#########
|
101
|
+
protected
|
102
|
+
#########
|
103
|
+
|
104
|
+
### Provide details about the Archetype for #inspect output.
|
105
|
+
def inspect_details
|
106
|
+
if self.from_aspect
|
107
|
+
return "Chione::Archetype from %p" % [ self.from_aspect ]
|
108
|
+
else
|
109
|
+
return "Chione::Archetype for creating entities with %s" %
|
110
|
+
[ self.components.keys.map( &:name ).join(', ') ]
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
|
69
115
|
end # module Chione::Archetype
|
70
116
|
|
71
117
|
|
data/lib/chione/aspect.rb
CHANGED
@@ -5,13 +5,15 @@ require 'set'
|
|
5
5
|
require 'loggability'
|
6
6
|
|
7
7
|
require 'chione' unless defined?( Chione )
|
8
|
+
require 'chione/mixins'
|
9
|
+
require 'chione/archetype'
|
8
10
|
|
9
11
|
|
10
12
|
# An expression of component-matching criteria used to find entities that should be
|
11
13
|
# processed by a System.
|
12
14
|
class Chione::Aspect
|
13
15
|
extend Loggability
|
14
|
-
|
16
|
+
include Chione::Inspection
|
15
17
|
|
16
18
|
# Loggability API -- log to the chione logger
|
17
19
|
log_to :chione
|
@@ -95,34 +97,74 @@ class Chione::Aspect
|
|
95
97
|
|
96
98
|
### Returns true if the receiver is an empty aspect, i.e., matches all entities.
|
97
99
|
def empty?
|
98
|
-
return
|
100
|
+
return self.one_of.empty? && self.all_of.empty? && self.none_of.empty?
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
### Returns +true+ if the components contained in the specified +component_hash+
|
105
|
+
### match the Aspect's specifications.
|
106
|
+
def matches?( component_hash )
|
107
|
+
return true if self.empty?
|
108
|
+
|
109
|
+
component_hash = component_hash.components if component_hash.respond_to?( :components )
|
110
|
+
|
111
|
+
return false unless self.one_of.empty? ||
|
112
|
+
self.one_of.any? {|component| component_hash.key?(component) }
|
113
|
+
return false unless self.none_of.none? {|component| component_hash.key?(component) }
|
114
|
+
return false unless self.all_of.all? {|component| component_hash.key?(component) }
|
115
|
+
|
116
|
+
return true
|
117
|
+
end
|
118
|
+
alias_method :match, :matches?
|
119
|
+
|
120
|
+
|
121
|
+
### Given an +entity_hash+ keyed by Component class, return the subset of
|
122
|
+
### values matching the receiving Aspect.
|
123
|
+
def matching_entities( entity_hash )
|
124
|
+
initial_set = if self.one_of.empty?
|
125
|
+
entity_hash.values
|
126
|
+
else
|
127
|
+
entity_hash.values_at( *self.one_of )
|
128
|
+
end
|
129
|
+
|
130
|
+
with_one = initial_set.reduce( :| ) || Set.new
|
131
|
+
with_all = entity_hash.values_at( *self.all_of ).reduce( with_one, :& )
|
132
|
+
without_any = entity_hash.values_at( *self.none_of ).reduce( with_all, :- )
|
133
|
+
|
134
|
+
return without_any
|
99
135
|
end
|
100
136
|
|
101
137
|
|
102
|
-
### Return
|
103
|
-
|
138
|
+
### Return an (anonymous) Chione::Archetype module that can be used to create
|
139
|
+
### entities that match it.
|
140
|
+
def archetype
|
141
|
+
return Chione::Archetype.from_aspect( self )
|
142
|
+
end
|
143
|
+
|
144
|
+
|
145
|
+
#########
|
146
|
+
protected
|
147
|
+
#########
|
148
|
+
|
149
|
+
### Return the detail part of the #inspect output.
|
150
|
+
def inspect_details
|
104
151
|
parts = []
|
105
152
|
parts << self.one_of_description
|
106
153
|
parts << self.all_of_description
|
107
154
|
parts << self.none_of_description
|
108
155
|
parts.compact!
|
109
156
|
|
110
|
-
str = "
|
157
|
+
str = "matching entities"
|
111
158
|
if parts.empty?
|
112
159
|
str << " with any components"
|
113
160
|
else
|
114
161
|
str << parts.join( ', ' )
|
115
162
|
end
|
116
|
-
str << ">"
|
117
163
|
|
118
164
|
return str
|
119
165
|
end
|
120
166
|
|
121
167
|
|
122
|
-
#########
|
123
|
-
protected
|
124
|
-
#########
|
125
|
-
|
126
168
|
### Return a String describing the components matching entities must have at
|
127
169
|
### least one of.
|
128
170
|
def one_of_description
|
data/lib/chione/component.rb
CHANGED
@@ -14,6 +14,9 @@ class Chione::Component
|
|
14
14
|
Pluggability,
|
15
15
|
Chione::MethodUtilities
|
16
16
|
|
17
|
+
include Chione::Inspection
|
18
|
+
|
19
|
+
|
17
20
|
# Loggability API -- log to the 'chione' logger
|
18
21
|
log_to :chione
|
19
22
|
|
@@ -26,16 +29,32 @@ class Chione::Component
|
|
26
29
|
|
27
30
|
|
28
31
|
### Declare a field for the component named +name+, with a default value of
|
29
|
-
### +default+.
|
30
|
-
|
32
|
+
### +default+. If the optional +process_block+ is provided, it will be called
|
33
|
+
### with the new value being assigned to the field before it is set, and the
|
34
|
+
### return value of it will be used instead.
|
35
|
+
def self::field( name, default: nil, &process_block )
|
31
36
|
self.fields ||= {}
|
32
37
|
self.fields[ name ] = default
|
33
|
-
|
38
|
+
|
39
|
+
define_method( "process_#{name}", &process_block ) if process_block
|
40
|
+
define_method( "#{name}=" ) do |new_val|
|
41
|
+
new_val = self.send( "process_#{name}", new_val ) if self.respond_to?( "process_#{name}" )
|
42
|
+
self.instance_variable_set( "@#{name}", new_val )
|
43
|
+
end
|
44
|
+
|
45
|
+
attr_reader( name )
|
34
46
|
end
|
35
47
|
|
36
48
|
|
37
49
|
### Create a new component with the specified +values+.
|
38
|
-
def initialize( values={} )
|
50
|
+
def initialize( entity_id=nil, values={} )
|
51
|
+
if entity_id.is_a?( Hash )
|
52
|
+
values = entity_id
|
53
|
+
entity_id = nil
|
54
|
+
end
|
55
|
+
|
56
|
+
@entity_id = entity_id
|
57
|
+
|
39
58
|
if self.class.fields
|
40
59
|
self.class.fields.each do |name, default|
|
41
60
|
self.method( "#{name}=" ).call( values[name] || default_value(default) )
|
@@ -44,10 +63,25 @@ class Chione::Component
|
|
44
63
|
end
|
45
64
|
|
46
65
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
66
|
+
######
|
67
|
+
public
|
68
|
+
######
|
69
|
+
|
70
|
+
##
|
71
|
+
# The ID of the entity the component belongs to
|
72
|
+
attr_accessor :entity_id
|
73
|
+
|
74
|
+
|
75
|
+
#########
|
76
|
+
protected
|
77
|
+
#########
|
78
|
+
|
79
|
+
### Return the detailed part of the Component's #inspect output.
|
80
|
+
def inspect_details
|
81
|
+
return "{%s} %s" % [
|
82
|
+
self.entity_id || "(unassigned)",
|
83
|
+
self.fields_description
|
84
|
+
]
|
51
85
|
end
|
52
86
|
|
53
87
|
|
@@ -63,6 +97,7 @@ class Chione::Component
|
|
63
97
|
end
|
64
98
|
|
65
99
|
|
100
|
+
|
66
101
|
#######
|
67
102
|
private
|
68
103
|
#######
|