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,48 @@
1
+ class BasicRenderManager < Gemini::GameObject
2
+ include_class 'org.newdawn.slick.geom.Circle'
3
+
4
+ def load
5
+ enable_listeners_for :before_render, :after_render
6
+ @image_cache = {}
7
+ @debug_queue = []
8
+ end
9
+
10
+ def render(graphics)
11
+ notify :before_render, graphics
12
+ #game_state.manager(:game_object).game_objects.each { |game_object| game_object.draw if game_object.respond_to? :draw}
13
+ game_state.manager(:game_object).layers_by_order.each do |game_objects|
14
+ game_objects.each { |game_object| game_object.draw(graphics) if game_object.respond_to? :draw}
15
+ end
16
+
17
+ pre_debug_color = graphics.color
18
+ until @debug_queue.empty?
19
+ debug_render = @debug_queue.shift
20
+ color = debug_render[:color]
21
+ color = Color.new(color) unless color.kind_of? Color
22
+ graphics.color = color.native_color
23
+ case debug_render[:type]
24
+ when :point
25
+ graphics.fill Circle.new(debug_render[:position].x, debug_render[:position].y, 2)
26
+ end
27
+ end
28
+ graphics.color = pre_debug_color
29
+ notify :after_render, graphics
30
+ end
31
+
32
+ def debug(type, color, options)
33
+ @debug_queue << {:type => type, :color => color}.merge(options)
34
+ end
35
+
36
+ def cache_image(cache_name, image_name)
37
+ image_resource = begin
38
+ Java::org::newdawn::slick::Image.new "data/#{image_name}"
39
+ rescue java.lang.RuntimeException
40
+ Java::org::newdawn::slick::Image.new "../data/#{image_name}"
41
+ end
42
+ @image_cache[cache_name] = image_resource
43
+ end
44
+
45
+ def get_cached_image(cache_name)
46
+ @image_cache[cache_name].copy
47
+ end
48
+ end
@@ -0,0 +1,33 @@
1
+ require 'behaviors/tangible'
2
+
3
+ class BasicTangibleManager < Gemini::GameObject
4
+ has_behavior :ReceivesEvents
5
+ has_behavior :Updates
6
+
7
+ def load
8
+ handle_event :toggle_debug_mode, :toggle_debug_mode
9
+ on_update do
10
+ @game_state.manager(:game_object).game_objects.each do |game_object|
11
+ next unless game_object.kind_of? Tangible
12
+ @game_state.manager(:game_object).game_objects.each do |other_game_object|
13
+ next unless other_game_object.kind_of? Tangible
14
+ next if game_object == other_game_object
15
+ if game_object.tangibly_collides_with?(other_game_object)
16
+ game_object.notify :tangible_collision
17
+ other_game_object.notify :tangible_collision
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ def toggle_debug_mode(unused_message=nil)
25
+ @debug_mode = !@debug_mode
26
+ @game_state.manager(:game_object).game_objects.each do |game_object|
27
+ game_object.set_tangible_debug_mode(@debug_mode) if game_object.kind_of? Tangible
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ end
@@ -0,0 +1,27 @@
1
+ class BasicUpdateManager < Gemini::GameObject
2
+ def load
3
+ enable_listeners_for :update, :before_update, :after_update
4
+ end
5
+
6
+ def update(delta)
7
+ # delta = 20.0
8
+ return if paused?
9
+
10
+ notify :before_update, delta
11
+ game_state.manager(:game_object).game_objects.each { |game_object| game_object.update(delta) if game_object.respond_to? :update}
12
+ notify :update, delta
13
+ notify :after_update, delta
14
+ end
15
+
16
+ def pause
17
+ @paused = true
18
+ end
19
+
20
+ def resume
21
+ @paused = false
22
+ end
23
+
24
+ def paused?
25
+ @paused
26
+ end
27
+ end
@@ -0,0 +1,229 @@
1
+ include_class 'org.newdawn.slick.Input'
2
+ include_class 'org.newdawn.slick.InputListener'
3
+ require 'message_queue'
4
+
5
+ require 'input_support/input_mapping'
6
+ require 'input_support/input_message'
7
+ require 'input_support/slick_input_listener'
8
+ require 'input_support/slick_input_message'
9
+
10
+ KEY_PRESSED = {:source_type => :key, :source_state => :pressed}
11
+ KEY_RELEASED = {:source_type => :key, :source_state => :released}
12
+ KEY_HELD = {:source_type => :key, :source_state => :held}
13
+ MOUSE_MOVED = {:source_type => :mouse, :source_state => :moved, :source_value => :any}
14
+ MOUSE_BUTTON1_PRESSED = {:source_type => :mouse, :source_state => :pressed, :source_value => Input::MOUSE_LEFT_BUTTON }
15
+ MOUSE_BUTTON1_RELEASED = {:source_type => :mouse, :source_state => :released, :source_value => Input::MOUSE_LEFT_BUTTON}
16
+ MOUSE_BUTTON2_PRESSED = {:source_type => :mouse, :source_state => :pressed, :source_value => Input::MOUSE_RIGHT_BUTTON}
17
+ MOUSE_BUTTON2_RELEASED = {:source_type => :mouse, :source_state => :released, :source_value => Input::MOUSE_RIGHT_BUTTON}
18
+ MOUSE_BUTTON3_PRESSED = {:source_type => :mouse, :source_state => :pressed, :source_value => Input::MOUSE_MIDDLE_BUTTON}
19
+ MOUSE_BUTTON3_RELEASED = {:source_type => :mouse, :source_state => :released, :source_value => Input::MOUSE_MIDDLE_BUTTON}
20
+
21
+ #
22
+ # XBox 360 controllers use the following axii:
23
+ # x
24
+ # y
25
+ # z
26
+ # rx
27
+ # ry
28
+ # rz
29
+ #
30
+ # The 360 controller has two sticks and two triggers
31
+ #
32
+ CONTROLLER_AXIS_UPDATE = {:source_type => :controller, :source_state => :axis_update}
33
+ CONTROLLER_BUTTON_PRESSED = {:source_type => :controller, :source_state => :pressed}
34
+ CONTROLLER_BUTTON_RELEASED = {:source_type => :controller, :source_state => :released}
35
+ CONTROLLER_BUTTON_HELD = {:source_type => :controller, :source_state => :held}
36
+
37
+ #TODO: Discover Windows mappings
38
+ if Platform.using_osx?
39
+ # buttons
40
+ XBOX_360_DPAD_UP = 0 # No Windows "buttons" for the dpad - it's unusable
41
+ XBOX_360_DPAD_DOWN = 1
42
+ XBOX_360_DPAD_LEFT = 2
43
+ XBOX_360_DPAD_RIGHT = 3
44
+ XBOX_360_START = 4
45
+ XBOX_360_BACK = 5
46
+ XBOX_360_LEFT_STICK = 6
47
+ XBOX_360_RIGHT_STICK = 7
48
+ XBOX_360_LEFT_BUMPER = 8
49
+ XBOX_360_RIGHT_BUMPER = 9
50
+ XBOX_360_GUIDE_BUTTON = 10
51
+ XBOX_360_A = 11
52
+ XBOX_360_B = 12
53
+ XBOX_360_X = 13
54
+ XBOX_360_Y = 14
55
+ # axes
56
+ XBOX_360_LEFT_X_AXIS = 'x'
57
+ XBOX_360_LEFT_Y_AXIS = 'y'
58
+ XBOX_360_LEFT_TRIGGER_AXIS = 'z' # On Windows, both triggers serve as one axis
59
+ XBOX_360_RIGHT_X_AXIS = 'rx'
60
+ XBOX_360_RIGHT_Y_AXIS = 'ry'
61
+ XBOX_360_RIGHT_TRIGGER_AXIS = 'rz' # On Windows, both triggers serve as one axis
62
+ elsif Platform.using_windows?
63
+ # buttons
64
+ XBOX_360_A = 0
65
+ XBOX_360_B = 1
66
+ XBOX_360_X = 2
67
+ XBOX_360_Y = 3
68
+ XBOX_360_LEFT_BUMPER = 4
69
+ XBOX_360_RIGHT_BUMPER = 5
70
+ XBOX_360_BACK = 6
71
+ XBOX_360_START = 7
72
+ XBOX_360_LEFT_STICK = 8
73
+ XBOX_360_RIGHT_STICK = 9
74
+ #axes
75
+ XBOX_360_LEFT_X_AXIS = 'X Axis'
76
+ XBOX_360_LEFT_Y_AXIS = 'Y Axis'
77
+ XBOX_360_TRIGGER_AXIS = 'Z Axis' # On OSX, both triggers serve as individual axes
78
+ XBOX_360_RIGHT_X_AXIS = 'X Rotation'
79
+ XBOX_360_RIGHT_Y_AXIS = 'Y Rotation'
80
+ end
81
+
82
+ # LWJGL can't poll for buttons in the negative range yet. Possible bug to report?
83
+ # 360 controller provides button presses for analog inputs for convienence
84
+ XBOX_360_LEFT_STICK_LEFT = -1
85
+ XBOX_360_LEFT_STICK_RIGHT = -2
86
+ XBOX_360_LEFT_STICK_UP = -3
87
+ XBOX_360_LEFT_STICK_DOWN = -4
88
+
89
+ class MouseEvent
90
+ PRESSED = :pressed
91
+ RELEASED = :released
92
+ attr_accessor :state, :location
93
+ def initialize(state, location)
94
+ @state, @location = state, location
95
+ end
96
+ end
97
+
98
+ module Gemini
99
+ # Consumes raw slick_input events and output events based on
100
+ # registered key bindings.
101
+ class InputManager < Gemini::GameObject
102
+
103
+ $LOAD_PATH.each do |path|
104
+ puts path
105
+ if File.basename(path) == "input_helpers"
106
+ # could be .class or .rb, we'll just search for *.* and hope nobody is silly (:
107
+ Dir.glob(File.join(File.expand_path(path), "*.*").gsub('%20', ' ')).each do |input_helper_path|
108
+ require input_helper_path.sub('.class', '') # .class can't be required directly
109
+ include File.basename(input_helper_path, '.rb').sub('.class', '').camelize.constantize
110
+ end
111
+ end
112
+ end
113
+
114
+ MAX_CONTROLLERS = 6
115
+
116
+ @@loading_input_manager = nil
117
+ def self.loading_input_manager
118
+ @@loading_input_manager
119
+ end
120
+
121
+ def self.define_keymap
122
+ yield loading_input_manager
123
+ end
124
+
125
+ def load(container)
126
+ @held_keys = []
127
+ @raw_input = container.input
128
+ @input_listener = Gemini::SlickInputListener.new(@game_state)
129
+ @raw_input.add_listener @input_listener
130
+ @held_buttons = {}
131
+ end
132
+
133
+ def load_keymap(keymap)
134
+ @keymap = Hash.new{|h,k| h[k] = []}
135
+
136
+ @held_buttons = Hash.new {|h,k| h[k] = []}
137
+ keymap_name = "/keymaps/#{keymap.underscore}"
138
+ keymap_path = $LOAD_PATH.find do |path|
139
+ puts "trying path for .rb/.class: #{File.expand_path(path + keymap_name)}"
140
+ File.exist?(File.expand_path(path + keymap_name + '.rb')) || File.exist?(File.expand_path(path + keymap_name + '.class'))
141
+ end
142
+ puts "keymap found: #{keymap_path.inspect}"
143
+
144
+ @@loading_input_manager = self
145
+ keymap_path += '/' unless keymap_path.nil? # was using <<, but that alters the load path in a bad way.
146
+ begin
147
+ # the method 'load' already exists on this scope
148
+ Kernel.load "#{keymap_path}#{keymap_name.sub('/', '')}.class"
149
+ rescue LoadError
150
+ # the method 'load' already exists on this scope
151
+ Kernel.load "#{keymap_path}#{keymap_name.sub('/', '')}.rb"
152
+ end
153
+ @@loading_input_manager = nil
154
+ end
155
+
156
+ def poll(screen_width, screen_height, delta)
157
+ return if @keymap.nil?
158
+ @input_listener.delta = delta
159
+ @raw_input.poll(screen_width, screen_height)
160
+ @keymap.values.map {|keymap_array| keymap_array.map{|keymap| keymap.poll(@raw_input)} }.flatten.compact.each do |game_message|
161
+ @game_state.manager(:message_queue).post_message game_message
162
+ end
163
+
164
+ # Check for any held keys
165
+ # @held_buttons.each do |device, button_ids|
166
+ # button_ids.each do |button_id|
167
+ # invoke_callbacks_for(device, :held, button_id, nil, delta)
168
+ # end
169
+ # end
170
+ end
171
+
172
+ # probably needs deletion
173
+ def poll_keyboard
174
+
175
+ end
176
+
177
+ # probably needs deletion
178
+ def poll_mouse
179
+
180
+ end
181
+
182
+ # probably needs deletion
183
+ def poll_joystick
184
+ @raw_input.controller_count.times do |controller_id|
185
+ @raw_input.get_axis_count(controller_id).times do |axis_id|
186
+ axis_name = @raw_input.get_axis_name(controller_id, axis_id)
187
+ axis_value = @raw_input.get_axis_value(controller_id, axis_id)
188
+ # Do we really want to do this on each poll?
189
+ # No raw slick event to catch, should be wrapped anyways
190
+ message = InputMessage.new(:joystick_id => controller_id, :input_name => axis_name, :input_value => axis_value, :raw_input => @raw_input)
191
+ invoke_callbacks_for(:joystick, :axis_update, axis_name, controller_id, message)
192
+ end
193
+ end
194
+ end
195
+
196
+ def connected_joystick_size
197
+ @raw_input.controller_count
198
+ end
199
+
200
+ def map_key(options, &block)
201
+ map :key, options, &block
202
+ end
203
+
204
+ def map_mouse(options, &block)
205
+ map :mouse, options, &block
206
+ end
207
+
208
+ def map_joystick(options, &block)
209
+ map :joystick, options, &block
210
+ end
211
+
212
+ private
213
+ def find_keymaps_for(device, input_button_or_axis, id)
214
+ @keymap["#{device}_#{input_button_or_axis}_#{id}"]
215
+ end
216
+
217
+ def map(device, options, &block)
218
+ mapping = InputMapping.create(device, options, &block)
219
+ @keymap[mapping.key] << mapping
220
+ end
221
+
222
+ def invoke_callbacks_for(device, input_type, input_button_or_axis, id, input_message)
223
+ key_mappings = find_keymaps_for(device, input_type, input_button_or_axis, id)
224
+ key_mappings.each do |key_map|
225
+ @game_state.manager(:message_queue).post_message key_map.to_game_message(input_message)
226
+ end
227
+ end
228
+ end
229
+ end
@@ -0,0 +1,126 @@
1
+ require 'managers/input_support/input_message'
2
+
3
+ module Gemini
4
+ class InputMapping
5
+ attr_accessor :device, :input_type, :input_button_or_axis, :joystick_id, :destination_type, :destination_value, :input_callback
6
+
7
+ def self.create(device, options, &callback)
8
+ options[:input_callback] = callback
9
+ new(device, options)
10
+ end
11
+
12
+ # TODO: Indicate whether or not a joystick mapping is active if a joystick is not installed
13
+ def initialize(device, options)
14
+ options = options.dup # we're going to delete some entries, which could have odd side effects without a clone
15
+ @device = device
16
+ @input_type = [:held, :released, :pressed, :axis_update].find do |input_event_name|
17
+ input_event_button_or_axis = options.delete input_event_name
18
+ if input_event_button_or_axis.nil?
19
+ false
20
+ else
21
+ @input_button_or_axis = input_event_button_or_axis
22
+ true
23
+ end
24
+ end
25
+
26
+ @joystick_id = options.delete(:joystick_id)
27
+ @input_callback = options.delete(:input_callback)
28
+ @player = options.delete :player
29
+ # after all the deletes, the game message and value should be only what's left
30
+ @game_message = options.keys.first
31
+ @game_value = options.values.first
32
+ end
33
+
34
+ def poll(raw_input)
35
+ @game_value = case @device
36
+ when :key
37
+ poll_key(raw_input)
38
+ when :mouse
39
+ when :joystick
40
+ poll_joystick(raw_input)
41
+ end
42
+ if post_canceled?
43
+ nil
44
+ else
45
+ to_game_message(raw_input)
46
+ end
47
+ end
48
+
49
+ def poll_key(raw_input)
50
+ case @input_type
51
+ when :pressed
52
+ result = raw_input.is_key_pressed(@input_button_or_axis)
53
+ cancel_post! unless result
54
+ result
55
+ when :held
56
+ result = raw_input.is_key_down(@input_button_or_axis)
57
+ cancel_post! unless result
58
+ result
59
+ when :released
60
+ key_down = raw_input.is_key_down(@input_button_or_axis)
61
+ result = (@key_down_on_last_poll && !key_down) ? true : false
62
+ @key_down_on_last_poll = key_down
63
+ cancel_post! unless result
64
+ result
65
+ else
66
+ cancel_post!
67
+ end
68
+ end
69
+
70
+ def poll_joystick(raw_input)
71
+ if @joystick_id >= raw_input.controller_count
72
+ cancel_post!
73
+ return
74
+ end
75
+
76
+ case @input_type
77
+ when :axis_update
78
+ @axis_id ||= find_axis_id_by_axis_name(raw_input, @input_button_or_axis)
79
+ axis_value = raw_input.get_axis_value(@joystick_id, @axis_id)
80
+ axis_value
81
+ when :pressed
82
+ result = raw_input.is_button_pressed(@input_button_or_axis, @joystick_id)
83
+ cancel_post! unless result
84
+ result
85
+ when :held
86
+ result = raw_input.is_button_pressed(@input_button_or_axis, @joystick_id)
87
+ cancel_post! unless result
88
+ result
89
+ when :released
90
+ button_down = raw_input.is_button_pressed(@input_button_or_axis, @joystick_id)
91
+ result = (@key_down_on_last_poll && !button_down) ? true : false
92
+ @key_down_on_last_poll = button_down
93
+ cancel_post! unless result
94
+ result
95
+ else
96
+ cancel_post!
97
+ end
98
+ end
99
+
100
+ def cancel_post!
101
+ @cancel_post = true
102
+ end
103
+
104
+ def post_canceled?
105
+ result = @cancel_post
106
+ @cancel_post = false
107
+ result
108
+ end
109
+
110
+ def find_axis_id_by_axis_name(raw_input, axis_name)
111
+ (0..raw_input.get_axis_count(@joystick_id)).find {|axis_id| raw_input.get_axis_name(@joystick_id, axis_id) == axis_name}
112
+ end
113
+
114
+ def key
115
+ "#{@device}_#{@input_type}_#{@input_button_or_axis}_#{@joystick_id}"
116
+ end
117
+
118
+ # eventually, raw_input will need to be wrapped
119
+ def to_game_message(raw_input)
120
+ game_message = InputMessage.new(@game_message, @game_value)
121
+ game_message.player = @player
122
+ @input_callback.call(game_message, raw_input) unless @input_callback.nil?
123
+ game_message
124
+ end
125
+ end
126
+ end