baku 0.2.3 → 0.3.1

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: e4e011013e5257d5b0af62562561e971cf0e449b
4
- data.tar.gz: 31931a5ea325fa8c8cb9e661e339935b83ac14fa
2
+ SHA256:
3
+ metadata.gz: f95ddbe20ed9e1c88da6a47399d9a6f4ebf0cb5e0ad591b8cceae36a2091c103
4
+ data.tar.gz: add1c691aa86d0b462c39353aa52ac6bd009b833f3314b4a5bb5f05148641a25
5
5
  SHA512:
6
- metadata.gz: b875ecf5c85daf770f8c91387848a93776aac8c5037112c9c9f5cd0832cb9948ebf7bfc321c035e4ce70848738d7622cecdc4607588ea3f45a92795c72f50f5f
7
- data.tar.gz: 9bf020e852d6e1929541f7ccc7650360cea9d833e0bac78711ed33b196f84edf2a97b588beb98418bce1d94ba0cd4debc531fe6f6623a624114c3c2a3bf0c804
6
+ metadata.gz: 59fd7f1018890d362342dfe25fdb5776301a1e6a6439eeac35a5136556fe95bdaac48e24a940a3c23a0505cf79a056c6be5c5031bc5cd4df7c104e55b4cd0fe5
7
+ data.tar.gz: ebcd87f863c3ab2b092c8a01b965134cd5676714b4f1a4238c9a1d44520a31b86b4d1751db8c0e268e3f51a3c31a4fa71bcbf090636a13cce6c5718f7c80b64f
data/.gitignore CHANGED
@@ -1,15 +1,52 @@
1
- /.bundle/
2
- /.yardoc
3
- /Gemfile.lock
4
- /_yardoc/
1
+ *.gem
2
+ *.rbc
3
+ /.config
5
4
  /coverage/
6
- /doc/
5
+ /InstalledFiles
7
6
  /pkg/
8
7
  /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
9
11
  /tmp/
10
12
 
11
- # rspec failure tracking
12
- .rspec_status
13
- .byebug_history
13
+ # Used by dotenv library to load environment variables.
14
+ # .env
15
+
16
+ ## Specific to RubyMotion:
17
+ .dat*
18
+ .repl_history
19
+ build/
20
+ *.bridgesupport
21
+ build-iPhoneOS/
22
+ build-iPhoneSimulator/
23
+
24
+ ## Specific to RubyMotion (use of CocoaPods):
25
+ #
26
+ # We recommend against adding the Pods directory to your .gitignore. However
27
+ # you should judge for yourself, the pros and cons are mentioned at:
28
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
29
+ #
30
+ # vendor/Pods/
31
+
32
+ ## Documentation cache and generated files:
33
+ /.yardoc/
34
+ /_yardoc/
35
+ /doc/
36
+ /rdoc/
37
+
38
+ ## Environment normalization:
39
+ /.bundle/
40
+ /vendor/bundle
41
+ /lib/bundler/man/
42
+
43
+ # for a library or gem, you might want to ignore these files since the code is
44
+ # intended to run in multiple environments; otherwise, check them in:
45
+ Gemfile.lock
14
46
  .ruby-version
15
- .ruby-gemset
47
+ .ruby-gemset
48
+
49
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
50
+ .rvmrc
51
+
52
+ .rspec_status
@@ -1,3 +1,23 @@
1
+ # 0.3.1
2
+
3
+ * Prevent system registration from overwriting existing entity list.
4
+
5
+ # 0.3.0
6
+
7
+ * Add tag system that processes entities by tag.
8
+
9
+ # 0.2.6
10
+
11
+ * Replace internal event listener with miru gem.
12
+
13
+ # 0.2.5
14
+
15
+ * Add has_component? to Entity.
16
+
17
+ # 0.2.4
18
+
19
+ * Add world disposal.
20
+
1
21
  # 0.2.3
2
22
 
3
23
  * Separate entity retrieval and processing logic in system to allow pre and post-processing.
data/README.md CHANGED
@@ -1,12 +1,10 @@
1
1
  # Baku
2
2
 
