gemini 1.0.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.
Files changed (114) hide show
  1. data/bin/gemini +18 -0
  2. data/build_configuration.rb +24 -0
  3. data/lib/ibxm.jar +0 -0
  4. data/lib/jinput.jar +0 -0
  5. data/lib/jogg-0.0.7.jar +0 -0
  6. data/lib/jorbis-0.0.15.jar +0 -0
  7. data/lib/jruby-complete.jar +0 -0
  8. data/lib/lwjgl.jar +0 -0
  9. data/lib/lwjgl_util_applet.jar +0 -0
  10. data/lib/native_files/OpenAL32.dll +0 -0
  11. data/lib/native_files/jinput-dx8.dll +0 -0
  12. data/lib/native_files/jinput-raw.dll +0 -0
  13. data/lib/native_files/libjinput-linux.so +0 -0
  14. data/lib/native_files/libjinput-linux64.so +0 -0
  15. data/lib/native_files/libjinput-osx.jnilib +0 -0
  16. data/lib/native_files/liblwjgl.jnilib +0 -0
  17. data/lib/native_files/liblwjgl.so +0 -0
  18. data/lib/native_files/liblwjgl64.so +0 -0
  19. data/lib/native_files/libopenal.so +0 -0
  20. data/lib/native_files/lwjgl.dll +0 -0
  21. data/lib/native_files/openal.dylib +0 -0
  22. data/lib/natives-linux.jar +0 -0
  23. data/lib/natives-mac.jar +0 -0
  24. data/lib/natives-win32.jar +0 -0
  25. data/lib/phys2d.jar +0 -0
  26. data/lib/slick.jar +0 -0
  27. data/package/jar/gemini.jar +0 -0
  28. data/src/base_state.rb +112 -0
  29. data/src/behavior.rb +230 -0
  30. data/src/behavior_event.rb +23 -0
  31. data/src/behaviors.txt +5 -0
  32. data/src/behaviors/animated_sprite.rb +51 -0
  33. data/src/behaviors/audible.rb +11 -0
  34. data/src/behaviors/axis_stateful.rb +33 -0
  35. data/src/behaviors/big_sprite.rb +56 -0
  36. data/src/behaviors/bounding_box_collidable.rb +25 -0
  37. data/src/behaviors/camera_anchored_drawable.rb +20 -0
  38. data/src/behaviors/cardinal_movable.rb +114 -0
  39. data/src/behaviors/clickable.rb +18 -0
  40. data/src/behaviors/countable.rb +31 -0
  41. data/src/behaviors/debug_physical.rb +31 -0
  42. data/src/behaviors/debug_tangible.rb +30 -0
  43. data/src/behaviors/drawable.rb +6 -0
  44. data/src/behaviors/drawable_shape.rb +43 -0
  45. data/src/behaviors/fading_image_trail_emittable.rb +28 -0
  46. data/src/behaviors/game_object_emittable.rb +12 -0
  47. data/src/behaviors/gravity_source.rb +21 -0
  48. data/src/behaviors/inertial.rb +11 -0
  49. data/src/behaviors/movable2d.rb +9 -0
  50. data/src/behaviors/multi_animated_sprite.rb +22 -0
  51. data/src/behaviors/physical.rb +348 -0
  52. data/src/behaviors/physical_cardinal_movable.rb +110 -0
  53. data/src/behaviors/physical_sprite.rb +29 -0
  54. data/src/behaviors/platformer_controllable.rb +144 -0
  55. data/src/behaviors/pointer.rb +28 -0
  56. data/src/behaviors/pressable.rb +13 -0
  57. data/src/behaviors/receives_events.rb +21 -0
  58. data/src/behaviors/regional.rb +71 -0
  59. data/src/behaviors/rotates_to_point.rb +18 -0
  60. data/src/behaviors/spatial.rb +41 -0
  61. data/src/behaviors/spline_stretchable_sprite.rb +45 -0
  62. data/src/behaviors/sprite.rb +99 -0
  63. data/src/behaviors/stateful.rb +31 -0
  64. data/src/behaviors/taggable.rb +27 -0
  65. data/src/behaviors/tangible.rb +51 -0
  66. data/src/behaviors/timeable.rb +79 -0
  67. data/src/behaviors/top_down_vehicle.rb +41 -0
  68. data/src/behaviors/triangle_trail_emittable.rb +41 -0
  69. data/src/behaviors/updates.rb +10 -0
  70. data/src/behaviors/updates_at_consistant_rate.rb +27 -0
  71. data/src/behaviors/vectored_movement.rb +47 -0
  72. data/src/behaviors/world_collidable.rb +8 -0
  73. data/src/color.rb +70 -0
  74. data/src/game_object.rb +174 -0
  75. data/src/game_objects/background.rb +9 -0
  76. data/src/game_objects/fading_image.rb +23 -0
  77. data/src/game_objects/icon_strip_counter_display.rb +58 -0
  78. data/src/game_objects/static_sprite.rb +18 -0
  79. data/src/game_objects/tangible_object.rb +4 -0
  80. data/src/game_objects/text.rb +59 -0
  81. data/src/game_objects/triangle_trail.rb +85 -0
  82. data/src/gemini.rb +110 -0
  83. data/src/gemini_version.rb +3 -0
  84. data/src/inflector.rb +68 -0
  85. data/src/input_helpers/joystick_dead_zone_filter.rb +9 -0
  86. data/src/listenable_mixin.rb +15 -0
  87. data/src/managers/basic_game_object_manager.rb +81 -0
  88. data/src/managers/basic_physics_manager.rb +97 -0
  89. data/src/managers/basic_render_manager.rb +48 -0
  90. data/src/managers/basic_tangible_manager.rb +33 -0
  91. data/src/managers/basic_update_manager.rb +27 -0
  92. data/src/managers/diagnostic/diagnostic_input_manager.rb +0 -0
  93. data/src/managers/input_manager.rb +229 -0
  94. data/src/managers/input_support/input_mapping.rb +126 -0
  95. data/src/managers/input_support/input_message.rb +5 -0
  96. data/src/managers/input_support/slick_input_listener.rb +19 -0
  97. data/src/managers/input_support/slick_input_message.rb +11 -0
  98. data/src/managers/input_support/slick_input_translator.rb +15 -0
  99. data/src/managers/message_queue.rb +54 -0
  100. data/src/managers/scrolling_render_manager.rb +44 -0
  101. data/src/managers/sound_manager.rb +60 -0
  102. data/src/managers/tag_manager.rb +43 -0
  103. data/src/math.rb +13 -0
  104. data/src/music.rb +14 -0
  105. data/src/org/rubyforge/rawr/Main.java +67 -0
  106. data/src/platform.rb +28 -0
  107. data/src/proc_enhancement.rb +5 -0
  108. data/src/project_generator.rb +122 -0
  109. data/src/skeleton.txt +10 -0
  110. data/src/spline.rb +13 -0
  111. data/src/states/input_diagnostic_state.rb +53 -0
  112. data/src/vector.rb +99 -0
  113. data/test/test_state.rb +3 -0
  114. metadata +181 -0
