jemini 2009.10.27
Sign up to get free protection for your applications and to get access to all the features.
- data/README.txt +9 -0
- data/bin/jemini +26 -0
- data/lib/ibxm.jar +0 -0
- data/lib/jinput.jar +0 -0
- data/lib/jogg-0.0.7.jar +0 -0
- data/lib/jorbis-0.0.15.jar +0 -0
- data/lib/jruby-complete.jar +0 -0
- data/lib/lwjgl.jar +0 -0
- data/lib/lwjgl_util_applet.jar +0 -0
- data/lib/native_files/OpenAL32.dll +0 -0
- data/lib/native_files/jinput-dx8.dll +0 -0
- data/lib/native_files/jinput-dx8_64.dll +0 -0
- data/lib/native_files/jinput-raw.dll +0 -0
- data/lib/native_files/jinput-raw_64.dll +0 -0
- data/lib/native_files/jinput-wintab.dll +0 -0
- data/lib/native_files/libjinput-linux.so +0 -0
- data/lib/native_files/libjinput-linux64.so +0 -0
- data/lib/native_files/libjinput-osx.jnilib +0 -0
- data/lib/native_files/liblwjgl.jnilib +0 -0
- data/lib/native_files/liblwjgl.so +0 -0
- data/lib/native_files/liblwjgl64.so +0 -0
- data/lib/native_files/libopenal.so +0 -0
- data/lib/native_files/lwjgl.dll +0 -0
- data/lib/native_files/openal.dylib +0 -0
- data/lib/natives-linux.jar +0 -0
- data/lib/natives-mac.jar +0 -0
- data/lib/natives-win32.jar +0 -0
- data/lib/phys2d.jar +0 -0
- data/lib/slick.jar +0 -0
- data/package/jar/jemini.jar +0 -0
- data/src/behavior.rb +248 -0
- data/src/behavior_event.rb +23 -0
- data/src/behaviors/animated_image.rb +88 -0
- data/src/behaviors/audible.rb +16 -0
- data/src/behaviors/axis_stateful.rb +35 -0
- data/src/behaviors/bounding_box_collidable.rb +27 -0
- data/src/behaviors/cardinal_movable.rb +121 -0
- data/src/behaviors/clickable.rb +19 -0
- data/src/behaviors/countable.rb +32 -0
- data/src/behaviors/debug_physical.rb +43 -0
- data/src/behaviors/debug_tangible.rb +31 -0
- data/src/behaviors/drawable.rb +7 -0
- data/src/behaviors/drawable_image.rb +111 -0
- data/src/behaviors/drawable_line.rb +32 -0
- data/src/behaviors/drawable_shape.rb +48 -0
- data/src/behaviors/fading_image_trail_emittable.rb +32 -0
- data/src/behaviors/game_object_emittable.rb +13 -0
- data/src/behaviors/grid_bound.rb +108 -0
- data/src/behaviors/handles_events.rb +33 -0
- data/src/behaviors/inertial.rb +14 -0
- data/src/behaviors/magnetic.rb +34 -0
- data/src/behaviors/metered.rb +3 -0
- data/src/behaviors/movable.rb +81 -0
- data/src/behaviors/particle_emitter.rb +27 -0
- data/src/behaviors/physical.rb +384 -0
- data/src/behaviors/physical_cardinal_movable.rb +111 -0
- data/src/behaviors/physical_image.rb +45 -0
- data/src/behaviors/pointer.rb +30 -0
- data/src/behaviors/pressable.rb +17 -0
- data/src/behaviors/regional.rb +76 -0
- data/src/behaviors/rotates_to_point.rb +19 -0
- data/src/behaviors/spatial.rb +43 -0
- data/src/behaviors/stateful.rb +33 -0
- data/src/behaviors/taggable.rb +28 -0
- data/src/behaviors/tangible.rb +59 -0
- data/src/behaviors/timeable.rb +88 -0
- data/src/behaviors/top_down_vehicle.rb +42 -0
- data/src/behaviors/triangle_trail_emittable.rb +46 -0
- data/src/behaviors/unique.rb +0 -0
- data/src/behaviors/updates.rb +8 -0
- data/src/behaviors/updates_at_consistant_rate.rb +28 -0
- data/src/behaviors/vectored_movement.rb +48 -0
- data/src/behaviors/world_collidable.rb +9 -0
- data/src/color.rb +70 -0
- data/src/events/grid_changed_event.rb +8 -0
- data/src/events/physical_message.rb +9 -0
- data/src/events/tangible_collision_event.rb +8 -0
- data/src/file_system.rb +17 -0
- data/src/game.rb +110 -0
- data/src/game_object.rb +176 -0
- data/src/game_objects/background.rb +10 -0
- data/src/game_objects/fading_image.rb +23 -0
- data/src/game_objects/tangible_object.rb +4 -0
- data/src/game_objects/text.rb +71 -0
- data/src/game_objects/triangle_trail.rb +85 -0
- data/src/game_state.rb +164 -0
- data/src/inflector.rb +68 -0
- data/src/input_helpers/joystick_dead_zone_filter.rb +9 -0
- data/src/jemini.rb +31 -0
- data/src/jemini_version.rb +4 -0
- data/src/listenable_mixin.rb +15 -0
- data/src/logger_mixin.rb +11 -0
- data/src/managers/basic_game_object_manager.rb +95 -0
- data/src/managers/basic_physics_manager.rb +95 -0
- data/src/managers/basic_render_manager.rb +49 -0
- data/src/managers/basic_tile_manager.rb +3 -0
- data/src/managers/basic_update_manager.rb +30 -0
- data/src/managers/diagnostic/diagnostic_input_manager.rb +0 -0
- data/src/managers/input_manager.rb +161 -0
- data/src/managers/input_support/input_binding.rb +77 -0
- data/src/managers/input_support/input_builder.rb +44 -0
- data/src/managers/input_support/input_listener.rb +74 -0
- data/src/managers/input_support/input_message.rb +5 -0
- data/src/managers/input_support/joystick_listener.rb +53 -0
- data/src/managers/input_support/key_listener.rb +27 -0
- data/src/managers/input_support/mouse_listener.rb +38 -0
- data/src/managers/input_support/slick_input_listener.rb +20 -0
- data/src/managers/input_support/slick_input_message.rb +11 -0
- data/src/managers/input_support/slick_input_translator.rb +15 -0
- data/src/managers/message_queue.rb +60 -0
- data/src/managers/network_manager.rb +41 -0
- data/src/managers/render_support/hardware_cursor.rb +13 -0
- data/src/managers/resource_manager.rb +167 -0
- data/src/managers/sound_manager.rb +47 -0
- data/src/managers/tag_manager.rb +47 -0
- data/src/managers/tangible_manager.rb +36 -0
- data/src/math.rb +23 -0
- data/src/org/rubyforge/rawr/Main.java +67 -0
- data/src/platform.rb +28 -0
- data/src/proc_enhancement.rb +5 -0
- data/src/project_generator.rb +138 -0
- data/src/resource.rb +31 -0
- data/src/spline.rb +13 -0
- data/src/states/input_diagnostic_state.rb +53 -0
- data/src/vector.rb +143 -0
- data/test/test_state.rb +3 -0
- 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,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,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
|