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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 9b24299f45b2755cca922ee6762900f1afb4b2b7
4
- data.tar.gz: e4bb1a2a39c594b2ecee9e898b358f138c9d6ce7
2
+ SHA256:
3
+ metadata.gz: ef14891907c37d8047d88177ab303208f073f8e0e33e940cbf56989a1e45e3ac
4
+ data.tar.gz: 35eaace97f89719cd01ba69fa437baed47bdfc8bcb84f918ba4c7e0ce08c512e
5
5
  SHA512:
6
- metadata.gz: fde13065c29d54acf5e355456f146740ed8a6f4a02084dff417944fae714e9395f566b2b717eef18ea398e4a7e9940f8f57871e1d9eb140ce60aa99bdaf45856
7
- data.tar.gz: 19d74ac66382bd50991a149ff5082346ba6eb67cbf0a629852051f19361bde42e3b7ec1e2b3279f128dbca377e94e8057df88b8eca349bed45480f0cb5caea4f
6
+ metadata.gz: a2d8877f54851147ce6760c041e302fce3e1e1a55b6d64eaa0122c173b13b61b188d47d3bac630438bac81d25bf5b32b26d9b206ee6129b4513e459564183309
7
+ data.tar.gz: b085ac2e31c52eeeaee5f9776a1049ba6172c1d05927ea72b8229f8476c080a93cc732e9ab17c12cabc940630a056908c5a48277cb89785e44bf816b31245867
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] [tip]
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] [github/master]
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:
@@ -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
- * https://github.com/libgdx/ashley (Java)
53
- * http://www.ashframework.org/ (ActionScript)
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
- {project page}[http://bitbucket.org/ged/chione]. Or if you prefer Git, via
60
- {its Github mirror}[https://github.com/ged/chione].
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
@@ -12,7 +12,7 @@ module Chione
12
12
  extend Loggability
13
13
 
14
14
  # Gem version
15
- VERSION = '0.3.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
@@ -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.create_entity
80
+ entity = world.create_blank_entity
61
81
  self.components.each do |component_type, args|
62
82
  component = component_type.new( *args )
63
- entity.add_component( component )
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
 
@@ -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 [ self.one_of, self.all_of, self.none_of ].all?( &:empty? )
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 a human-readable String representation of the Aspect.
103
- def inspect
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 = "#<%p:%#0x matching entities" % [ self.class, self.object_id * 2 ]
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
@@ -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
- def self::field( name, default: nil )
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
- attr_accessor( name )
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
- ### Return a human-readable representation of the object suitable for debugging.
48
- def inspect
49
- fields_desc = self.fields_description
50
- return "#<%p:%#x %s>" % [ self.class, self.object_id * 2, fields_desc ]
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
  #######