baku 0.1.0 → 0.2.0
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 +4 -4
- data/.gitignore +3 -0
- data/CHANGELOG.md +10 -0
- data/README.md +0 -1
- data/baku.gemspec +1 -0
- data/lib/baku/component.rb +1 -3
- data/lib/baku/component_mask.rb +51 -0
- data/lib/baku/entity.rb +24 -11
- data/lib/baku/entity_manager.rb +47 -47
- data/lib/baku/event_dispatcher.rb +19 -0
- data/lib/baku/system.rb +12 -7
- data/lib/baku/version.rb +1 -1
- data/lib/baku/world.rb +14 -8
- data/lib/baku.rb +8 -2
- metadata +19 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1653036472420b349cb3e013e0d55a589ebe29cb
|
4
|
+
data.tar.gz: 4ce15a89513b81e4803b800a3083b7e5d51ce45a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cc818103da055af5358e1dfeab535945c31be1b847f931b54febebbe407e6ab3a3427660de8abeb5063d24ed2bf01ad958ce32af3b89bed1338061dd71ef6b35
|
7
|
+
data.tar.gz: 497c1f10325f892d97dbe9a48ef30052b4d03edc26e6cf20453e9ca52b32f7cee10d3a7bf7c5215fb85f4f74f1f4d2cf86eafda98b346bd926801dcb1445b487
|
data/.gitignore
CHANGED
data/CHANGELOG.md
ADDED
data/README.md
CHANGED
data/baku.gemspec
CHANGED
data/lib/baku/component.rb
CHANGED
@@ -0,0 +1,51 @@
|
|
1
|
+
module Baku
|
2
|
+
class ComponentMask
|
3
|
+
attr_reader :value
|
4
|
+
|
5
|
+
@@component_set = Set.new
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def record_components(components)
|
9
|
+
components.each do |component|
|
10
|
+
@@component_set << component
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def from_components(components)
|
15
|
+
record_components(components)
|
16
|
+
|
17
|
+
mask_value = 0
|
18
|
+
|
19
|
+
@@component_set.each_with_index do |component, index|
|
20
|
+
mask_value |= (1 << index) if components.include?(component)
|
21
|
+
end
|
22
|
+
|
23
|
+
ComponentMask.new(mask_value)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def initialize(value)
|
28
|
+
@value = value
|
29
|
+
end
|
30
|
+
|
31
|
+
def add_component(component_class)
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
def matches?(other_mask)
|
36
|
+
@value & other_mask.value == @value
|
37
|
+
end
|
38
|
+
|
39
|
+
def ==(other)
|
40
|
+
@value == other.value
|
41
|
+
end
|
42
|
+
|
43
|
+
def eql?(other)
|
44
|
+
self == other
|
45
|
+
end
|
46
|
+
|
47
|
+
def hash
|
48
|
+
value
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/baku/entity.rb
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
module Baku
|
2
2
|
class Entity
|
3
|
-
|
3
|
+
include Baku::EventDispatcher
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
attr_reader :components, :tags
|
6
|
+
|
7
|
+
def initialize(tags = [])
|
7
8
|
@tags = tags
|
8
|
-
|
9
|
-
@id = SecureRandom.uuid
|
10
9
|
@components = {}
|
11
10
|
end
|
12
11
|
|
@@ -16,9 +15,11 @@ module Baku
|
|
16
15
|
new("Entity already has component: #{component.class}")
|
17
16
|
end
|
18
17
|
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
components[component.class] = component
|
19
|
+
|
20
|
+
update_component_mask
|
21
|
+
|
22
|
+
dispatch_event(:component_added, self, component)
|
22
23
|
end
|
23
24
|
|
24
25
|
def remove_component(component_class)
|
@@ -27,13 +28,25 @@ module Baku
|
|
27
28
|
new("Entity does not have component: #{component_class}")
|
28
29
|
end
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
|
31
|
+
@components.delete(component_class)
|
32
|
+
|
33
|
+
update_component_mask
|
34
|
+
|
35
|
+
dispatch_event(:component_removed, self, @components[component_class])
|
33
36
|
end
|
34
37
|
|
35
38
|
def get_component(component_class)
|
36
39
|
@components[component_class]
|
37
40
|
end
|
41
|
+
|
42
|
+
def component_mask
|
43
|
+
@component_mask ||= ComponentMask.from_components(@components)
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def update_component_mask
|
49
|
+
@component_mask = ComponentMask.from_components(@components)
|
50
|
+
end
|
38
51
|
end
|
39
52
|
end
|
data/lib/baku/entity_manager.rb
CHANGED
@@ -1,54 +1,51 @@
|
|
1
1
|
module Baku
|
2
|
+
# The EntityManager stores entities in such a way that they can be retrieved
|
3
|
+
# efficiently by either ComponentMask or tag. Before storing any entities, the
|
4
|
+
# ComponentMasks that we wish to match on should be registered. This step is
|
5
|
+
# performed transparently by the World whenever a System is added.
|
2
6
|
class EntityManager
|
3
7
|
def initialize
|
4
|
-
@
|
8
|
+
@entities_by_component_mask = {}
|
5
9
|
@entities_by_tag = {}
|
6
|
-
|
7
|
-
@component_set = Set.new
|
8
|
-
@system_mask_cache = {}
|
9
10
|
end
|
10
11
|
|
11
|
-
def
|
12
|
+
def register_component_mask(component_mask)
|
13
|
+
@entities_by_component_mask[component_mask] = []
|
14
|
+
end
|
15
|
+
|
16
|
+
def add_entity(entity)
|
17
|
+
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
|
+
|
12
24
|
entity.tags.each do |tag|
|
13
25
|
@entities_by_tag[tag] ||= []
|
14
26
|
@entities_by_tag[tag] << entity
|
15
27
|
end
|
16
28
|
end
|
17
29
|
|
18
|
-
def
|
19
|
-
|
20
|
-
@
|
30
|
+
def remove_entity(entity)
|
31
|
+
entity.tags.each do |tag|
|
32
|
+
@entities_by_tag[tag].delete(entity)
|
21
33
|
end
|
22
|
-
|
23
|
-
system_component_mask =
|
24
|
-
get_component_mask(system.components)
|
25
|
-
|
26
|
-
@system_mask_cache[system] = system_component_mask
|
27
34
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
# the diff of the mask before and after, but this works for now.
|
33
|
-
def entity_add_component(entity, component)
|
34
|
-
old_mask = get_component_mask(entity.components)
|
35
|
-
entity.components[component.class] = component
|
36
|
-
new_mask = get_component_mask(entity.components)
|
37
|
-
|
38
|
-
update_system_membership(entity, old_mask, new_mask)
|
39
|
-
end
|
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))
|
40
39
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
update_system_membership(entity, old_mask, new_mask)
|
40
|
+
@entities_by_component_mask.each do |component_mask, entities|
|
41
|
+
if component_mask.matches?(entity.component_mask)
|
42
|
+
entities.delete(entity)
|
43
|
+
end
|
44
|
+
end
|
47
45
|
end
|
48
46
|
|
49
|
-
def
|
50
|
-
|
51
|
-
@entities_by_system_mask[system_mask]
|
47
|
+
def get_entities(component_mask)
|
48
|
+
@entities_by_component_mask[component_mask]
|
52
49
|
end
|
53
50
|
|
54
51
|
def get_entities_by_tag(tag)
|
@@ -57,27 +54,30 @@ module Baku
|
|
57
54
|
|
58
55
|
private
|
59
56
|
|
60
|
-
def
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
57
|
+
def add_entity_to_matching_component_lists(entity)
|
58
|
+
@entities_by_component_mask.each do |component_mask, entities|
|
59
|
+
if component_mask.matches?(entity.component_mask)
|
60
|
+
entities << entity
|
61
|
+
end
|
65
62
|
end
|
63
|
+
end
|
66
64
|
|
67
|
-
|
65
|
+
def on_entity_component_added(entity, component)
|
66
|
+
add_entity_to_matching_component_lists(entity)
|
68
67
|
end
|
69
68
|
|
70
|
-
def
|
71
|
-
|
72
|
-
|
73
|
-
|
69
|
+
def on_entity_component_removed(entity, component)
|
70
|
+
old_mask = ComponentMask.from_components(entity.components + component)
|
71
|
+
new_mask = entity.component_mask
|
72
|
+
|
73
|
+
@entities_by_component_mask.each do |component_mask, entities|
|
74
|
+
old_match = component_mask.match?(old_mask)
|
75
|
+
new_match = component_mask.match?(new_mask)
|
74
76
|
|
75
77
|
if old_match && !new_match
|
76
78
|
entities.delete(entity)
|
77
|
-
elsif !old_match && new_match
|
78
|
-
entities << entity
|
79
79
|
end
|
80
|
-
end
|
80
|
+
end
|
81
81
|
end
|
82
82
|
end
|
83
83
|
end
|
@@ -0,0 +1,19 @@
|
|
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
|
data/lib/baku/system.rb
CHANGED
@@ -1,25 +1,30 @@
|
|
1
1
|
module Baku
|
2
2
|
class System
|
3
3
|
attr_reader :components, :game_loop_step
|
4
|
-
|
4
|
+
attr_writer :entity_manager
|
5
5
|
|
6
6
|
def initialize(components, game_loop_step)
|
7
7
|
@components = components
|
8
8
|
@game_loop_step = game_loop_step
|
9
9
|
end
|
10
10
|
|
11
|
-
def
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
11
|
+
def process_entities
|
12
|
+
if @entity_manager.nil?
|
13
|
+
raise StandardError.new("Must set :entity_manager property of System.")
|
14
|
+
end
|
15
|
+
|
16
|
+
@entity_manager.get_entities(component_mask).each do |entity|
|
16
17
|
entity_components = @components.map { |c| entity.get_component(c) }
|
17
18
|
process_entity(entity, *entity_components)
|
18
19
|
end
|
19
20
|
end
|
20
|
-
|
21
|
+
|
21
22
|
def process_entity(entity)
|
22
23
|
raise NotImplementedError
|
23
24
|
end
|
25
|
+
|
26
|
+
def component_mask
|
27
|
+
@component_mask ||= ComponentMask.from_components(@components)
|
28
|
+
end
|
24
29
|
end
|
25
30
|
end
|
data/lib/baku/version.rb
CHANGED
data/lib/baku/world.rb
CHANGED
@@ -26,28 +26,34 @@ module Baku
|
|
26
26
|
end
|
27
27
|
|
28
28
|
system_list << system
|
29
|
-
|
29
|
+
|
30
|
+
@entity_manager.register_component_mask(system.component_mask)
|
30
31
|
|
31
|
-
@entity_manager
|
32
|
+
system.entity_manager = @entity_manager
|
32
33
|
end
|
33
34
|
|
34
35
|
def create_entity(tags = [])
|
35
|
-
entity = Entity.new(
|
36
|
-
@entity_manager.
|
36
|
+
entity = Entity.new(tags)
|
37
|
+
@entity_manager.add_entity(entity)
|
37
38
|
entity
|
38
39
|
end
|
39
40
|
|
40
|
-
def
|
41
|
-
@entity_manager.
|
41
|
+
def destroy_entity(entity)
|
42
|
+
@entity_manager.remove_entity(entity)
|
42
43
|
end
|
43
44
|
|
44
45
|
def update(delta_ms)
|
45
46
|
@delta_ms = delta_ms
|
46
|
-
|
47
|
+
|
48
|
+
@update_systems.each do |system|
|
49
|
+
system.process_entities
|
50
|
+
end
|
47
51
|
end
|
48
52
|
|
49
53
|
def draw
|
50
|
-
@draw_systems.each
|
54
|
+
@draw_systems.each do |system|
|
55
|
+
system.process_entities
|
56
|
+
end
|
51
57
|
end
|
52
58
|
end
|
53
59
|
end
|
data/lib/baku.rb
CHANGED
@@ -1,8 +1,14 @@
|
|
1
1
|
require "baku/version"
|
2
2
|
|
3
3
|
module Baku
|
4
|
-
|
4
|
+
begin
|
5
|
+
require 'pry-byebug'
|
6
|
+
rescue LoadError
|
7
|
+
# development dependencies
|
8
|
+
end
|
9
|
+
|
5
10
|
require 'set'
|
6
|
-
|
11
|
+
|
12
|
+
require_relative "baku/event_dispatcher.rb"
|
7
13
|
Gem.find_files("baku/**/*.rb").each { |path| require path }
|
8
14
|
end
|
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.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Tuttle
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-09-
|
11
|
+
date: 2017-09-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pry-byebug
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 3.5.0
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 3.5.0
|
55
69
|
description: An Entity Component System framework for Ruby
|
56
70
|
email:
|
57
71
|
- jtuttle.develops@gmail.com
|
@@ -62,6 +76,7 @@ files:
|
|
62
76
|
- ".gitignore"
|
63
77
|
- ".rspec"
|
64
78
|
- ".travis.yml"
|
79
|
+
- CHANGELOG.md
|
65
80
|
- Gemfile
|
66
81
|
- LICENSE.txt
|
67
82
|
- README.md
|
@@ -71,8 +86,10 @@ files:
|
|
71
86
|
- bin/setup
|
72
87
|
- lib/baku.rb
|
73
88
|
- lib/baku/component.rb
|
89
|
+
- lib/baku/component_mask.rb
|
74
90
|
- lib/baku/entity.rb
|
75
91
|
- lib/baku/entity_manager.rb
|
92
|
+
- lib/baku/event_dispatcher.rb
|
76
93
|
- lib/baku/system.rb
|
77
94
|
- lib/baku/version.rb
|
78
95
|
- lib/baku/world.rb
|