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
data/README.txt
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
Jemini 2009.10.27
|
2
|
+
|
3
|
+
== Description
|
4
|
+
|
5
|
+
Jemini is a game library designed to allow creation of reusable features. How many times has someone implemented the aiming on a first person shooter, or a minimap on a real time strategy? Jemini comes packaged with lots of behaviors out of the box, with the ability to easily author more. Jemini uses Phys2D and Slick for physics and graphics, with 3D on the roadmap.
|
6
|
+
|
7
|
+
== License
|
8
|
+
|
9
|
+
Jemini is released under the BSD license. See the COPYING file for the full license.
|
data/bin/jemini
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
#!/usr/bin/env jruby
|
2
|
+
$LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), '..', 'src'))
|
3
|
+
require 'project_generator'
|
4
|
+
|
5
|
+
begin
|
6
|
+
rawr_install_args = ''
|
7
|
+
project_dir = nil
|
8
|
+
until ARGV.empty?
|
9
|
+
arg = ARGV.shift
|
10
|
+
case arg
|
11
|
+
when /-RI(.+)/
|
12
|
+
rawr_install_args << $1 + ' '
|
13
|
+
else
|
14
|
+
project_dir = arg
|
15
|
+
end
|
16
|
+
end
|
17
|
+
raise "No project dir provided" if project_dir.nil?
|
18
|
+
generator = Jemini::ProjectGenerator.new(:project_dir => project_dir, :rawr_install => rawr_install_args)
|
19
|
+
generator.generate_project
|
20
|
+
rescue => exception
|
21
|
+
abort [
|
22
|
+
"Usage: jemini [-RI--no-download] <dir_name>",
|
23
|
+
"Error: #{exception.message}",
|
24
|
+
exception.backtrace
|
25
|
+
].join("\n")
|
26
|
+
end
|
data/lib/ibxm.jar
ADDED
Binary file
|
data/lib/jinput.jar
ADDED
Binary file
|
data/lib/jogg-0.0.7.jar
ADDED
Binary file
|
Binary file
|
Binary file
|
data/lib/lwjgl.jar
ADDED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/lib/natives-mac.jar
ADDED
Binary file
|
Binary file
|
data/lib/phys2d.jar
ADDED
Binary file
|
data/lib/slick.jar
ADDED
Binary file
|
Binary file
|
data/src/behavior.rb
ADDED
@@ -0,0 +1,248 @@
|
|
1
|
+
require 'listenable_mixin'
|
2
|
+
|
3
|
+
module Jemini
|
4
|
+
class MethodExistsError < Exception; end
|
5
|
+
class InvalidWrapWithCallbacksError < Exception; end
|
6
|
+
|
7
|
+
class ValueChangedEvent
|
8
|
+
attr_accessor :previous_value, :desired_value
|
9
|
+
|
10
|
+
def initialize(previous_value, desired_value)
|
11
|
+
@previous_value, @desired_value = previous_value, desired_value
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class Behavior
|
16
|
+
include ListenableMixin
|
17
|
+
attr_reader :reference_count
|
18
|
+
#The GameObject this Behavior belongs to.
|
19
|
+
attr_reader :game_object
|
20
|
+
#The GameState of the GameObject this Behavior belongs to.
|
21
|
+
def game_state; @game_object.game_state; end
|
22
|
+
|
23
|
+
def self.method_added(method)
|
24
|
+
if !callback_methods_to_wrap.member?(method) || callback_methods_wrapped.member?(method)
|
25
|
+
super
|
26
|
+
return
|
27
|
+
end
|
28
|
+
|
29
|
+
callback_methods_wrapped << method
|
30
|
+
alias_method :"wrapped_#{method}", method
|
31
|
+
arity = instance_method(:"wrapped_#{method}").arity
|
32
|
+
if arity.abs > 0
|
33
|
+
args = (1..arity.abs).inject([]){|args, i| args << "arg#{i}" }
|
34
|
+
args[-1].insert(0,"*") if arity < 0
|
35
|
+
end
|
36
|
+
if match = /^(.*)=$/.match(method.to_s)
|
37
|
+
method_name = match[1]
|
38
|
+
code = <<-ENDL
|
39
|
+
def #{method}(#{args})
|
40
|
+
raise Jemini::InvalidWrapWithCallbacksError.new("Cannot wrap #{method} with callbacks without \\"#{method_name}\\"") unless respond_to?(:#{method_name})
|
41
|
+
event = ValueChangedEvent.new(@game_object.#{method_name}, #{args})
|
42
|
+
callback_abort = CallbackStatus.new
|
43
|
+
@game_object.notify :before_#{method_name}_changes, event
|
44
|
+
if callback_abort.continue?
|
45
|
+
self.wrapped_#{method} #{args}
|
46
|
+
@game_object.notify :after_#{method_name}_changes, event
|
47
|
+
end
|
48
|
+
end
|
49
|
+
ENDL
|
50
|
+
wrapped_methods << "before_#{method_name}_changes"
|
51
|
+
wrapped_methods << "after_#{method_name}_changes"
|
52
|
+
else
|
53
|
+
code = <<-ENDL
|
54
|
+
def #{method}(#{(args.join(",") + ",") if args} &block)
|
55
|
+
callback_abort = CallbackStatus.new
|
56
|
+
@game_object.notify :before_#{method}, callback_abort
|
57
|
+
if callback_abort.continue?
|
58
|
+
self.wrapped_#{method}(#{(args.join(",") + ",") if args} &block)
|
59
|
+
@game_object.notify :after_#{method}
|
60
|
+
end
|
61
|
+
end
|
62
|
+
ENDL
|
63
|
+
wrapped_methods << "before_#{method}"
|
64
|
+
wrapped_methods << "after_#{method}"
|
65
|
+
end
|
66
|
+
begin
|
67
|
+
self.class_eval(code, __FILE__, __LINE__)
|
68
|
+
rescue Exception => exception
|
69
|
+
STDERR.puts "Failed to evaluate code:", code
|
70
|
+
raise
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
protected
|
75
|
+
|
76
|
+
@@listener_names = Hash.new {|h,k| h[k] = []}
|
77
|
+
def self.listen_for(*listener_names)
|
78
|
+
@@listener_names[self].concat listener_names
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.listener_names
|
82
|
+
@@listener_names[self]
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.depends_on(behavior)
|
86
|
+
require "behaviors/#{behavior.underscore}"
|
87
|
+
add_dependency(behavior)
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.depends_on_kind_of(behavior)
|
91
|
+
add_kind_of_dependency(behavior)
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.wrap_with_callbacks(*args)
|
95
|
+
@@callback_methods_to_wrap[self].concat args
|
96
|
+
end
|
97
|
+
|
98
|
+
@@callback_methods_to_wrap = Hash.new {|h,k| h[k] = []}
|
99
|
+
def self.callback_methods_to_wrap
|
100
|
+
@@callback_methods_to_wrap[self]
|
101
|
+
end
|
102
|
+
|
103
|
+
@@callback_methods_wrapped = Hash.new {|h,k| h[k] = []}
|
104
|
+
def self.callback_methods_wrapped
|
105
|
+
@@callback_methods_wrapped[self]
|
106
|
+
end
|
107
|
+
|
108
|
+
@@wrapped_methods = Hash.new {|h,k| h[k] = []}
|
109
|
+
def self.wrapped_methods
|
110
|
+
@@wrapped_methods[self]
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
|
115
|
+
def self.new(*args)
|
116
|
+
super
|
117
|
+
end
|
118
|
+
|
119
|
+
def self.declared_method_list
|
120
|
+
public_instance_methods - Behavior.public_instance_methods
|
121
|
+
end
|
122
|
+
|
123
|
+
@@behavior_dependencies = Hash.new{|h,k| h[k] = []}
|
124
|
+
def self.dependencies
|
125
|
+
@@behavior_dependencies[self]
|
126
|
+
end
|
127
|
+
|
128
|
+
def self.add_dependency(behavior)
|
129
|
+
@@behavior_dependencies[self] << behavior
|
130
|
+
end
|
131
|
+
|
132
|
+
@@kind_of_behavior_dependencies = Hash.new{|h,k| h[k] = []}
|
133
|
+
def self.kind_of_dependencies
|
134
|
+
@@kind_of_behavior_dependencies[self]
|
135
|
+
end
|
136
|
+
|
137
|
+
def self.add_kind_of_dependency(behavior)
|
138
|
+
@@kind_of_behavior_dependencies[self] << behavior
|
139
|
+
end
|
140
|
+
|
141
|
+
def initialize(game_object)
|
142
|
+
@game_object = game_object
|
143
|
+
@dependant_behaviors = []
|
144
|
+
@reference_count = 0
|
145
|
+
|
146
|
+
initialize_dependant_behaviors
|
147
|
+
|
148
|
+
#TODO: Move this to GameObject
|
149
|
+
behavior_list = @game_object.send(:instance_variable_get, :@__behaviors)
|
150
|
+
return unless behavior_list[self.class.name.to_sym].nil?
|
151
|
+
behavior_list[self.class.name.to_sym] = self
|
152
|
+
|
153
|
+
initialize_declared_methods
|
154
|
+
initialize_listeners
|
155
|
+
|
156
|
+
load
|
157
|
+
end
|
158
|
+
|
159
|
+
def initialize_declared_methods
|
160
|
+
self.class.declared_method_list.each do |method|
|
161
|
+
raise MethodExistsError.new("Error while adding the behavior #{self.class}. The method #{method} already exists on game object #{@game_object}.") if @game_object.respond_to? method
|
162
|
+
if method.to_s =~ /=/
|
163
|
+
code = <<-ENDL
|
164
|
+
def #{method}(arg)
|
165
|
+
@__behaviors[:#{self.class}].#{method}(arg)
|
166
|
+
end
|
167
|
+
ENDL
|
168
|
+
else
|
169
|
+
code = <<-ENDL
|
170
|
+
def #{method}(*args, &blk)
|
171
|
+
@__behaviors[:#{self.class}].#{method}(*args, &blk)
|
172
|
+
end
|
173
|
+
ENDL
|
174
|
+
end
|
175
|
+
@game_object.send(:instance_eval, code, __FILE__, __LINE__)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def initialize_dependant_behaviors
|
180
|
+
self.class.dependencies.each do |dependant_behavior|
|
181
|
+
begin
|
182
|
+
dependant_behavior_class = Object.const_get(dependant_behavior)
|
183
|
+
rescue NameError
|
184
|
+
raise "Cannot load dependant behavior '#{dependant_behavior}' in behavior '#{self.class}'"
|
185
|
+
end
|
186
|
+
|
187
|
+
unless @game_object.kind_of? dependant_behavior_class
|
188
|
+
@game_object.add_behavior dependant_behavior_class.to_s
|
189
|
+
@dependant_behaviors << dependant_behavior
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def initialize_listeners
|
195
|
+
@game_object.enable_listeners_for *self.class.listener_names
|
196
|
+
@game_object.enable_listeners_for *self.class.wrapped_methods
|
197
|
+
end
|
198
|
+
|
199
|
+
def delete
|
200
|
+
return if @deleted
|
201
|
+
unload
|
202
|
+
__remove_listeners
|
203
|
+
self.class.declared_method_list.each do |method_name|
|
204
|
+
target_class = class <<@game_object; self; end
|
205
|
+
target_class.send(:remove_method, method_name)
|
206
|
+
end
|
207
|
+
#TODO: Make sure we don't delete dependent behaviors that still have depending behaviors
|
208
|
+
@dependant_behaviors.each do |dependant|
|
209
|
+
@game_object.remove_behavior dependant
|
210
|
+
end
|
211
|
+
@deleted = true
|
212
|
+
end
|
213
|
+
|
214
|
+
public
|
215
|
+
|
216
|
+
def set_event_aliases(mappings, block)
|
217
|
+
if mappings.kind_of? Hash
|
218
|
+
mappings.each do |event, event_alias|
|
219
|
+
@game_object.handle_event(event_alias) do |message|
|
220
|
+
send(event, message)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
else mappings.kind_of? Symbol
|
224
|
+
@game_object.handle_event(mappings) do |message|
|
225
|
+
message = message.dup
|
226
|
+
send(block.call(message), message)
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
def add_reference_count
|
232
|
+
@reference_count += 1
|
233
|
+
end
|
234
|
+
|
235
|
+
def remove_reference_count
|
236
|
+
@reference_count -= 1
|
237
|
+
end
|
238
|
+
|
239
|
+
def load; end
|
240
|
+
def unload; end
|
241
|
+
end
|
242
|
+
|
243
|
+
class CallbackStatus
|
244
|
+
def continue?
|
245
|
+
true
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
#TODO: This appears to be un-used. Use it or drop it.
|
2
|
+
|
3
|
+
module Jemini
|
4
|
+
class BehaviorEvent
|
5
|
+
def initialize(*args)
|
6
|
+
@memoizations = Hash.new { |h,k| h[k] = {} }
|
7
|
+
load(*args)
|
8
|
+
end
|
9
|
+
|
10
|
+
def load(*args); end
|
11
|
+
|
12
|
+
def self.method_added(name)
|
13
|
+
match = /^memoize_(.+)$/.match name.to_s
|
14
|
+
return unless match
|
15
|
+
public_name = match[1]
|
16
|
+
eval <<-ENDL
|
17
|
+
def #{public_name}(*args)
|
18
|
+
@memoizations[:#{public_name}][args] ||= #{name}
|
19
|
+
end
|
20
|
+
ENDL
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
#A 2D image with mutltiple frames of animation.
|
2
|
+
class AnimatedImage < Jemini::Behavior
|
3
|
+
DEFAULT_MILLISECONDS_PER_UPDATE = 250 # quarter of a second
|
4
|
+
java_import 'org.newdawn.slick.Image'
|
5
|
+
java_import 'org.newdawn.slick.Animation'
|
6
|
+
|
7
|
+
depends_on :DrawableImage
|
8
|
+
depends_on :Updates
|
9
|
+
|
10
|
+
attr_reader :animations
|
11
|
+
attr_accessor :animation_speed
|
12
|
+
|
13
|
+
def load
|
14
|
+
@animations_per_action = {}
|
15
|
+
@current_action = 'default'
|
16
|
+
@animation_timer = 0
|
17
|
+
@frame_number = 1
|
18
|
+
@pulsing = false
|
19
|
+
@repeat = true
|
20
|
+
@animation_speed = DEFAULT_MILLISECONDS_PER_UPDATE
|
21
|
+
game_object.on_update do |delta|
|
22
|
+
update_animation(delta)
|
23
|
+
@pulsed_this_frame = false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def animate(action)
|
28
|
+
self.current_action = action.to_s
|
29
|
+
@repeat = false
|
30
|
+
end
|
31
|
+
|
32
|
+
def animate_pulse(action, delta)
|
33
|
+
self.current_action = action unless @current_action.to_s == action.to_s
|
34
|
+
@pulsing = true
|
35
|
+
@pulsed_this_frame = true
|
36
|
+
update_animation(delta)
|
37
|
+
end
|
38
|
+
|
39
|
+
def animate_cycle(action)
|
40
|
+
animate action
|
41
|
+
@repeat = true
|
42
|
+
end
|
43
|
+
|
44
|
+
def animate_as(noun)
|
45
|
+
@noun = noun
|
46
|
+
noun_regex = Regexp.new(noun.to_s)
|
47
|
+
all_images_for_noun = game_state.manager(:resource).image_names.select {|image| image.to_s =~ noun_regex }
|
48
|
+
animations_for_noun = all_images_for_noun.map {|image_name| image_name.to_s.sub("#{@noun}_", '')}
|
49
|
+
@animations = animations_for_noun.map {|animation| animation.sub(/\d/, '').to_sym}.uniq
|
50
|
+
@animations.each do |action|
|
51
|
+
action_regex = Regexp.new(action.to_s)
|
52
|
+
animations = all_images_for_noun.select {|numbered_animation| numbered_animation.to_s =~ action_regex }
|
53
|
+
@animations_per_action[action.to_s] = animations #.map {|a| a.to_s }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def current_action=(action)
|
60
|
+
@animation_timer = 0
|
61
|
+
@current_action = action
|
62
|
+
@frame_number = 1 # one based
|
63
|
+
@pulsing = false
|
64
|
+
@pulsed_this_frame = false
|
65
|
+
@game_object.image = @animations_per_action[action.to_s].first
|
66
|
+
end
|
67
|
+
|
68
|
+
def update_animation(delta)
|
69
|
+
return if @noun.nil?
|
70
|
+
self.current_action = 'default' if @pulsing && !@pulsed_this_frame
|
71
|
+
|
72
|
+
@animation_timer += delta
|
73
|
+
|
74
|
+
return if @animation_timer < @animation_speed
|
75
|
+
|
76
|
+
@frame_number = @animation_timer / @animation_speed
|
77
|
+
|
78
|
+
animations = @animations_per_action[@current_action.to_s]
|
79
|
+
new_frame = animations[@frame_number]
|
80
|
+
if new_frame
|
81
|
+
@game_object.image = new_frame
|
82
|
+
elsif @repeat
|
83
|
+
self.current_action = @current_action
|
84
|
+
else
|
85
|
+
self.current_action = 'default'
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|