3
- Baku provides a simple Entity Component System framework for use with Ruby game
4
- engines. It has been tested with [Gosu](https://www.libgosu.org/ruby.html), but
5
- should be flexible enough to work with any Ruby project that has a game loop.
3
+ Baku provides a simple Entity Component System framework for use with Ruby game engines. It has been tested with [Gosu](https://www.libgosu.org/ruby.html), but should be flexible enough to work with any Ruby project that has a game loop.
6
4
 
7
- Baku is still very much a work in progress. There are undoubtedly bugs. I will
8
- be continually iterating and improving on it as I use it for my personal game
9
- development projects. Enjoy!
5
+ Baku is still very much a work in progress. There are undoubtedly bugs. I will be continually iterating and improving on it as I use it for my personal game development projects. Enjoy!
6
+
7
+ The [Baku wiki](https://github.com/jtuttle/baku/wiki) includes a [quick start guide](https://github.com/jtuttle/baku/wiki/quick-start-guide) if you're already familiar with the ECS approach. If not, there is also a descriptive [tutorial](https://github.com/jtuttle/baku/wiki/tutorial) that will cover ECS concepts while walking you through setting up Gosu with Baku.
10
8
 
11
9
  ## Installation
12
10
 
@@ -24,74 +22,6 @@ Or install it yourself as:
24
22
 
25
23
  $ gem install baku
26
24
 
27
- ## Usage
28
-
29
- Create components by overriding `Baku::Component` and calling `super()`. The
30
- example component below simple stores the x and y coordinates of an entity in
31
- a 2D space.
32
-
33
- ```
34
- class TransformComponent < Baku::Component
35
- attr_accessor :x, :y
36
-
37
- def initialize(x, y)
38
- super()
39
-
40
- @x = x
41
- @y = y
42
- end
43
- end
44
- ```
45
-
46
- Create systems by overriding `Baku::System` and calling `super()` to specify the
47
- components that an entity must possess in order for it to be processed by the
48
- system. The example system below will only operate on entities that possess both
49
- a `TransformComponent` and a `VelocityComponent`. You will also need to specify
50
- whether the system will be run during the `:update` or `:draw` loop.
51
-
52
- ```
53
- class MovementSystem < Baku::System
54
- def initialize
55
- super([TransformComponent, VelocityComponent], :update)
56
- end
57
-
58
- def process_entity(entity, transform, velocity)
59
- transform.x += velocity.x
60
- transform.y += velocity.y
61
- end
62
- end
63
- ```
64
-
65
- In your game initialization logic, create a `Baku::World` instance and register
66
- any systems you want to use. In the below example, we register our example
67
- system from above and create an entity that will be processed by the system:
68
-
69
- ```
70
- def game_initialization
71
- @world = Baku::World.new
72
- @world.add_system(MovementSystem.new)
73
-
74
- entity = @world.create_entity
75
- entity.add_component(TransformComponent)
76
- entity.add_component(VelocityComponent)
77
- end
78
- ```
79
-
80
- In your game `update` and `draw` loops, call the `Baku::World` instance's
81
- `update` and `draw` methods. You'll want to keep track of the millseconds
82
- between frames and pass that to the `update` method if you're planning to
83
- use the entity component system for anything that needs it.
84
-
85
- ```
86
- def game_update_loop
87
- @world.update(delta_ms)
88
- end
89
-
90
- def game_draw_loop
91
- @world.draw
92
- end
93
- ```
94
-
95
25
  ## Development
96
26
 
97
27
  After checking out the repo, run `bin/setup` to install dependencies. Then, run
@@ -1,28 +1,28 @@
1
- # coding: utf-8
2
- lib = File.expand_path("../lib", __FILE__)
1
+ lib = File.expand_path('../lib', __FILE__)
3
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require "baku/version"
3
+ require 'baku/version'
5
4
 
6
5
  Gem::Specification.new do |spec|
7
- spec.name = "baku"
6
+ spec.name = 'baku'
8
7
  spec.version = Baku::VERSION
9
- spec.authors = ["John Tuttle"]
10
- spec.email = ["jtuttle.develops@gmail.com"]
8
+ spec.authors = ['John Tuttle']
9
+ spec.email = ['jtuttle.develops@gmail.com']
11
10
 
12
- spec.summary = "An Entity Component System framework for Ruby"
13
- spec.description = "An Entity Component System framework for Ruby"
14
- spec.homepage = "https://github.com/jtuttle/baku"
15
- spec.license = "MIT"
11
+ spec.summary = 'An Entity Component System framework for Ruby'
12
+ spec.description = 'An Entity Component System framework for Ruby'
13
+ spec.homepage = 'https://github.com/jtuttle/baku'
14
+ spec.license = 'MIT'
16
15
 
16
+ # use double quotes for "\x0" (https://github.com/bundler/bundler/issues/4133)
17
17
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
18
  f.match(%r{^(test|spec|features)/})
19
19
  end
20
- spec.bindir = "exe"
21
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
- spec.require_paths = ["lib"]
20
+ spec.require_paths = ['lib']
23
21
 
24
- spec.add_development_dependency "bundler", "~> 1.15"
25
- spec.add_development_dependency "rake", "~> 10.0"
26
- spec.add_development_dependency "rspec", "~> 3.0"
27
- spec.add_development_dependency "pry-byebug", "~> 3.5.0"
22
+ spec.add_development_dependency 'bundler', '~> 2.1.4'
23
+ spec.add_development_dependency 'rake', '~> 13.0'
24
+ spec.add_development_dependency 'rspec', '~> 3.9'
25
+ spec.add_development_dependency 'pry-byebug', '~> 3.9.0'
26
+
27
+ spec.add_dependency 'miru', '~> 0.1.0'
28
28
  end
@@ -6,9 +6,10 @@ module Baku
6
6
  rescue LoadError
7
7
  # development dependencies
8
8
  end
9
-
9
+
10
10
  require 'set'
11
+
12
+ require 'miru'
11
13
 
12
- require_relative "baku/event_dispatcher.rb"
13
14
  Gem.find_files("baku/**/*.rb").each { |path| require path }
14
15
  end
@@ -0,0 +1,35 @@
1
+ require_relative 'system'
2
+
3
+ module Baku
4
+ class ComponentSystem < System
5
+ attr_reader :components
6
+
7
+ def initialize(components, game_loop_step)
8
+ @components = components
9
+ @game_loop_step = game_loop_step
10
+ end
11
+
12
+ def register_world(world)
13
+ super(world)
14
+
15
+ world.entity_manager.register_component_mask(component_mask)
16
+ end
17
+
18
+ def process_entities(entities)
19
+ entities.each do |entity|
20
+ entity_components = @components.map { |c| entity.get_component(c) }
21
+ process_entity(entity, *entity_components)
22
+ end
23
+ end
24
+
25
+ def component_mask
26
+ @component_mask ||= ComponentMask.from_components(@components)
27
+ end
28
+
29
+ protected
30
+
31
+ def retrieve_entities
32
+ @world.entity_manager.get_entities(component_mask)
33
+ end
34
+ end
35
+ end
@@ -1,6 +1,6 @@
1
1
  module Baku
2
2
  class Entity
3
- include Baku::EventDispatcher
3
+ include Miru::EventDispatcher
4
4
 
5
5
  attr_reader :components, :tags
6
6
 
@@ -28,11 +28,16 @@ module Baku
28
28
  new("Entity does not have component: #{component_class}")
29
29
  end
30
30
 
31
+ removed_component = @components[component_class]
31
32
  @components.delete(component_class)
32
33
 
33
34
  update_component_mask
34
35
 
35
- dispatch_event(:component_removed, self, @components[component_class])
36
+ dispatch_event(:component_removed, self, removed_component)
37
+ end
38
+
39
+ def has_component?(component_class)
40
+ @components.has_key?(component_class)
36
41
  end
37
42
 
38
43
  def get_component(component_class)
@@ -9,17 +9,26 @@ module Baku
9
9
  @entities_by_tag = {}
10
10
  end
11
11
 
12
+ def dispose
13
+ @entities_by_component_mask.clear
14
+ @entities_by_tag.clear
15
+ end
16
+
12
17
  def register_component_mask(component_mask)
13
- @entities_by_component_mask[component_mask] = []
18
+ @entities_by_component_mask[component_mask] ||= []
14
19
  end
15
20
 
16
21
  def add_entity(entity)
17
22
  add_entity_to_matching_component_lists(entity)
18
-
19
- entity.add_event_listener(:component_added,
20
- method(:on_entity_component_added))
21
- entity.add_event_listener(:component_removed,
22
- method(:on_entity_component_removed))
23
+
24
+ entity.add_event_listener(
25
+ :component_added,
26
+ method(:on_entity_component_added)
27
+ )
28
+ entity.add_event_listener(
29
+ :component_removed,
30
+ method(:on_entity_component_removed)
31
+ )
23
32
 
24
33
  entity.tags.each do |tag|
25
34
  @entities_by_tag[tag] ||= []
@@ -31,11 +40,15 @@ module Baku
31
40
  entity.tags.each do |tag|
32
41
  @entities_by_tag[tag].delete(entity)
33
42
  end
34
-
35
- entity.remove_event_listener(:component_added,
36
- method(:on_entity_component_added))
37
- entity.remove_event_listener(:component_removed,
38
- method(:on_entity_component_removed))
43
+
44
+ entity.remove_event_listener(
45
+ :component_added,
46
+ method(:on_entity_component_added)
47
+ )
48
+ entity.remove_event_listener(
49
+ :component_removed,
50
+ method(:on_entity_component_removed)
51
+ )
39
52
 
40
53
  @entities_by_component_mask.each do |component_mask, entities|
41
54
  if component_mask.matches?(entity.component_mask)
@@ -45,11 +58,11 @@ module Baku
45
58
  end
46
59
 
47
60
  def get_entities(component_mask)
48
- @entities_by_component_mask[component_mask]
61
+ @entities_by_component_mask[component_mask] || []
49
62
  end
50
63
 
51
64
  def get_entities_by_tag(tag)
52
- @entities_by_tag[tag]
65
+ @entities_by_tag[tag] || []
53
66
  end
54
67
 
55
68
  private
@@ -69,17 +82,17 @@ module Baku
69
82
  end
70
83
 
71
84
  def on_entity_component_removed(entity, component)
72
- old_mask = ComponentMask.from_components(entity.components + component)
85
+ old_mask = ComponentMask.from_components(entity.components.keys + [component.class])
73
86
  new_mask = entity.component_mask
74
87
 
75
88
  @entities_by_component_mask.each do |component_mask, entities|
76
- old_match = component_mask.match?(old_mask)
77
- new_match = component_mask.match?(new_mask)
78
-
89
+ old_match = component_mask.matches?(old_mask)
90
+ new_match = component_mask.matches?(new_mask)
91
+
79
92
  if old_match && !new_match
80
93
  entities.delete(entity)
81
94
  end
82
- end
95
+ end
83
96
  end
84
97
  end
85
98
  end
@@ -1,42 +1,34 @@
1
1
  module Baku
2
2
  class System
3
3
  attr_reader :components, :game_loop_step
4
- attr_writer :world
5
4
 
6
5
  def initialize(components, game_loop_step)
7
6
  @components = components
8
7
  @game_loop_step = game_loop_step
9
8
  end
10
9
 
10
+ def register_world(world)
11
+ @world = world
12
+ end
13
+
11
14
  def execute
12
15
  if @world.nil?
13
16
  raise StandardError.new("Must set :world property of System.")
14
17
  end
15
18
 
16
- entities = @world.entity_manager.get_entities(component_mask)
19
+ entities = retrieve_entities
17
20
 
18
21
  process_entities(entities)
19
22
  end
20
-
21
- def process_entities(entities)
22
- entities.each do |entity|
23
- entity_components = @components.map { |c| entity.get_component(c) }
24
- process_entity(entity, *entity_components)
25
- end
26
- end
27
23
 
28
24
  def process_entity(entity)
29
25
  raise NotImplementedError
30
26
  end
31
27
 
32
- def component_mask
33
- @component_mask ||= ComponentMask.from_components(@components)
34
- end
35
-
36
- private
28
+ protected
37
29
 
38
30
  def retrieve_entities
39
- @world.entity_manager.get_entities(component_mask)
31
+ raise NotImplementedError
40
32
  end
41
33
  end
42
34
  end
@@ -0,0 +1,24 @@
1
+ require_relative 'system'
2
+
3
+ module Baku
4
+ class TagSystem < System
5
+ attr_reader :tag
6
+
7
+ def initialize(tag, game_loop_step)
8
+ @tag = tag
9
+ @game_loop_step = game_loop_step
10
+ end
11
+
12
+ def process_entities(entities)
13
+ entities.each do |entity|
14
+ process_entity(entity)
15
+ end
16
+ end
17
+
18
+ protected
19
+
20
+ def retrieve_entities
21
+ @world.entity_manager.get_entities_by_tag(@tag)
22
+ end
23
+ end
24
+ end
@@ -1,3 +1,3 @@
1
1
  module Baku
2
- VERSION = "0.2.3"
2
+ VERSION = "0.3.1"
3
3
  end
@@ -13,6 +13,13 @@ module Baku
13
13
  @blackboard = {}
14
14
  end
15
15
 
16
+ def dispose
17
+ @update_systems.clear
18
+ @draw_systems.clear
19
+ @entity_manager.dispose
20
+ @blackboard.clear
21
+ end
22
+
16
23
  def add_system(system)
17
24
  system_list =
18
25
  if system.game_loop_step == :update
@@ -24,12 +31,10 @@ module Baku
24
31
  if system_list.map(&:class).include?(system.class)
25
32
  raise StandardError.new("Already added #{system.class} system to world.")
26
33
  end
27
-
28
- system_list << system
29
34
 
30
- @entity_manager.register_component_mask(system.component_mask)
35
+ system.register_world(self)
31
36
 
32
- system.world = self
37
+ system_list << system
33
38
  end
34
39
 
35
40
  def create_entity(tags = [])
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: baku
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Tuttle
8
- autorequire:
9
- bindir: exe
8
+ autorequire:
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2017-09-21 00:00:00.000000000 Z
11
+ date: 2020-11-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -16,56 +16,70 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.15'
19
+ version: 2.1.4
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.15'
26
+ version: 2.1.4
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
33
+ version: '13.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '10.0'
40
+ version: '13.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '3.0'
47
+ version: '3.9'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '3.0'
54
+ version: '3.9'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: pry-byebug
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 3.5.0
61
+ version: 3.9.0
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 3.5.0
68
+ version: 3.9.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: miru
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.1.0
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.1.0
69
83
  description: An Entity Component System framework for Ruby
70
84
  email:
71
85
  - jtuttle.develops@gmail.com
@@ -87,17 +101,18 @@ files:
87
101
  - lib/baku.rb
88
102
  - lib/baku/component.rb
89
103
  - lib/baku/component_mask.rb
104
+ - lib/baku/component_system.rb
90
105
  - lib/baku/entity.rb
91
106
  - lib/baku/entity_manager.rb
92
- - lib/baku/event_dispatcher.rb
93
107
  - lib/baku/system.rb
108
+ - lib/baku/tag_system.rb
94
109
  - lib/baku/version.rb
95
110
  - lib/baku/world.rb
96
111
  homepage: https://github.com/jtuttle/baku
97
112
  licenses:
98
113
  - MIT
99
114
  metadata: {}
100
- post_install_message:
115
+ post_install_message:
101
116
  rdoc_options: []
102
117
  require_paths:
103
118
  - lib
@@ -112,9 +127,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
112
127
  - !ruby/object:Gem::Version
113
128
  version: '0'
114
129
  requirements: []
115
- rubyforge_project:
116
- rubygems_version: 2.6.12
117
- signing_key:
130
+ rubygems_version: 3.0.6
131
+ signing_key:
118
132
  specification_version: 4
119
133
  summary: An Entity Component System framework for Ruby
120
134
  test_files: []
@@ -1,19 +0,0 @@
1
- module Baku
2
- module EventDispatcher
3
- def add_event_listener(event_name, method)
4
- @event_listeners ||= {}
5
- @event_listeners[event_name] ||= []
6
-
7
- @event_listeners[event_name] << method
8
- end
9
-
10
- def remove_event_listener(event_name, method)
11
- @event_listeners[event_name].delete(method)
12
- end
13
-
14
- def dispatch_event(event_name, *args)
15
- return unless @event_listeners && @event_listeners.has_key?(event_name)
16
- @event_listeners[event_name].each { |f| f.call(*args) }
17
- end
18
- end
19
- end