jemini 2009.10.27

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 (127) hide show
  1. data/README.txt +9 -0
  2. data/bin/jemini +26 -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-dx8_64.dll +0 -0
  13. data/lib/native_files/jinput-raw.dll +0 -0
  14. data/lib/native_files/jinput-raw_64.dll +0 -0
  15. data/lib/native_files/jinput-wintab.dll +0 -0
  16. data/lib/native_files/libjinput-linux.so +0 -0
  17. data/lib/native_files/libjinput-linux64.so +0 -0
  18. data/lib/native_files/libjinput-osx.jnilib +0 -0
  19. data/lib/native_files/liblwjgl.jnilib +0 -0
  20. data/lib/native_files/liblwjgl.so +0 -0
  21. data/lib/native_files/liblwjgl64.so +0 -0
  22. data/lib/native_files/libopenal.so +0 -0
  23. data/lib/native_files/lwjgl.dll +0 -0
  24. data/lib/native_files/openal.dylib +0 -0
  25. data/lib/natives-linux.jar +0 -0
  26. data/lib/natives-mac.jar +0 -0
  27. data/lib/natives-win32.jar +0 -0
  28. data/lib/phys2d.jar +0 -0
  29. data/lib/slick.jar +0 -0
  30. data/package/jar/jemini.jar +0 -0
  31. data/src/behavior.rb +248 -0
  32. data/src/behavior_event.rb +23 -0
  33. data/src/behaviors/animated_image.rb +88 -0
  34. data/src/behaviors/audible.rb +16 -0
  35. data/src/behaviors/axis_stateful.rb +35 -0
  36. data/src/behaviors/bounding_box_collidable.rb +27 -0
  37. data/src/behaviors/cardinal_movable.rb +121 -0
  38. data/src/behaviors/clickable.rb +19 -0
  39. data/src/behaviors/countable.rb +32 -0
  40. data/src/behaviors/debug_physical.rb +43 -0
  41. data/src/behaviors/debug_tangible.rb +31 -0
  42. data/src/behaviors/drawable.rb +7 -0
  43. data/src/behaviors/drawable_image.rb +111 -0
  44. data/src/behaviors/drawable_line.rb +32 -0
  45. data/src/behaviors/drawable_shape.rb +48 -0
  46. data/src/behaviors/fading_image_trail_emittable.rb +32 -0
  47. data/src/behaviors/game_object_emittable.rb +13 -0
  48. data/src/behaviors/grid_bound.rb +108 -0
  49. data/src/behaviors/handles_events.rb +33 -0
  50. data/src/behaviors/inertial.rb +14 -0
  51. data/src/behaviors/magnetic.rb +34 -0
  52. data/src/behaviors/metered.rb +3 -0
  53. data/src/behaviors/movable.rb +81 -0
  54. data/src/behaviors/particle_emitter.rb +27 -0
  55. data/src/behaviors/physical.rb +384 -0
  56. data/src/behaviors/physical_cardinal_movable.rb +111 -0
  57. data/src/behaviors/physical_image.rb +45 -0
  58. data/src/behaviors/pointer.rb +30 -0
  59. data/src/behaviors/pressable.rb +17 -0
  60. data/src/behaviors/regional.rb +76 -0
  61. data/src/behaviors/rotates_to_point.rb +19 -0
  62. data/src/behaviors/spatial.rb +43 -0
  63. data/src/behaviors/stateful.rb +33 -0
  64. data/src/behaviors/taggable.rb +28 -0
  65. data/src/behaviors/tangible.rb +59 -0
  66. data/src/behaviors/timeable.rb +88 -0
  67. data/src/behaviors/top_down_vehicle.rb +42 -0
  68. data/src/behaviors/triangle_trail_emittable.rb +46 -0
  69. data/src/behaviors/unique.rb +0 -0
  70. data/src/behaviors/updates.rb +8 -0
  71. data/src/behaviors/updates_at_consistant_rate.rb +28 -0
  72. data/src/behaviors/vectored_movement.rb +48 -0
  73. data/src/behaviors/world_collidable.rb +9 -0
  74. data/src/color.rb +70 -0
  75. data/src/events/grid_changed_event.rb +8 -0
  76. data/src/events/physical_message.rb +9 -0
  77. data/src/events/tangible_collision_event.rb +8 -0
  78. data/src/file_system.rb +17 -0
  79. data/src/game.rb +110 -0
  80. data/src/game_object.rb +176 -0
  81. data/src/game_objects/background.rb +10 -0
  82. data/src/game_objects/fading_image.rb +23 -0
  83. data/src/game_objects/tangible_object.rb +4 -0
  84. data/src/game_objects/text.rb +71 -0
  85. data/src/game_objects/triangle_trail.rb +85 -0
  86. data/src/game_state.rb +164 -0
  87. data/src/inflector.rb +68 -0
  88. data/src/input_helpers/joystick_dead_zone_filter.rb +9 -0
  89. data/src/jemini.rb +31 -0
  90. data/src/jemini_version.rb +4 -0
  91. data/src/listenable_mixin.rb +15 -0
  92. data/src/logger_mixin.rb +11 -0
  93. data/src/managers/basic_game_object_manager.rb +95 -0
  94. data/src/managers/basic_physics_manager.rb +95 -0
  95. data/src/managers/basic_render_manager.rb +49 -0
  96. data/src/managers/basic_tile_manager.rb +3 -0
  97. data/src/managers/basic_update_manager.rb +30 -0
  98. data/src/managers/diagnostic/diagnostic_input_manager.rb +0 -0
  99. data/src/managers/input_manager.rb +161 -0
  100. data/src/managers/input_support/input_binding.rb +77 -0
  101. data/src/managers/input_support/input_builder.rb +44 -0
  102. data/src/managers/input_support/input_listener.rb +74 -0
  103. data/src/managers/input_support/input_message.rb +5 -0
  104. data/src/managers/input_support/joystick_listener.rb +53 -0
  105. data/src/managers/input_support/key_listener.rb +27 -0
  106. data/src/managers/input_support/mouse_listener.rb +38 -0
  107. data/src/managers/input_support/slick_input_listener.rb +20 -0
  108. data/src/managers/input_support/slick_input_message.rb +11 -0
  109. data/src/managers/input_support/slick_input_translator.rb +15 -0
  110. data/src/managers/message_queue.rb +60 -0
  111. data/src/managers/network_manager.rb +41 -0
  112. data/src/managers/render_support/hardware_cursor.rb +13 -0
  113. data/src/managers/resource_manager.rb +167 -0
  114. data/src/managers/sound_manager.rb +47 -0
  115. data/src/managers/tag_manager.rb +47 -0
  116. data/src/managers/tangible_manager.rb +36 -0
  117. data/src/math.rb +23 -0
  118. data/src/org/rubyforge/rawr/Main.java +67 -0
  119. data/src/platform.rb +28 -0
  120. data/src/proc_enhancement.rb +5 -0
  121. data/src/project_generator.rb +138 -0
  122. data/src/resource.rb +31 -0
  123. data/src/spline.rb +13 -0
  124. data/src/states/input_diagnostic_state.rb +53 -0
  125. data/src/vector.rb +143 -0
  126. data/test/test_state.rb +3 -0
  127. metadata +188 -0
