gamebox 0.4.0.rc5 → 0.4.0.rc11

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.
Files changed (93) hide show
  1. data/README.md +205 -127
  2. data/bin/gamebox +49 -3
  3. data/bin/gb +87 -0
  4. data/gamebox.gemspec +4 -3
  5. data/lib/gamebox.rb +1 -1
  6. data/lib/gamebox/actors/collidable_debugger.rb +4 -4
  7. data/lib/gamebox/actors/icon.rb +7 -0
  8. data/lib/gamebox/actors/label.rb +41 -42
  9. data/lib/gamebox/behaviors/animated.rb +6 -0
  10. data/lib/gamebox/behaviors/audible.rb +1 -2
  11. data/lib/gamebox/behaviors/collidable.rb +1 -1
  12. data/lib/gamebox/behaviors/graphical.rb +8 -4
  13. data/lib/gamebox/behaviors/physical.rb +6 -1
  14. data/lib/gamebox/behaviors/positioned.rb +4 -11
  15. data/lib/gamebox/behaviors/projectile.rb +8 -0
  16. data/lib/gamebox/behaviors/visible.rb +3 -3
  17. data/lib/gamebox/core/aabb_tree.rb +1 -1
  18. data/lib/gamebox/core/actor.rb +37 -50
  19. data/lib/gamebox/core/actor_definition.rb +41 -0
  20. data/lib/gamebox/core/actor_view.rb +6 -21
  21. data/lib/gamebox/core/actor_view_definition.rb +19 -0
  22. data/lib/gamebox/core/actor_view_factory.rb +9 -3
  23. data/lib/gamebox/core/behavior.rb +8 -27
  24. data/lib/gamebox/core/behavior_definition.rb +24 -0
  25. data/lib/gamebox/core/config_manager.rb +45 -30
  26. data/lib/gamebox/core/configuration.rb +5 -0
  27. data/lib/gamebox/core/core.rb +4 -0
  28. data/lib/gamebox/core/debug_helpers.rb +46 -0
  29. data/lib/gamebox/core/director.rb +32 -5
  30. data/lib/gamebox/core/event_symbols.rb +214 -0
  31. data/lib/gamebox/core/game.rb +1 -1
  32. data/lib/gamebox/core/input_manager.rb +1 -4
  33. data/lib/gamebox/core/input_mapper.rb +85 -0
  34. data/lib/gamebox/core/physics.rb +7 -3
  35. data/lib/gamebox/core/physics_manager.rb +5 -1
  36. data/lib/gamebox/core/renderer.rb +72 -0
  37. data/lib/gamebox/core/stage.rb +25 -81
  38. data/lib/gamebox/core/stage_definition.rb +60 -0
  39. data/lib/gamebox/core/stage_factory.rb +56 -0
  40. data/lib/gamebox/core/stage_manager.rb +5 -11
  41. data/lib/gamebox/core/timer_manager.rb +6 -2
  42. data/lib/gamebox/core/viewport.rb +12 -5
  43. data/lib/gamebox/core/wrapped_screen.rb +8 -5
  44. data/lib/gamebox/gamebox_application.rb +21 -19
  45. data/lib/gamebox/lib/array_ext.rb +9 -0
  46. data/lib/gamebox/lib/observable_attributes.rb +24 -0
  47. data/lib/gamebox/lib/vector2.rb +432 -0
  48. data/lib/gamebox/post_setup_handlers/file_watcher.rb +37 -0
  49. data/lib/gamebox/post_setup_handlers/gamebox_debug_helpers.rb +13 -0
  50. data/lib/gamebox/post_setup_handlers/pry_remote_server.rb +29 -0
  51. data/lib/gamebox/spec/helper.rb +165 -17
  52. data/lib/gamebox/tasks/gamebox_tasks.rake +27 -12
  53. data/lib/gamebox/version.rb +1 -1
  54. data/lib/gamebox/views/graphical_actor_view.rb +4 -5
  55. data/script/perf_aabb.rb +13 -8
  56. data/spec/acceptance/animation_spec.rb +1 -3
  57. data/spec/acceptance/basic_actor_lifecycle_spec.rb +1 -1
  58. data/spec/acceptance/fps_actor_spec.rb +8 -12
  59. data/spec/acceptance/input_mapper_spec.rb +17 -24
  60. data/spec/acceptance/update_ordering_spec.rb +64 -0
  61. data/spec/actors/label_spec.rb +90 -5
  62. data/spec/behaviors/animated_spec.rb +1 -1
  63. data/spec/behaviors/collidable_spec.rb +7 -15
  64. data/spec/behaviors/positioned_spec.rb +12 -5
  65. data/spec/core/actor_spec.rb +31 -3
  66. data/spec/core/actor_view_spec.rb +1 -1
  67. data/spec/core/behavior_spec.rb +3 -0
  68. data/spec/core/configuration_spec.rb +49 -2
  69. data/spec/core/input_mapper_spec.rb +7 -0
  70. data/spec/core/renderer_spec.rb +89 -0
  71. data/spec/core/stage_definition_spec.rb +41 -0
  72. data/spec/core/stage_manager_spec.rb +11 -11
  73. data/spec/core/stage_spec.rb +38 -78
  74. data/spec/core/viewport_spec.rb +5 -2
  75. data/spec/core/wrapped_screen_spec.rb +18 -12
  76. data/spec/views/graphical_actor_view_spec.rb +33 -62
  77. data/templates/actor_template.erb +11 -0
  78. data/templates/app/README.md +1 -0
  79. data/templates/app/src/actors/{player.rb → player_actor.rb} +3 -1
  80. data/templates/app/src/behaviors/.gitkeep +0 -0
  81. data/templates/app/src/stages/demo_stage.rb +14 -0
  82. data/templates/behavior_template.erb +13 -0
  83. data/templates/stage_template.erb +13 -0
  84. metadata +60 -21
  85. data/component_generators/actor_generator.rb +0 -17
  86. data/lib/gamebox/actors/emitter.rb +0 -12
  87. data/lib/gamebox/behaviors/emitting.rb +0 -48
  88. data/lib/gamebox/behaviors/input_mapper.rb +0 -11
  89. data/lib/gamebox/lib/ftor.rb +0 -372
  90. data/spec/actors/emitter_spec.rb +0 -5
  91. data/templates/app/NEXT_STEPS.txt +0 -1
  92. data/templates/app/README.rdoc +0 -24
  93. data/templates/app/src/demo_stage.rb +0 -7
