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.
- data/bin/gemini +18 -0
- data/build_configuration.rb +24 -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-raw.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/gemini.jar +0 -0
- data/src/base_state.rb +112 -0
- data/src/behavior.rb +230 -0
- data/src/behavior_event.rb +23 -0
- data/src/behaviors.txt +5 -0
- data/src/behaviors/animated_sprite.rb +51 -0
- data/src/behaviors/audible.rb +11 -0
- data/src/behaviors/axis_stateful.rb +33 -0
- data/src/behaviors/big_sprite.rb +56 -0
- data/src/behaviors/bounding_box_collidable.rb +25 -0
- data/src/behaviors/camera_anchored_drawable.rb +20 -0
- data/src/behaviors/cardinal_movable.rb +114 -0
- data/src/behaviors/clickable.rb +18 -0
- data/src/behaviors/countable.rb +31 -0
- data/src/behaviors/debug_physical.rb +31 -0
- data/src/behaviors/debug_tangible.rb +30 -0
- data/src/behaviors/drawable.rb +6 -0
- data/src/behaviors/drawable_shape.rb +43 -0
- data/src/behaviors/fading_image_trail_emittable.rb +28 -0
- data/src/behaviors/game_object_emittable.rb +12 -0
- data/src/behaviors/gravity_source.rb +21 -0
- data/src/behaviors/inertial.rb +11 -0
- data/src/behaviors/movable2d.rb +9 -0
- data/src/behaviors/multi_animated_sprite.rb +22 -0
- data/src/behaviors/physical.rb +348 -0
- data/src/behaviors/physical_cardinal_movable.rb +110 -0
- data/src/behaviors/physical_sprite.rb +29 -0
- data/src/behaviors/platformer_controllable.rb +144 -0
- data/src/behaviors/pointer.rb +28 -0
- data/src/behaviors/pressable.rb +13 -0
- data/src/behaviors/receives_events.rb +21 -0
- data/src/behaviors/regional.rb +71 -0
- data/src/behaviors/rotates_to_point.rb +18 -0
- data/src/behaviors/spatial.rb +41 -0
- data/src/behaviors/spline_stretchable_sprite.rb +45 -0
- data/src/behaviors/sprite.rb +99 -0
- data/src/behaviors/stateful.rb +31 -0
- data/src/behaviors/taggable.rb +27 -0
- data/src/behaviors/tangible.rb +51 -0
- data/src/behaviors/timeable.rb +79 -0
- data/src/behaviors/top_down_vehicle.rb +41 -0
- data/src/behaviors/triangle_trail_emittable.rb +41 -0
- data/src/behaviors/updates.rb +10 -0
- data/src/behaviors/updates_at_consistant_rate.rb +27 -0
- data/src/behaviors/vectored_movement.rb +47 -0
- data/src/behaviors/world_collidable.rb +8 -0
- data/src/color.rb +70 -0
- data/src/game_object.rb +174 -0
- data/src/game_objects/background.rb +9 -0
- data/src/game_objects/fading_image.rb +23 -0
- data/src/game_objects/icon_strip_counter_display.rb +58 -0
- data/src/game_objects/static_sprite.rb +18 -0
- data/src/game_objects/tangible_object.rb +4 -0
- data/src/game_objects/text.rb +59 -0
- data/src/game_objects/triangle_trail.rb +85 -0
- data/src/gemini.rb +110 -0
- data/src/gemini_version.rb +3 -0
- data/src/inflector.rb +68 -0
- data/src/input_helpers/joystick_dead_zone_filter.rb +9 -0
- data/src/listenable_mixin.rb +15 -0
- data/src/managers/basic_game_object_manager.rb +81 -0
- data/src/managers/basic_physics_manager.rb +97 -0
- data/src/managers/basic_render_manager.rb +48 -0
- data/src/managers/basic_tangible_manager.rb +33 -0
- data/src/managers/basic_update_manager.rb +27 -0
- data/src/managers/diagnostic/diagnostic_input_manager.rb +0 -0
- data/src/managers/input_manager.rb +229 -0
- data/src/managers/input_support/input_mapping.rb +126 -0
- data/src/managers/input_support/input_message.rb +5 -0
- data/src/managers/input_support/slick_input_listener.rb +19 -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 +54 -0
- data/src/managers/scrolling_render_manager.rb +44 -0
- data/src/managers/sound_manager.rb +60 -0
- data/src/managers/tag_manager.rb +43 -0
- data/src/math.rb +13 -0
- data/src/music.rb +14 -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 +122 -0
- data/src/skeleton.txt +10 -0
- data/src/spline.rb +13 -0
- data/src/states/input_diagnostic_state.rb +53 -0
- data/src/vector.rb +99 -0
- data/test/test_state.rb +3 -0
- metadata +181 -0
@@ -0,0 +1,45 @@
|
|
1
|
+
class SplineStretchableSprite < Gemini::Behavior
|
2
|
+
INDEPENDENT_MODE = :independent
|
3
|
+
MERGED_MODE = :merged
|
4
|
+
depends_on_kind_of :Sprite
|
5
|
+
depends_on :UpdatesAtConsistantRate #TODO: Make Updates coexist with this behavior
|
6
|
+
|
7
|
+
def load
|
8
|
+
@original_image = @target.image
|
9
|
+
@target.on_update do
|
10
|
+
# @target.width = @original_width
|
11
|
+
# @target.height = @original_height
|
12
|
+
old_width = @target.width
|
13
|
+
old_height = @target.height
|
14
|
+
@target.image = @original_image
|
15
|
+
if INDEPENDENT_MODE == @mode
|
16
|
+
@target.image_scaling(@spline_x.succ, @spline_y.succ)
|
17
|
+
else
|
18
|
+
@target.image_scaling(@spline.succ)
|
19
|
+
end
|
20
|
+
|
21
|
+
new_width = @target.width
|
22
|
+
new_height = @target.height
|
23
|
+
#recenter_position(old_width, old_height, new_width, new_height) unless @target.kind_of? TangibleSprite
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def set_stretch_splines(spline_x, spline_y = nil)
|
28
|
+
@original_image = @target.image
|
29
|
+
unless spline_y.nil?
|
30
|
+
@spline_x = spline_x
|
31
|
+
@spline_y = spline_y
|
32
|
+
@mode = INDEPENDENT_MODE
|
33
|
+
else
|
34
|
+
@spline = spline_x
|
35
|
+
@mode = MERGED_MODE
|
36
|
+
end
|
37
|
+
end
|
38
|
+
alias_method :set_stretch_spline, :set_stretch_splines
|
39
|
+
|
40
|
+
private
|
41
|
+
def recenter_position(old_width, old_height, new_width, new_height)
|
42
|
+
@target.x = @target.x + (old_width - new_width) / 2
|
43
|
+
@target.y = @target.y + (old_height - new_height) / 2
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'behaviors/drawable'
|
2
|
+
|
3
|
+
# WARNING: Using Slick's image for rotation can cause some odd quirks with it
|
4
|
+
# not quite rotating correctly (especially noticable around 180 degress).
|
5
|
+
# @rotation stands alone for this reason, instead of using Slick's rotation
|
6
|
+
class Sprite < Drawable
|
7
|
+
include_class 'org.newdawn.slick.Image'
|
8
|
+
depends_on :Spatial
|
9
|
+
attr_accessor :image, :color, :texture_coords, :image_size
|
10
|
+
alias_method :set_image_size, :image_size=
|
11
|
+
wrap_with_callbacks :draw
|
12
|
+
|
13
|
+
def load
|
14
|
+
@color = Color.new(1.0, 1.0, 1.0, 1.0)
|
15
|
+
@texture_coords = [Vector.new(0.0, 0.0), Vector.new(1.0, 1.0)]
|
16
|
+
@rotation = 0.0
|
17
|
+
end
|
18
|
+
|
19
|
+
def image=(sprite_name)
|
20
|
+
if sprite_name.kind_of? Image
|
21
|
+
@image = sprite_name
|
22
|
+
else
|
23
|
+
@image = Image.new("data/#{sprite_name}")
|
24
|
+
end
|
25
|
+
set_image_size(Vector.new(@image.width, @image.height))
|
26
|
+
end
|
27
|
+
alias_method :set_image, :image=
|
28
|
+
|
29
|
+
def color=(color)
|
30
|
+
@color = color
|
31
|
+
end
|
32
|
+
alias_method :set_color, :color=
|
33
|
+
|
34
|
+
#TODO: Take vectors for first args as well
|
35
|
+
def image_scaling(x_scale, y_scale = nil)
|
36
|
+
y_scale = x_scale if y_scale.nil?
|
37
|
+
set_image @image.get_scaled_copy(x_scale.to_f * image_size.x, y_scale.to_f * image_size.y)
|
38
|
+
end
|
39
|
+
|
40
|
+
#TODO: Take vectors for first args as well
|
41
|
+
def scale_image_from_original(x_scale, y_scale = nil)
|
42
|
+
y_scale = x_scale if y_scale.nil?
|
43
|
+
@original_image = @image.copy if @original_image.nil?
|
44
|
+
set_image @original_image.get_scaled_copy(x_scale.to_f * @original_image.width, y_scale.to_f * @original_image.height)
|
45
|
+
end
|
46
|
+
|
47
|
+
def image_rotation
|
48
|
+
@rotation
|
49
|
+
end
|
50
|
+
|
51
|
+
def image_rotation=(rotation)
|
52
|
+
@rotation = rotation
|
53
|
+
rescue => e
|
54
|
+
puts "rotation error for: #{@target}"
|
55
|
+
end
|
56
|
+
alias_method :set_image_rotation, :image_rotation=
|
57
|
+
|
58
|
+
def add_rotation(rotation)
|
59
|
+
@rotation += rotation
|
60
|
+
end
|
61
|
+
|
62
|
+
def flip_horizontally
|
63
|
+
@texture_coords[1].x, @texture_coords[0].x = @texture_coords[0].x, @texture_coords[1].x
|
64
|
+
end
|
65
|
+
|
66
|
+
def flip_vertically
|
67
|
+
@texture_coords[1].y, @texture_coords[0].y = @texture_coords[0].y, @texture_coords[1].y
|
68
|
+
end
|
69
|
+
|
70
|
+
def top_left_position
|
71
|
+
#Vector.new(center_position.x - image_size.x / 2.0, center_position.y - image_size.y / 2.0)
|
72
|
+
Vector.new(@target.x - image_size.x / 2.0, @target.y - image_size.y / 2.0)
|
73
|
+
end
|
74
|
+
|
75
|
+
def move_by_top_left(move_x_or_vector, move_y = nil)
|
76
|
+
half_width = image_size.x / 2.0
|
77
|
+
half_height = image_size.y / 2.0
|
78
|
+
if move_y.nil?
|
79
|
+
@target.move(move_x_or_vector.x + half_width, move_x_or_vector.y + half_height)
|
80
|
+
else
|
81
|
+
@target.move(move_x_or_vector + half_width, move_y + half_height)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def draw(graphics)
|
86
|
+
return if @image.nil? || @image_size.nil?
|
87
|
+
half_width = image_size.x / 2.0
|
88
|
+
half_height = image_size.y / 2.0
|
89
|
+
center_x = @target.x - half_width
|
90
|
+
center_y = @target.y - half_height
|
91
|
+
unless 0 == @rotation
|
92
|
+
graphics.rotate @target.x, @target.y, @rotation
|
93
|
+
end
|
94
|
+
@image.draw(center_x, center_y, @target.x + half_width, @target.y + half_height,
|
95
|
+
@texture_coords[0].x * image_size.x, @texture_coords[0].y * image_size.y, @texture_coords[1].x * image_size.x, @texture_coords[1].y * image_size.y,
|
96
|
+
@color.native_color)
|
97
|
+
graphics.reset_transform
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# Notes from Logan:
|
2
|
+
# I started on this behavior, and realized what I needed was multiple axises of states for my behavior
|
3
|
+
# that I wanted to use Stateful in. This behavior is simple, and seems like it would be useful for some cases.
|
4
|
+
# Thus, the behavior remains, but it is not tested or used at the time of this comment.
|
5
|
+
class Stateful < Gemini::Behavior
|
6
|
+
class StateTransferEvent
|
7
|
+
attr_accessor :before_state, :after_state
|
8
|
+
def initialize(before_state, after_state)
|
9
|
+
@before_state = before_state
|
10
|
+
@after_state = after_state
|
11
|
+
end
|
12
|
+
end
|
13
|
+
attr_accessor :default_state, :current_state
|
14
|
+
wrap_with_callbacks :transfer_state
|
15
|
+
|
16
|
+
def load
|
17
|
+
@state_transitions = {}
|
18
|
+
@target.enable_listeners_for :state_transfer_accepted
|
19
|
+
@target.enable_listeners_for :state_transfer_rejected
|
20
|
+
end
|
21
|
+
|
22
|
+
def transfer_state(state)
|
23
|
+
event = StateTransferEvent.new(@current_state, state)
|
24
|
+
if @state_transitions[@current_state].include? state
|
25
|
+
@current_state = state
|
26
|
+
notify :state_transfer_accepted, event
|
27
|
+
else
|
28
|
+
notify :state_transfer_rejected, event
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class Taggable < Gemini::Behavior
|
2
|
+
|
3
|
+
def load
|
4
|
+
@tags = []
|
5
|
+
@target.enable_listeners_for :tag_added, :tag_removed
|
6
|
+
end
|
7
|
+
|
8
|
+
def add_tag(*tags)
|
9
|
+
new_tags = tags - @tags
|
10
|
+
@tags.concat new_tags
|
11
|
+
new_tags.each { |tag| @target.notify :tag_added, tag }
|
12
|
+
end
|
13
|
+
|
14
|
+
def remove_tag(*tags)
|
15
|
+
tags_to_remove = @tags & tags
|
16
|
+
@tags -= tags_to_remove
|
17
|
+
tags_to_remove.each {|tag| @target.notify :tag_removed, tag}
|
18
|
+
end
|
19
|
+
|
20
|
+
def has_tag?(*tags)
|
21
|
+
tags.any? {|tag| @tags.member?(tag) }
|
22
|
+
end
|
23
|
+
|
24
|
+
def tags
|
25
|
+
@tags.clone
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
class TangibleBox
|
2
|
+
attr_accessor :size
|
3
|
+
def get_points(top_left_position, rotation)
|
4
|
+
top_left = top_left_position
|
5
|
+
top_right = Vector.new(top_left_position.x + size.x, top_left_position.y)
|
6
|
+
bottom_left = Vector.new(top_left_position.x, top_left_position.y + size.y)
|
7
|
+
bottom_right = Vector.new(top_left_position.x + size.x, top_left_position.y + size.y)
|
8
|
+
[top_left, top_right, bottom_right, bottom_left]
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Tangible < Gemini::Behavior
|
13
|
+
depends_on :Spatial
|
14
|
+
attr_reader :tangible_shape
|
15
|
+
|
16
|
+
def load
|
17
|
+
@target.enable_listeners_for :tangible_collision
|
18
|
+
end
|
19
|
+
|
20
|
+
def tangible_debug_mode=(mode)
|
21
|
+
if mode
|
22
|
+
@target.add_behavior :DebugTangible
|
23
|
+
else
|
24
|
+
@target.remove_behavior :DebugTangible
|
25
|
+
end
|
26
|
+
end
|
27
|
+
alias_method :set_tangible_debug_mode, :tangible_debug_mode=
|
28
|
+
|
29
|
+
def set_tangible_shape(name, *args)
|
30
|
+
@tangible_shape = case name
|
31
|
+
when :Box
|
32
|
+
box = TangibleBox.new
|
33
|
+
if args.size == 1
|
34
|
+
box.size = args[0]
|
35
|
+
else
|
36
|
+
box.size = Vector.new(args[0], args[1])
|
37
|
+
end
|
38
|
+
box
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def tangibly_collides_with?(other_tangible)
|
43
|
+
#TODO: top_left isn't on spatial...
|
44
|
+
other_shape = other_tangible.tangible_shape
|
45
|
+
|
46
|
+
((@target.x <= other_tangible.x && (@target.x + @tangible_shape.size.x) >= other_tangible.x) ||
|
47
|
+
(@target.x >= other_tangible.x && @target.x <= (other_tangible.x + other_shape.size.x))) &&
|
48
|
+
((@target.y <= other_tangible.y && (@target.y + @tangible_shape.size.y) >= other_tangible.y) ||
|
49
|
+
(@target.y >= other_tangible.y && @target.y <= (other_tangible.y + other_shape.size.y)))
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
class Timeable < Gemini::Behavior
|
2
|
+
depends_on :Updates
|
3
|
+
|
4
|
+
def load
|
5
|
+
@target.enable_listeners_for :timer_tick, :countdown_complete
|
6
|
+
@timers = {}
|
7
|
+
@target.on_update do |delta|
|
8
|
+
update_timers delta
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def add_countdown(name, seconds, notify_frequency = nil)
|
13
|
+
@timers[name] = Timer.new(name, Timer::COUNTDOWN, seconds, notify_frequency) {|timer| @target.notify :timer_tick, timer }
|
14
|
+
end
|
15
|
+
|
16
|
+
def add_countup(name, seconds, notify_frequency = nil)
|
17
|
+
@timers[name] = Timer.new(name, Timer::COUNTUP, seconds, notify_frequency) {|timer| @target.notify :timer_tick, timer }
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
def update_timers(delta)
|
22
|
+
@timers.each do |name, timer|
|
23
|
+
timer.apply_delta delta
|
24
|
+
if timer.countdown_complete?
|
25
|
+
@target.notify :countdown_complete, name
|
26
|
+
end
|
27
|
+
end
|
28
|
+
# in order to keep from mutating the array while we iterate, handle separately.
|
29
|
+
@timers.delete_if {|name, timer| timer.countdown_complete? }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class Timer
|
34
|
+
COUNTDOWN = :countdown
|
35
|
+
COUNTUP = :countup
|
36
|
+
def initialize(name, direction, seconds, notify_frequency, ¬ify_callback)
|
37
|
+
@name = name
|
38
|
+
@direction = direction
|
39
|
+
@milliseconds = seconds * 1000.0
|
40
|
+
@notify_frequency = notify_frequency * 1000.0 if notify_frequency
|
41
|
+
@notify_callback = notify_callback unless notify_frequency.nil?
|
42
|
+
@current_milliseconds = 0
|
43
|
+
@milliseconds_since_last_notify = 0
|
44
|
+
end
|
45
|
+
|
46
|
+
def apply_delta(delta_in_milliseconds)
|
47
|
+
return if @countdown_complete
|
48
|
+
|
49
|
+
@current_milliseconds += delta_in_milliseconds
|
50
|
+
@milliseconds_since_last_notify += delta_in_milliseconds
|
51
|
+
|
52
|
+
if @notify_callback && @notify_frequency && (@milliseconds_since_last_notify >= @notify_frequency)
|
53
|
+
@notify_callback.call(self)
|
54
|
+
@milliseconds_since_last_notify = 0
|
55
|
+
end
|
56
|
+
@countdown_complete = true if (COUNTDOWN == @direction) && (@current_milliseconds >= @milliseconds)
|
57
|
+
end
|
58
|
+
|
59
|
+
def reset
|
60
|
+
@current_milliseconds = 0
|
61
|
+
@countdown_complete = false
|
62
|
+
end
|
63
|
+
|
64
|
+
def ticks_elapsed
|
65
|
+
(@current_milliseconds / (@notify_frequency)).round
|
66
|
+
end
|
67
|
+
|
68
|
+
def ticks_left
|
69
|
+
((@milliseconds - @current_milliseconds) / (@notify_frequency)).round
|
70
|
+
end
|
71
|
+
|
72
|
+
def percent_complete
|
73
|
+
@current_milliseconds / @milliseconds
|
74
|
+
end
|
75
|
+
|
76
|
+
def countdown_complete?
|
77
|
+
@countdown_complete
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class TopDownVehicle < Gemini::Behavior
|
2
|
+
attr_accessor :minimum_speed_to_turn
|
3
|
+
alias_method :set_minimum_speed_to_turn, :minimum_speed_to_turn=
|
4
|
+
|
5
|
+
depends_on :VectoredMovement
|
6
|
+
|
7
|
+
def load
|
8
|
+
@vm_behavior = @target.send(:instance_variable_get, :@__behaviors)[:VectoredMovement]
|
9
|
+
@target.set_damping 0.1
|
10
|
+
@target.set_angular_damping 0.1
|
11
|
+
@minimum_speed_to_turn = 2.5
|
12
|
+
@vectored_movement_turning = false
|
13
|
+
|
14
|
+
#TODO: Replace this with a spline method that determines how far to turn based on the spline
|
15
|
+
@target.on_update do
|
16
|
+
if @turning && !@vectored_movement_turning && (@target.velocity.x.abs + @target.velocity.y.abs) > @minimum_speed_to_turn
|
17
|
+
@at_beginning_of_turn.call
|
18
|
+
@vectored_movement_turning = true
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def begin_acceleration(message)
|
24
|
+
@vm_behavior.begin_acceleration(message)
|
25
|
+
end
|
26
|
+
|
27
|
+
def end_acceleration(message)
|
28
|
+
@vm_behavior.end_acceleration(message)
|
29
|
+
end
|
30
|
+
|
31
|
+
def begin_turn(message)
|
32
|
+
@turning = true
|
33
|
+
@at_beginning_of_turn = Proc.new { @vm_behavior.begin_turn(message) }
|
34
|
+
end
|
35
|
+
|
36
|
+
def end_turn(message)
|
37
|
+
@turning = false
|
38
|
+
@vm_behavior.end_turn(message)
|
39
|
+
@vectored_movement_turning = false
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'behaviors/drawable'
|
2
|
+
|
3
|
+
class TriangleTrailEmittable < Gemini::Behavior
|
4
|
+
#depends_on :Movable2d
|
5
|
+
depends_on :Updates
|
6
|
+
depends_on_kind_of :Spatial
|
7
|
+
|
8
|
+
def load
|
9
|
+
@emitter = @target.game_state.create :TriangleTrail
|
10
|
+
@emitter_offset = [0,0]
|
11
|
+
|
12
|
+
|
13
|
+
@target.on_update do
|
14
|
+
@emitter.move(@emitter_offset[0] + @target.x, @emitter_offset[1] + @target.y)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def unload
|
19
|
+
@target.game_state.remove @emitter
|
20
|
+
end
|
21
|
+
|
22
|
+
def alpha
|
23
|
+
@emitter.alpha
|
24
|
+
end
|
25
|
+
|
26
|
+
def alpha=(alpha)
|
27
|
+
@emitter.alpha = alpha
|
28
|
+
end
|
29
|
+
|
30
|
+
def emit_triangle_trail_from_offset(offset)
|
31
|
+
@emitter_offset = offset
|
32
|
+
end
|
33
|
+
|
34
|
+
def emit_triangle_trail_with_radius(radius)
|
35
|
+
@emitter.radius = radius
|
36
|
+
end
|
37
|
+
|
38
|
+
def layer=(layer_name)
|
39
|
+
@target.game_state.manager(:game_object).move_game_object_to_layer(@emitter, layer_name)
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class UpdatesAtConsistantRate < Gemini::Behavior
|
2
|
+
attr_accessor :updates_per_second
|
3
|
+
|
4
|
+
def load
|
5
|
+
@update_delay = 0
|
6
|
+
@time_since_last_update = 0
|
7
|
+
@target.enable_listeners_for :update
|
8
|
+
self.updates_per_second = 30
|
9
|
+
end
|
10
|
+
|
11
|
+
def updates_per_second=(count)
|
12
|
+
if 0 == count
|
13
|
+
@update_delay = 0
|
14
|
+
else
|
15
|
+
@update_delay = 1000 / count
|
16
|
+
end
|
17
|
+
@updates_per_second = count
|
18
|
+
end
|
19
|
+
|
20
|
+
def update(delta_in_milliseconds)
|
21
|
+
@time_since_last_update += delta_in_milliseconds
|
22
|
+
if @time_since_last_update > @update_delay
|
23
|
+
@time_since_last_update -= @update_delay
|
24
|
+
notify :update
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|