@@ -0,0 +1,85 @@
1
+ class Gemini::TriangleTrail < Gemini::GameObject
2
+ #has_behavior :Movable2d
3
+ has_behavior :Spatial
4
+ attr_accessor :radius, :alpha
5
+
6
+ def load
7
+ @trail = []
8
+ @trail_poly_size = 10
9
+ @trail_size = 50
10
+ @radius = 10
11
+ @alpha = 0.5
12
+ @flip = false
13
+ #TODO: Remove message when the callback stuff is checked in
14
+ @first_move = true
15
+ listen_for(:after_move) do |message|
16
+ if @first_move
17
+ @first_move = false
18
+ next
19
+ end
20
+ @trail.pop if @trail.size >= @trail_size
21
+ @trail.unshift([x, y])
22
+ end
23
+ end
24
+
25
+ def draw(graphics)
26
+ if @trail.size > 3
27
+ gl = Java::org::newdawn::slick::opengl::renderer::Renderer.get
28
+
29
+ #Java::org::newdawn::slick::opengl::SlickCallable.new do
30
+ callable_class = Java::org::newdawn::slick::opengl::SlickCallable
31
+ callable_class.enter_safe_block
32
+ # use LWJGL's const directly, Slick's wrapper does not have the triangle strip const
33
+ triangle_strip_enum = Java::org::lwjgl::opengl::GL11::GL_TRIANGLE_STRIP
34
+ gl.gl_begin triangle_strip_enum
35
+ gl.gl_color4f(0.0, 1.0, 1.0, @alpha)
36
+
37
+ origin_x, origin_y = calculate_point_on_trail_edge(@trail[1], @trail[0], @radius, @flip)
38
+ gl.gl_vertex2f(origin_x, origin_y)
39
+
40
+ flipped_origin_x, flipped_origin_y = calculate_point_on_trail_edge(@trail[1], @trail[0], @radius, !@flip)
41
+ gl.gl_vertex2f(flipped_origin_x, flipped_origin_y)
42
+
43
+ last_trail_vector = @trail[1]
44
+ #gl.gl_color4f(0.0, 1.0, 1.0, alpha)
45
+ @trail[2..-1].each_with_index do |trail_vector, index|
46
+ next if trail_vector == last_trail_vector
47
+ actual_trail_size = (@trail.size - 1).to_f
48
+ trail_radius = (@radius) * ((actual_trail_size - (index + 2).to_f) / actual_trail_size)
49
+
50
+ rotated_x, rotated_y = calculate_point_on_trail_edge(trail_vector, last_trail_vector, trail_radius, @flip)
51
+ gl.gl_vertex2f(rotated_x, rotated_y)
52
+ rotated_x, rotated_y = calculate_point_on_trail_edge(trail_vector, last_trail_vector, trail_radius, !@flip)
53
+ gl.gl_vertex2f(rotated_x, rotated_y)
54
+
55
+ last_trail_vector = trail_vector
56
+ end
57
+ gl.gl_end
58
+ callable_class.leave_safe_block
59
+ end
60
+ end
61
+
62
+ def calculate_point_on_trail_edge(current_vector, previous_vector, trail_radius, flip)
63
+ trail_diff = [current_vector[0] - previous_vector[0], current_vector[1] - previous_vector[1]]
64
+ diff_angle = Math.atan2(trail_diff[1].to_f, trail_diff[0].to_f)
65
+
66
+ rotation_angle = (Math::PI * 1) / 2
67
+ rotation_angle = -rotation_angle if flip
68
+
69
+ sine = Math.sin(diff_angle + rotation_angle)
70
+ cosine = Math.cos(diff_angle + rotation_angle)
71
+ rotated_weight_x = cosine
72
+ rotated_weight_y = sine
73
+
74
+ rotated_x = (trail_radius * rotated_weight_x) + current_vector[0]
75
+ rotated_y = (trail_radius * rotated_weight_y) + current_vector[1]
76
+
77
+ [rotated_x, rotated_y]
78
+ end
79
+
80
+ def normalize_vector(vector)
81
+ max_value = vector.map{|value| value.abs}.max
82
+ return Array.new(vector.size, 0) if max_value.zero?
83
+ vector.map {|value| value / max_value}
84
+ end
85
+ end
@@ -0,0 +1,110 @@
1
+ $LOAD_PATH << File.expand_path(File.dirname(__FILE__) + '/managers').gsub('%20', ' ')
2
+ $LOAD_PATH << File.expand_path(File.dirname(__FILE__) + '/game_objects').gsub('%20', ' ')
3
+ #$LOAD_PATH << File.expand_path(File.dirname(__FILE__) + '/states')
4
+ $LOAD_PATH << File.expand_path(File.dirname(__FILE__) + '/input_helpers').gsub('%20', ' ')
5
+
6
+ # Because Windows isn't friendly with JRuby
7
+ $LOAD_PATH << 'managers'
8
+ $LOAD_PATH << 'game_objects'
9
+ #$LOAD_PATH << 'states'
10
+ $LOAD_PATH << 'input_helpers'
11
+
12
+ require 'platform'
13
+ require 'color'
14
+ require 'vector'
15
+ require 'spline'
16
+ require 'inflector'
17
+
18
+ require 'math'
19
+ require 'proc_enhancement'
20
+ require 'game_object'
21
+ require 'message_queue'
22
+ require 'input_manager'
23
+ require 'base_state'
24
+ require 'inflector'
25
+ require 'basic_game_object_manager'
26
+ require 'basic_update_manager'
27
+ require 'basic_render_manager'
28
+
29
+ module Gemini
30
+ class Main < Java::org::newdawn::slick::BasicGame
31
+ include_class 'org.newdawn.slick.AppGameContainer'
32
+ attr_accessor :screen_width, :screen_height, :initial_state
33
+
34
+ def self.start_app(screen_title, screen_width, screen_height, initial_state, fullscreen=false)
35
+ puts "in start app"
36
+ main = Main.new(screen_title, initial_state)
37
+ main.screen_width = screen_width
38
+ main.screen_height = screen_height
39
+ container = AppGameContainer.new(main, screen_width, screen_height, fullscreen)
40
+ container.vsync = false
41
+ container.maximum_logic_update_interval = 60
42
+ container.smooth_deltas = false #true
43
+ #main.container = container
44
+ container.start
45
+ end
46
+
47
+ def self.create_canvas(screen_title, screen_width, screen_height, initial_state)
48
+ main = Main.new screen_title, initial_state
49
+ main.screen_width = screen_width
50
+ main.screen_height = screen_height
51
+ puts "creating canvas"
52
+ $canvas = Java::org::newdawn::slick::CanvasGameContainer.new(main)
53
+ puts "setting size to #{screen_width}, #{screen_height}"
54
+ $canvas.set_size(screen_width, screen_height)
55
+ puts "done setting size"
56
+ container = $canvas.container
57
+ container.vsync = true
58
+ container.maximum_logic_update_interval = 60
59
+ #container.start
60
+ $canvas
61
+ end
62
+
63
+ def initialize(screen_title=nil, initial_state=:MainState)
64
+ super(screen_title)
65
+ @initial_state = initial_state
66
+ @fresh_state = true
67
+ end
68
+
69
+ def init(container)
70
+ @container = container
71
+ BaseState.active_state = load_state(@initial_state)
72
+ BaseState.active_state.load
73
+ end
74
+
75
+ def update(container, delta)
76
+ #don't tell the new state that it now has to update load time worth of a delta
77
+ if @fresh_state
78
+ delta = 0
79
+ @fresh_state = false
80
+ end
81
+ # Workaround for image loading with Slick.
82
+ # Must be done in game init or game loop (instead of immediately in the event).
83
+ if @queued_state
84
+ @queued_state.load(*@state_args)
85
+ BaseState.active_state = @queued_state
86
+ @queued_state = nil
87
+ @fresh_state = true
88
+ return
89
+ end
90
+ BaseState.active_state.manager(:input).poll(@screen_width, @screen_height, delta)
91
+ BaseState.active_state.manager(:message_queue).process_messages(delta)
92
+ BaseState.active_state.manager(:update).update(delta)
93
+ BaseState.active_state.manager(:game_object).__process_pending_game_objects
94
+ end
95
+
96
+ def render(container, graphics)
97
+ BaseState.active_state.manager(:render).render(graphics)
98
+ end
99
+
100
+ def load_state(state_name, args = [])
101
+ require "states/#{state_name.underscore}" unless Object.const_defined? state_name.camelize
102
+ @state_args = args
103
+ state_name.camelize.constantize.new @container, self
104
+ end
105
+
106
+ def queue_state(state)
107
+ @queued_state = state
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,3 @@
1
+ module Gemini
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,68 @@
1
+ # This code is a modified version of the Inflector class
2
+ # from the Ruby on Rails project (http://www.rubyonrails.com)
3
+
4
+ module Monkeybars
5
+ module Inflector
6
+ # The reverse of +camelize+. Makes an underscored form from the expression in the string.
7
+ #
8
+ # Changes '::' to '/' to convert namespaces to paths.
9
+ #
10
+ # Examples
11
+ # "ActiveRecord".underscore #=> "active_record"
12
+ # "ActiveRecord::Errors".underscore #=> active_record/errors
13
+ def underscore()
14
+ self.to_s.gsub(/::/, '/').
15
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
16
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
17
+ tr("-", "_").
18
+ downcase
19
+ end
20
+
21
+ # Constantize tries to find a declared constant with the name specified
22
+ # in the string. It raises a NameError when the name is not in CamelCase
23
+ # or is not initialized.
24
+ #
25
+ # Examples
26
+ # "Module".constantize #=> Module
27
+ # "Class".constantize #=> Class
28
+ def constantize()
29
+ unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ self.to_s
30
+ raise NameError, "#{self.inspect} is not a valid constant name!"
31
+ end
32
+
33
+ Object.module_eval("::#{$1}", __FILE__, __LINE__)
34
+ end
35
+
36
+ # By default, camelize converts strings to UpperCamelCase. If the argument to camelize
37
+ # is set to ":lower" then camelize produces lowerCamelCase.
38
+ #
39
+ # camelize will also convert '/' to '::' which is useful for converting paths to namespaces
40
+ #
41
+ # Examples
42
+ # "active_record".camelize #=> "ActiveRecord"
43
+ # "active_record".camelize(:lower) #=> "activeRecord"
44
+ # "active_record/errors".camelize #=> "ActiveRecord::Errors"
45
+ # "active_record/errors".camelize(:lower) #=> "activeRecord::Errors"
46
+ def camelize(first_letter_in_uppercase = true)
47
+ if first_letter_in_uppercase
48
+ self.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
49
+ else
50
+ self.to_s[0..0] + camelize(self.to_s)[1..-1]
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ class String
57
+ include Monkeybars::Inflector
58
+ end
59
+
60
+ class Symbol
61
+ include Monkeybars::Inflector
62
+ end
63
+
64
+ class Class
65
+ def constantize
66
+ self
67
+ end
68
+ end
@@ -0,0 +1,9 @@
1
+ module JoystickDeadZoneFilter
2
+ def filter_dead_zone(dead_zone, value)
3
+ if dead_zone > value.abs
4
+ 0.0
5
+ else
6
+ value
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,15 @@
1
+ module Gemini
2
+ module ListenableMixin
3
+ def __added_listener_for(target, method_name, callback)
4
+ @__methods_registered ||= {}
5
+ @__methods_registered[target] = [method_name, callback]
6
+ end
7
+
8
+ def __remove_listeners
9
+ return if @__methods_registered.nil?
10
+ @__methods_registered.each do |target, listener_method_name_and_callback|
11
+ target.send("remove_#{listener_method_name_and_callback.first}", self, listener_method_name_and_callback.last)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,81 @@
1
+ class BasicGameObjectManager < Gemini::GameObject
2
+ attr_reader :layers
3
+ FRONT_LAYER = 'front'
4
+ BACK_LAYER = 'back'
5
+
6
+ def load
7
+ enable_listeners_for :before_add_game_object, :after_add_game_object, :before_remove_game_object, :after_remove_game_object
8
+ #@layers = Hash.new{|h,k| h[k] = []}
9
+ @layer_order = [:default]
10
+ @layers = {:default => []}
11
+ @game_objects_to_remove = []
12
+ @game_objects_to_add = []
13
+ end
14
+
15
+ def __process_pending_game_objects
16
+ @game_objects_to_remove.pop.__destroy until @game_objects_to_remove.empty?
17
+ until @game_objects_to_add.empty?
18
+ layer, game_object = @game_objects_to_add.pop
19
+ @layers[layer] << game_object
20
+ end
21
+ end
22
+
23
+ def add_game_object(game_object)
24
+ notify :before_add_game_object, game_object, :default
25
+ @layers[:default] << game_object
26
+ notify :after_add_game_object, game_object, :default
27
+ end
28
+
29
+ def remove_game_object(game_object)
30
+ owning_layer = @layers.values.find {|layer| layer.include? game_object}
31
+ return if owning_layer.nil? #NOTE: Not sure if this is the right thing to do, but at least no exception is thrown
32
+ notify :before_remove_game_object, game_object
33
+ owning_layer.delete game_object
34
+ game_object.unload
35
+ notify :after_remove_game_object, game_object
36
+ @game_objects_to_remove.push game_object
37
+ #game_object.unload
38
+ end
39
+
40
+ def add_game_object_to_layer(game_object, layer)
41
+ notify :before_add_game_object, game_object, layer
42
+ @layers[layer] << game_object
43
+ #@game_objects_to_add.push [layer, game_object]
44
+ notify :after_add_game_object, game_object
45
+ end
46
+
47
+ def move_game_object_to_layer(game_object, layer_name)
48
+ owning_layer = @layers.values.find {|layer| layer.include? game_object}
49
+ owning_layer.delete game_object
50
+ @layers[layer_name] << game_object
51
+ end
52
+
53
+ def game_objects
54
+ game_objects = []
55
+ @layers.values.each do |layer|
56
+ layer.each do |game_object|
57
+ game_objects << game_object
58
+ end
59
+ end
60
+ game_objects
61
+ end
62
+
63
+ def layers_by_order
64
+ @layer_order.map {|layer_name| @layers[layer_name]}.compact
65
+ end
66
+
67
+ def add_layer_at(layer_name, location)
68
+ if location.kind_of? Numeric
69
+ @layer_order.delete_at(location) if @layer_order[location].nil?
70
+ @layer_order.insert(location, layer_name)
71
+ else # string/symbol
72
+ case location.to_s
73
+ when FRONT_LAYER
74
+ @layer_order << layer_name
75
+ when BACK_LAYER
76
+ @layer_order.unshift(layer_name)
77
+ end
78
+ end
79
+ @layers[layer_name] = []
80
+ end
81
+ end
@@ -0,0 +1,97 @@
1
+ require 'behaviors/physical'
2
+
3
+ class BasicPhysicsManager < Gemini::GameObject
4
+ INTERPOLATION_THESHOLD = 6.0
5
+ MILLISECONDS_PER_UPDATE = 6 # 6000/ 1000
6
+ DELTA_FACTOR = 0.01
7
+ include_class 'net.phys2d.math.Vector2f'
8
+ include_class 'net.phys2d.raw.World'
9
+ include_class 'net.phys2d.raw.strategies.QuadSpaceStrategy'
10
+ include_class 'net.phys2d.raw.strategies.BruteCollisionStrategy'
11
+ has_behavior :ReceivesEvents
12
+
13
+ def load
14
+ @delta_debt = 0
15
+ @world = World.new(Vector2f.new(0, 0), 5, QuadSpaceStrategy.new(20, 5))
16
+ # @world = World.new(Vector2f.new(0, 0), 10, BruteCollisionStrategy.new)
17
+ @world.add_listener self
18
+ @game_state.manager(:update).on_update do |delta|
19
+ update delta
20
+ end
21
+
22
+ @game_state.manager(:game_object).on_after_add_game_object do |game_object|
23
+ add_to_world game_object if game_object.kind_of? Physical
24
+ end
25
+
26
+ @game_state.manager(:game_object).on_after_remove_game_object do |game_object|
27
+ game_object.remove_from_world(@world) if game_object.kind_of? Physical
28
+ end
29
+
30
+ handle_event :toggle_debug_mode, :toggle_debug_mode
31
+ end
32
+
33
+ def update(delta)
34
+ delta += @delta_debt
35
+ @delta_debt = 0
36
+ if delta == MILLISECONDS_PER_UPDATE
37
+ step
38
+ else
39
+ temp_delta = delta
40
+ until temp_delta <= 0
41
+ new_delta = temp_delta > MILLISECONDS_PER_UPDATE ? MILLISECONDS_PER_UPDATE : temp_delta
42
+ if new_delta < MILLISECONDS_PER_UPDATE
43
+ @delta_debt = new_delta
44
+ return #don't step, we'll try again next update
45
+ else
46
+ step
47
+ temp_delta -= new_delta
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ # there's a typo in the API, I swears it.
54
+ def collision_occured(event)
55
+ event.body_a.user_data.notify :physical_collided, PhysicsMessage.new(event, event.body_b.user_data)
56
+ event.body_b.user_data.notify :physical_collided, PhysicsMessage.new(event, event.body_a.user_data)
57
+ end
58
+
59
+ def toggle_debug_mode(message)
60
+ @debug_mode = !@debug_mode
61
+ @game_state.manager(:game_object).game_objects.each do |game_object|
62
+ game_object.set_physical_debug_mode(@debug_mode) if game_object.kind_of? Physical
63
+ end
64
+ end
65
+
66
+ def gravity=(gravity_or_x)
67
+ if gravity_or_x.kind_of? Numeric
68
+ @world.set_gravity(0, gravity_or_x)
69
+ else
70
+ raise "Not implemented yet"
71
+ # @world.set_gravity(gravity_or_x)
72
+ end
73
+ end
74
+
75
+ private
76
+ def step
77
+ @world.step # must step at fixed rate (1/60f) or results are unpredictable
78
+ end
79
+
80
+ def add_to_world(game_object)
81
+ game_object.add_to_world(@world)
82
+ game_object.set_physical_debug_mode(true) if @debug_mode
83
+ end
84
+ # def colliding?(body)
85
+ # 0 < @world.get_contacts(body).size
86
+ # end
87
+
88
+ #TODO: Make subclass of Message
89
+ class PhysicsMessage
90
+ attr_reader :other, :event
91
+
92
+ def initialize(slick_event, other)
93
+ @event = slick_event
94
+ @other = other
95
+ end
96
+ end
97
+ end