data/bin/gb ADDED
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rake'
3
+ require 'thor'
4
+ require 'gamebox'
5
+ include Rake::DSL
6
+
7
+ DIST_TYPES = %w(mac win linux)
8
+ load File.expand_path(File.join(File.dirname(__FILE__), "..", "/lib/gamebox/tasks/gamebox_tasks.rake"))
9
+
10
+ def print_version
11
+ puts "Gamebox #{Gamebox::VERSION::STRING}"
12
+ end
13
+
14
+ def run_rake_task(*args)
15
+ sh "rake #{args.shift}[#{args.join(',')}]"
16
+ end
17
+
18
+ if ARGV.include?('-v') || ARGV.include?('--version')
19
+ print_version
20
+ exit 0
21
+ end
22
+
23
+ class GameboxThorCommand < Thor
24
+ include Thor::Actions
25
+
26
+ def self.source_root
27
+ File.join(File.dirname(__FILE__), "../templates/")
28
+ end
29
+
30
+ desc "new PATH", "Generates a new gamebox game at PATH."
31
+ def new(*args)
32
+ game_name = args[0]
33
+ self.destination_root = game_name
34
+
35
+ if Gamebox::VERSION::RC > 0
36
+ @gamebox_version = Gamebox::VERSION::STRING
37
+ else
38
+ @gamebox_version = "~> "+[Gamebox::VERSION::MAJOR, Gamebox::VERSION::MINOR, '0'].join('.')
39
+ end
40
+
41
+ directory "app", "."
42
+ end
43
+ desc "n PATH", "Generates a new gamebox game at PATH."
44
+ alias_method :n, :new
45
+
46
+ desc "start", "starts the application"
47
+ def start
48
+ print_version
49
+ run_rake_task("run")
50
+ end
51
+
52
+ desc "s", "starts the application"
53
+ alias_method :s, :start
54
+
55
+ desc "debug", "starts the application in debug"
56
+ def debug
57
+ print_version
58
+ run_rake_task("debug")
59
+ end
60
+
61
+ desc "d", "starts the application in debug"
62
+ alias_method :d, :debug
63
+
64
+ desc "dist [mac|linux|win|all]", "Build an executable for your app"
65
+ def dist(*args)
66
+ dist_type = args[0]
67
+ if DIST_TYPES.include?(dist_type)
68
+ run_rake_task("dist:#{dist_type}")
69
+ elsif dist_type == "all"
70
+ DIST_TYPES.each do |type|
71
+ run_rake_task("dist:#{type}")
72
+ end
73
+ else
74
+ p "Unrecognized dist type"
75
+ end
76
+ end
77
+
78
+ desc "generate [actor|behavior|stage] NAME", "Gamebox generator, this will generate templated files for you for quicker development"
79
+ def generate(*args)
80
+ run_rake_task("generate:#{args.shift}", *args)
81
+ end
82
+ desc "g [actor|behavior|stage] NAME", "Gamebox generator, this will generate templated files for you for quicker development"
83
+ alias_method :g, :generate
84
+
85
+ end
86
+
87
+ GameboxThorCommand.start
@@ -20,12 +20,13 @@ Gem::Specification.new do |s|
20
20
 
