gamebox 0.4.0.rc5 → 0.4.0.rc11

Sign up to get free protection for your applications and to get access to all the features.
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