@@ -0,0 +1,77 @@
1
+ require 'managers/input_support/input_listener'
2
+
3
+ module Jemini
4
+ class InputBinding
5
+ MOUSE_BUTTON_NAMES = [:mouse_left, :mouse_right, :mouse_middle].freeze
6
+ attr_reader :action_name, :listeners
7
+
8
+ def initialize(action_name)
9
+ @action_name = action_name
10
+ @listeners = []
11
+ end
12
+
13
+ # type can be one of :hold, :release, :press, and :move
14
+ def add_input_listener(type, button_id, options={})
15
+ device = detect_device(button_id, type)
16
+ real_button = detect_button(button_id, device)
17
+ value = options[:value]
18
+ to = options[:to]
19
+ listener = InputListener.create(action_name, type, device, real_button)
20
+ listener.default_value = value
21
+ listener.message_to = to
22
+ InputManager.loading_input_manager.listeners << listener
23
+ end
24
+
25
+ def detect_device(button_id, type)
26
+ if mouse_button?(button_id, type)
27
+ :mouse
28
+ else
29
+ :key
30
+ end
31
+ end
32
+
33
+ def detect_button(button_id, device)
34
+ case device
35
+ when :mouse
36
+ detect_mouse_button(button_id)
37
+ when :key
38
+ case button_id.to_s
39
+ when /(left|right)_alt/
40
+ "Input::KEY_#{$1[0].chr.upcase}ALT".constantize
41
+ when /(left|right)_ctrl/
42
+ "Input::KEY_#{$1[0].chr.upcase}CONTROL".constantize
43
+ when /(left|right)_bracket/
44
+ "Input::KEY_#{$1[0].chr.upcase}BRACKET".constantize
45
+ when /(up|down|left|right)_arrow/
46
+ "Input::KEY_#{$1.upcase}".constantize
47
+ when /(left|right)_shift/
48
+ "Input::KEY_#{$1[0].chr.upcase}SHIFT".constantize
49
+ else
50
+ "Input::KEY_#{button_id.to_s.underscore.upcase}".constantize
51
+ end
52
+ end
53
+ end
54
+
55
+ def mouse_button?(button_id, type)
56
+ return true if type == :move && button_id == :mouse
57
+ return true if MOUSE_BUTTON_NAMES.include? button_id
58
+ return false unless button_id.respond_to? :has_key?
59
+ return true if button_id.has_key? :mouse_button
60
+ end
61
+
62
+ def detect_mouse_button(button_id)
63
+ case button_id
64
+ when :mouse_left
65
+ 0
66
+ when :mouse_right
67
+ 1
68
+ when :mouse_middle
69
+ 2
70
+ when :mouse
71
+ nil
72
+ else
73
+ button_id[:mouse_button]
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,44 @@
1
+ require 'managers/input_support/input_binding'
2
+ require 'logger_mixin'
3
+
4
+ module Jemini
5
+ class InputBuilder
6
+
7
+ include LoggerMixin
8
+
9
+ def self.declare
10
+ yield new
11
+ end
12
+
13
+ def in_order_to(action_name)
14
+ log.debug "in_order_to: #{action_name}"
15
+ @current_binding = create_binding(action_name)
16
+ yield self
17
+ @current_binding = nil
18
+ end
19
+
20
+ def create_binding(action_name)
21
+ InputBinding.new(action_name)
22
+ end
23
+
24
+ def hold(button, options={})
25
+ log.debug "hold: #{button}, #{options}"
26
+ @current_binding.add_input_listener(:hold, button, options)
27
+ end
28
+
29
+ def press(button, options={})
30
+ log.debug "press: #{button}, #{options}"
31
+ @current_binding.add_input_listener(:press, button, options)
32
+ end
33
+
34
+ def release(button, options={})
35
+ log.debug "release: #{button}, #{options}"
36
+ @current_binding.add_input_listener(:release, button, options)
37
+ end
38
+
39
+ def move(button, options={})
40
+ log.debug "move: #{button}, #{options}"
41
+ @current_binding.add_input_listener(:move, button, options)
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,74 @@
1
+ require 'managers/input_support/input_message'
2
+
3
+ module Jemini
4
+ class InputListener
5
+ attr_accessor :device,
6
+ :input_type,
7
+ :input_button_or_axis,
8
+ :joystick_id,
9
+ :destination_type,
10
+ :destination_value,
11
+ :input_callback,
12
+ :game_state,
13
+ :default_value,
14
+ :message_to
15
+
16
+ def self.create(message, type, device, button_id, options={}, &callback)
17
+ options[:input_callback] = callback
18
+ device_type = case device
19
+ when :key
20
+ KeyListener
21
+ when :mouse
22
+ MouseListener
23
+ when :joystick
24
+ JoystickListener
25
+ end
26
+ device_type.new(message, type, button_id, options)
27
+ end
28
+
29
+ # TODO: Indicate whether or not a joystick mapping is active if a joystick is not installed
30
+ def initialize(message, button_type, button_id, options)
31
+ @input_type = button_type
32
+ @input_button_or_axis = button_id
33
+ @game_message = message
34
+ # TODO: There has to be a better, threadsafe way to do this.
35
+ # Maybe threadsafety isn't a huge concern here?
36
+ @game_state = Jemini::InputManager::loading_input_manager.game_state
37
+ end
38
+
39
+ def poll(raw_input)
40
+ @poll_result = poll_value(raw_input)
41
+ if post_canceled?
42
+ @cancel_post = false
43
+ nil
44
+ else
45
+ to_game_message(raw_input, @poll_result)
46
+ end
47
+ end
48
+
49
+ def cancel_post!
50
+ @cancel_post = true
51
+ end
52
+
53
+ def post_canceled?
54
+ @cancel_post
55
+ end
56
+
57
+ def key
58
+ "#{@device}_#{@input_type}_#{@input_button_or_axis}_#{@joystick_id || 'any'}"
59
+ end
60
+
61
+ def to_s
62
+ key
63
+ end
64
+
65
+ # eventually, raw_input will need to be wrapped
66
+ def to_game_message(raw_input, game_value)
67
+ game_message = InputMessage.new(@game_message, default_value || game_value)
68
+ game_message.player = @player
69
+ @input_callback.call(game_message, raw_input) unless @input_callback.nil?
70
+ game_message.to = message_to
71
+ game_message
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,5 @@
1
+ module Jemini
2
+ class InputMessage < Message
3
+ attr_accessor :player
4
+ end
5
+ end
@@ -0,0 +1,53 @@
1
+ require 'managers/input_support/input_listener'
2
+
3
+ module Jemini
4
+ class JoystickListener < Jemini::InputListener
5
+ def device
6
+ :joystick
7
+ end
8
+
9
+ def find_axis_id_by_axis_name(raw_input, axis_name)
10
+ (0..raw_input.get_axis_count(@joystick_id)).find {|axis_id| raw_input.get_axis_name(@joystick_id, axis_id) == axis_name}
11
+ end
12
+
13
+ def poll_value(raw_input)
14
+ if @joystick_id && @joystick_id >= raw_input.controller_count
15
+ cancel_post!
16
+ return
17
+ end
18
+
19
+ case @input_type
20
+ when :axis_update
21
+ @axis_id ||= find_axis_id_by_axis_name(raw_input, @input_button_or_axis)
22
+ axis_value = raw_input.get_axis_value(@joystick_id, @axis_id)
23
+ axis_value
24
+ when :pressed
25
+ if @joystick_id.nil?
26
+ result = (0..raw_input.controller_count).any? {|i| raw_input.is_button_pressed(@input_button_or_axis, i)} unless raw_input.controller_count.zero?
27
+ else
28
+ result = raw_input.is_button_pressed(@input_button_or_axis, @joystick_id)
29
+ end
30
+ pressed = !@key_down_on_last_poll && result
31
+ @key_down_on_last_poll = result
32
+ cancel_post! unless pressed
33
+ pressed
34
+ when :held
35
+ if @joystick_id.nil?
36
+ result = (0..raw_input.controller_count).any? {|i| raw_input.is_button_pressed(@input_button_or_axis, i)} unless raw_input.controller_count.zero?
37
+ else
38
+ result = raw_input.is_button_pressed(@input_button_or_axis, @joystick_id)
39
+ end
40
+ cancel_post! unless result
41
+ result
42
+ when :released
43
+ button_down = raw_input.is_button_pressed(@input_button_or_axis, @joystick_id)
44
+ result = (@key_down_on_last_poll && !button_down) ? true : false
45
+ @key_down_on_last_poll = button_down
46
+ cancel_post! unless result
47
+ result
48
+ else
49
+ cancel_post!
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,27 @@
1
+ require 'managers/input_support/input_listener'
2
+
3
+ module Jemini
4
+ class KeyListener < Jemini::InputListener
5
+ def device
6
+ :key
7
+ end
8
+
9
+ def poll_value(raw_input)
10
+ case @input_type
11
+ when :press
12
+ cancel_post! unless raw_input.is_key_pressed(@input_button_or_axis)
13
+ when :hold
14
+ cancel_post! unless raw_input.is_key_down(@input_button_or_axis)
15
+ when :release
16
+ key_down = raw_input.is_key_down(@input_button_or_axis)
17
+ result = (@key_down_on_last_poll && !key_down) ? true : false
18
+ @key_down_on_last_poll = key_down
19
+ cancel_post! unless result
20
+ else
21
+ cancel_post!
22
+ raise "Input type of #{@input_type.inspect} is not supported!"
23
+ end
24
+ @game_value unless post_canceled?
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,38 @@
1
+ require 'managers/input_support/input_listener'
2
+
3
+ module Jemini
4
+ class MouseListener < Jemini::InputListener
5
+ def device
6
+ :mouse
7
+ end
8
+
9
+ def poll_value(raw_input)
10
+ value = MouseValue.new
11
+ value.position = percent_on_screen(raw_input)
12
+ value.screen_position = Vector.new(raw_input.mouse_x, raw_input.mouse_y)
13
+ case @input_type
14
+ when :move, :axis_update
15
+
16
+ when :press
17
+ cancel_post! unless raw_input.mouse_pressed?(@input_button_or_axis)
18
+ when :hold
19
+ cancel_post! unless raw_input.mouse_button_down?(@input_button_or_axis)
20
+ when :release
21
+ button_down = raw_input.mouse_button_down?(@input_button_or_axis)
22
+ result = (@button_down_on_last_poll && !button_down)
23
+ @button_down_on_last_poll = button_down
24
+ cancel_post! unless result
25
+ end
26
+
27
+ value
28
+ end
29
+
30
+ def percent_on_screen(raw_input)
31
+ Vector.new(raw_input.mouse_x.to_f / game_state.screen_size.x.to_f, raw_input.mouse_y.to_f / game_state.screen_size.y.to_f)
32
+ end
33
+ end
34
+
35
+ class MouseValue
36
+ attr_accessor :position, :screen_position, :position_delta, :screen_position_delta
37
+ end
38
+ end
@@ -0,0 +1,20 @@
1
+ module Jemini
2
+ class SlickInputListener
3
+ java_import 'org.newdawn.slick.InputListener'
4
+ include InputListener
5
+
6
+ def initialize(state)
7
+ @state = state
8
+ end
9
+
10
+ def isAcceptingInput
11
+ #@state == GameState.active_state
12
+ true
13
+ end
14
+
15
+ def method_missing(method, *args)
16
+ return if (method == :inputEnded) || @state != GameState.active_state
17
+ @state.manager(:message_queue).post_message SlickInputMessage.new(method, args)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,11 @@
1
+ module Jemini
2
+ class SlickInputMessage < Message
3
+ attr_accessor :event_name, :data
4
+
5
+ def initialize(event_name, data)
6
+ self.name = :slick_input
7
+ @event_name = event_name
8
+ @data = data
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ module Jemini
2
+ class SlickInputTranslator
3
+ SLICK_INPUT_TYPE_TRANSLATION = {
4
+ :keyPressed => [:key, :pressed], # which key?
5
+ :keyReleased => [:key, :released],
6
+ :mouseMoved => [:mouse, :moved],
7
+ :mousePressed => [:mouse, :pressed], # which button?
8
+ :mouseReleased => [:mouse, :released],
9
+ :mouseClicked => [:mouse, :clicked],
10
+ :mouseWheelMoved => [:mouse, :wheel_moved],
11
+ :controllerLeftPressed => [:controller, :pressed]
12
+
13
+ }
14
+ end
15
+ end
@@ -0,0 +1,60 @@
1
+ require 'thread'
2
+ module Jemini
3
+
4
+ # Message object that is posted to the MessageQueue.
5
+ class Message
6
+ attr_accessor :name, :value, :delta, :to
7
+
8
+ def initialize(name, value, delta=nil, to=nil)
9
+ @name = name
10
+ @value = value
11
+ @delta = delta
12
+ @to = to
13
+ end
14
+ end
15
+
16
+ class MessageQueue < Jemini::GameObject
17
+ def load
18
+ @listeners = Hash.new {|h,k| h[k] = []}
19
+ @messages = Queue.new
20
+ end
21
+
22
+ def process_messages(delta)
23
+ until @messages.empty?
24
+ message = @messages.shift
25
+ message.delta = delta
26
+
27
+ @listeners[message.name].each do |listener|
28
+ begin
29
+ if message.to.nil?
30
+ listener[1].call(message)
31
+ else
32
+ listener[1].call(message) if listener[0].respond_to?(:handles_events_for?) && listener[0].handles_events_for?(message.to)
33
+ end
34
+ rescue Exception => e
35
+ # Replace this with a logger
36
+ $stderr << "Error in callback #{listener[1]} for key: #{listener[0]}\n#{e.class} - #{e.message}\n#{e.backtrace.join("\n")}"
37
+ java.lang.System.exit(1)
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ def post_message(message)
44
+ @messages << message
45
+ end
46
+
47
+ # Listeners are registered on a certain type of message. This type is arbitrary
48
+ # and can be any symbol. The second parameter is a key that is used to identify
49
+ # the callback when it is removed. The third parameter is the callback object
50
+ # which must be a proc. Alternatively, the second parameter may be omitted and a
51
+ # block passed in its place.
52
+ def add_listener(type, key, callback=nil, &block)
53
+ @listeners[type.to_sym] << [key, callback || block]
54
+ end
55
+
56
+ def remove_listener(type, key)
57
+ @listeners[type.to_sym].delete_if {|listener| listener.first == key}
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,41 @@
1
+ module Jemini
2
+
3
+ class NetworkManager < Jemini::GameObject
4
+
5
+ attr_accessor :socket
6
+
7
+ class Peer
8
+ attr_accessor :address, :port
9
+ def initialize(address, port)
10
+ @address, @port = address, port
11
+ end
12
+ end
13
+
14
+ has_behavior :HandlesEvents
15
+
16
+ #An array of all network peers.
17
+ attr_accessor :peers
18
+
19
+ def load
20
+ @peers = []
21
+ @socket = UDPSocket.new
22
+ end
23
+
24
+ # def unload
25
+ # end
26
+
27
+ #Add an address and port to the list of network peers.
28
+ def add_peer(address, port = 5364)
29
+ @peers << Peer.new(address, port)
30
+ end
31
+
32
+ #Send event to each registered peer.
33
+ def notify_peers(event)
34
+ @peers.each do |peer|
35
+ @socket.send(event, 0, peer.address, peer.port)
36
+ end
37
+ end
38
+
39
+ end
40
+
41
+ end