21
21
  s.add_dependency "gosu"
22
22
  s.add_dependency "publisher"
23
- s.add_dependency "conject", ">= 0.0.5"
23
+ s.add_dependency "conject", ">= 0.0.8"
24
24
  s.add_dependency "tween"
25
25
  s.add_dependency "i18n"
26
- s.add_dependency "thor", ">= 0.15.2"
26
+ s.add_dependency "thor", ">= 0.14.6"
27
27
  s.add_dependency "require_all"
28
- s.add_dependency "kvo", ">= 0.0.2"
28
+ s.add_dependency "kvo", ">= 0.1.0"
29
+ s.add_dependency "listen", ">= 0.5.3"
29
30
 
30
31
  s.add_development_dependency "pry", '~>0.9.7'
31
32
  s.add_development_dependency "pry-remote"
@@ -26,7 +26,7 @@ end
26
26
 
27
27
  require "#{GAMEBOX_PATH}/version.rb"
28
28
  require 'require_all'
29
- directory_load_order = %w(lib core actors behaviors views stagehands)
29
+ directory_load_order = %w(lib core post_setup_handlers actors behaviors views stagehands)
30
30
  directory_load_order.each do |dir|
31
31
  require_all "#{GAMEBOX_PATH}/#{dir}/**/*.rb"
32
32
  end
@@ -1,8 +1,8 @@
1
- Actor.define :collidable_debugger do
1
+ define_actor :collidable_debugger do
2
2
  has_behaviors :collider_container
3
3
  end
4
4
 
5
- Behavior.define :collider_container do
5
+ define_behavior :collider_container do
6
6
  setup do
7
7
  actor.has_attributes collider: actor.opts[:collider]
8
8
  actor.collider.when :remove do
@@ -11,9 +11,9 @@ Behavior.define :collider_container do
11
11
  end
12
12
  end
13
13
 
14
- ActorView.define :collidable_debugger_view do
14
+ define_actor_view :collidable_debugger_view do
15
15
 
16
- configure do
16
+ setup do
17
17
  @color = Color::WHITE
18
18
  end
19
19
 
@@ -0,0 +1,7 @@
1
+ # actor to represent an image being drawn somewhere
2
+ # example:
3
+ # create_actor :icon, image: 'my/image.png'
4
+ define_actor :icon do
5
+ has_behaviors :positioned, :graphical
6
+ has_attributes view: :graphical_actor_view
7
+ end
@@ -1,50 +1,49 @@
1
- Behavior.define :label_stuff do
2
- requires_behaviors :positioned
3
- requires :font_style_factory
4
-
5
- setup do
6
- # will define attributes and set their values if no one else has
7
- actor.has_attributes text: "",
8
- font_size: 30,
9
- font_name: "Asimov.ttf",
10
- color: [250,250,250,255],
11
- width: 0,
12
- height: 0,
13
- layer: 1
14
-
15
-
16
- font_style = font_style_factory.build actor.font_name, actor.font_size, actor.color
17
- actor.has_attributes font_style: font_style
1
+ define_actor :label do
2
+ has_attributes layered: 1
3
+ behavior do
4
+ requires_behaviors :positioned
5
+ requires :font_style_factory
6
+
7
+ setup do
8
+ # will define attributes and set their values if no one else has
9
+ actor.has_attributes text: "",
10
+ font_size: Gamebox.configuration.default_font_size,
11
+ font_name: Gamebox.configuration.default_font_name,
12
+ color: Gamebox.configuration.default_font_color,
13
+ width: 0,
14
+ height: 0,
15
+ layer: 1
16
+
17
+
18
+ font_style = font_style_factory.build actor.font_name, actor.font_size, actor.color
19
+ actor.has_attributes font_style: font_style
20
+
21
+ actor.when :font_size_changed do
22
+ actor.font_style.size = actor.font_size
23
+ actor.font_style.reload
24
+ recalculate_size
25
+ end
26
+ actor.when :font_name_changed do
27
+ actor.font_style.name = actor.font_name
28
+ actor.font_style.reload
29
+ recalculate_size
30
+ end
31
+ actor.when :text_changed do
32
+ recalculate_size
33
+ end
34
+ actor.when :color_changed do
35
+ actor.font_style.color = actor.color
36
+ end
18
37
 
19
- actor.when :font_size_changed do
20
- actor.font_style.size = actor.font_size
21
- actor.font_style.reload
22
- recalculate_size
23
- end
24
- actor.when :font_name_changed do
25
- actor.font_style.reload
26
- recalculate_size
27
- end
28
- actor.when :text_changed do
29
- recalculate_size
30
- end
31
- actor.when :color_changed do
32
- actor.font_style.color = actor.color
33
38
  end
34
39
 
35
- end
36
-
37
- helpers do
38
- def recalculate_size
39
- actor.width = actor.font_style.calc_width actor.text
40
- actor.height = actor.font_style.height
40
+ helpers do
41
+ def recalculate_size
42
+ actor.width = actor.font_style.calc_width actor.text
43
+ actor.height = actor.font_style.height
44
+ end
41
45
  end
42
46
  end
43
- end
44
-
45
- Actor.define :label do
46
- has_attributes layered: 1
47
- has_behavior :label_stuff
48
47
 
49
48
  view do
50
49
  draw do |target,x_off,y_off,z|
@@ -36,9 +36,15 @@ Behavior.define :animated do
36
36
  set_image
37
37
  end
38
38
  end
39
+
40
+ reacts_with :remove
39
41
  end
40
42
 
41
43
  helpers do
44
+ def remove
45
+ director.unsubscribe_all self
46
+ end
47
+
42
48
  def next_frame
43
49
  action_set = @images[actor.action]
44
50
  @frame_num = (@frame_num + 1) % action_set.size unless action_set.nil?
@@ -1,7 +1,6 @@
1
1
 
2
2
 
3
- Behavior.define :audible do
4
-
3
+ define_behavior :audible do
5
4
  requires :sound_manager
6
5
  setup do
7
6
  reacts_with :play_sound, :stop_sound
@@ -56,7 +56,7 @@ Behavior.define :collidable do
56
56
  stage.unregister_collidable actor
57
57
  end
58
58
 
59
- reacts_with :position_changed
59
+ actor.when(:position_changed) { position_changed }
60
60
  end
61
61
 
62
62
  helpers do
@@ -7,10 +7,14 @@ Behavior.define :graphical do
7
7
  requires_behaviors :layered
8
8
  requires :resource_manager
9
9
  setup do
10
- image = resource_manager.load_actor_image(actor)
11
- scale = @opts[:scale] || 1,
12
- actor.has_attributes( image: image,
13
- width: image.width,
10
+ image = actor.do_or_do_not(:image) || resource_manager.load_actor_image(actor)
11
+ image = resource_manager.load_image(image) if image.is_a? String
12
+ scale = @opts[:scale] || 1
13
+
14
+ actor.has_attribute :image
15
+ actor.image = image
16
+
17
+ actor.has_attributes( width: image.width,
14
18
  height: image.height,
15
19
  tiled: @opts[:tiled],
16
20
  view: @opts[:view] || :graphical_actor_view,
@@ -52,10 +52,15 @@ Behavior.define :physical do
52
52
 
53
53
  warp(vec2(actor.x,actor.y))
54
54
 
55
- reacts_with :warp
55
+ reacts_with :warp, :remove
56
56
  end
57
57
 
58
58
  helpers do
59
+ def remove
60
+ # TODO not sure what else needs to be cleaned up here
61
+ director.unsubscribe_all self
62
+ end
63
+
59
64
  def setup_friction
60
65
  @friction = @opts[:friction]
61
66
  @friction ||= 0.4
@@ -1,18 +1,11 @@
1
1
  define_behavior :positioned do
2
- requires :director
3
2
  setup do
4
3
  x = opts[:x] || 0
5
4
  y = opts[:y] || 0
6
5
  actor.has_attributes x: x, y: y
7
- director.when :update do |time|
8
- if @x_dirty || @y_dirty
9
- actor.react_to :position_changed
10
- actor.emit :position_changed
11
- end
12
- @x_dirty = false
13
- @y_dirty = false
14
- end
15
- actor.when :x_changed do @x_dirty = true end
16
- actor.when :y_changed do @y_dirty = true end
6
+ actor.has_attributes position: vec2(actor.x, actor.y)
7
+ actor.when(:x_changed) { actor.position = vec2(actor.x, actor.y) }
8
+ actor.when(:y_changed) { actor.position = vec2(actor.x, actor.y) }
17
9
  end
10
+
18
11
  end
@@ -10,6 +10,14 @@ define_behavior :projectile do
10
10
  actor.x += (actor.vel_x * secs)
11
11
  actor.y += (actor.vel_y * secs)
12
12
  end
13
+
14
+ reacts_with :remove
15
+ end
16
+
17
+ helpers do
18
+ def remove
19
+ director.unsubscribe_all self
20
+ end
13
21
  end
14
22
 
15
23
  end
@@ -1,15 +1,15 @@
1
1
  # in charge of registering / showing / hiding of actor views
2
2
  define_behavior :visible do
3
- requires :stage
3
+ requires :renderer
4
4
  setup do
5
5
  actor.has_attribute :visible
6
6
  end
7
7
 
8
8
  react_to do |message, *args|
9
9
  if message == :show
10
- stage.register_drawable opts[:view] unless actor.visible
10
+ renderer.register_drawable opts[:view] unless actor.visible
11
11
  elsif message == :hide
12
- stage.unregister_drawable opts[:view] if actor.visible
12
+ renderer.unregister_drawable opts[:view] if actor.visible
13
13
  end
14
14
  actor.visible = message == :show
15
15
  end
@@ -132,7 +132,7 @@ class AABBTree
132
132
  w ||= 2
133
133
  h ||= 2
134
134
 
135
- expand_bb_by!(Rect.new item.x, item.y, w, h, DEFAULT_BB_SCALE)
135
+ expand_bb_by!(Rect.new(item.x, item.y, w, h), DEFAULT_BB_SCALE)
136
136
  end
137
137
  end
138
138
  end
@@ -8,6 +8,7 @@ class Actor
8
8
  can_fire_anything
9
9
  construct_with :this_object_context
10
10
  public :this_object_context
11
+ attr_accessor :actor_type
11
12
 
12
13
  def initialize
13
14
  has_attribute :alive, true
@@ -15,8 +16,8 @@ class Actor
15
16
  end
16
17
 
17
18
  def configure(opts={}) # :nodoc:
19
+ self.actor_type = opts.delete(:actor_type)
18
20
  has_attributes opts
19
- self.actor_type = opts[:actor_type]
20
21
  end
21
22
 
22
23
  # Used by BehaviorFactory#add_behavior.
@@ -31,11 +32,12 @@ class Actor
31
32
  end
32
33
  end
33
34
 
34
- def react_to(message, *opts)
35
+ def react_to(message, *opts, &blk)
35
36
  # TODO cache the values array?
36
37
  @behaviors.values.each do |behavior|
37
- behavior.react_to(message, *opts)
38
+ behavior.react_to(message, *opts, &blk)
38
39
  end
40
+ nil
39
41
  end
40
42
 
41
43
  def has_behavior?(name)
@@ -54,16 +56,40 @@ class Actor
54
56
  fire :remove_me
55
57
  end
56
58
 
59
+ def input
60
+ # TODO conject should have a lazily loaded dependency mechanism
61
+ @input_mapper ||= this_object_context[:input_mapper]
62
+ end
63
+
57
64
  def to_s
58
- atts = methods.sort - Actor.instance_methods
59
- atts_hash = {}
60
- atts.each do |att|
61
- atts_hash[att] = send(att) unless att.to_s.end_with? "="
65
+ attrs = []
66
+ attributes.keys.sort.each do |name|
67
+ attrs << "#{name}: #{printable_value(attributes[name])}"
68
+ end
69
+ """
70
+ #{actor_type}:#{self.object_id}
71
+ Behaviors:
72
+ #{@behaviors.keys.sort}
73
+ Attributes:
74
+ #{attrs.join("\n")}
75
+ """
76
+ end
77
+ alias pretty_inspect to_s
78
+
79
+ private
80
+ def printable_value(value)
81
+ case value
82
+ when String, Float, Fixnum, TrueClass, FalseClass, Vector2
83
+ value
84
+ when Array
85
+ value.map do |pv|
86
+ printable_value(pv)
87
+ end
88
+ else
89
+ value.class
62
90
  end
63
- "#{self.actor_type}:#{self.object_id} with attributes\n#{atts_hash.inspect}"
64
91
  end
65
92
 
66
- # TODO should this live somewhere else?
67
93
  class << self
68
94
 
69
95
  def define(actor_type, opts={}, &blk)
@@ -74,7 +100,6 @@ class Actor
74
100
  # TODO evaluate the perf of doing this
75
101
  definition.source = caller.detect{|c|!c.match /core/}
76
102
  definition.instance_eval &blk if block_given?
77
- @definitions[actor_type] = definition
78
103
 
79
104
  view_blk = definition.view_blk
80
105
  if view_blk
@@ -86,6 +111,8 @@ class Actor
86
111
  Behavior.define actor_type, &behavior_blk
87
112
  definition.has_behavior actor_type
88
113
  end
114
+
115
+ @definitions[actor_type] = definition
89
116
  end
90
117
 
91
118
  def definitions
@@ -94,45 +121,5 @@ class Actor
94
121
 
95
122
  end
96
123
 
97
- class ActorDefinition
98
- attr_accessor :behaviors, :attributes, :view_blk, :behavior_blk, :source
99
- def initialize
100
- @behaviors = []
101
- @attributes = []
102
- end
103
-
104
- def has_behaviors(*behaviors, &blk)
105
- if block_given?
106
- collector = MethodMissingCollector.new
107
- collector.instance_eval &blk
108
- collector.calls.each do |name, args|
109
- if args.empty?
110
- @behaviors << name
111
- else
112
- @behaviors << {name => args.first}
113
- end
114
- end
115
- end
116
- behaviors.each do |beh|
117
- @behaviors << beh
118
- end
119
- end
120
- alias has_behavior has_behaviors
121
-
122
- def has_attributes(*attributes)
123
- attributes.each do |att|
124
- @attributes << att
125
- end
126
- end
127
- alias has_behavior has_behaviors
128
-
129
- def view(&blk)
130
- @view_blk = blk
131
- end
132
-
133
- def behavior(&blk)
134
- @behavior_blk = blk
135
- end
136
- end
137
124
 
138
125
  end