jemini 2009.10.27

Sign up to get free protection for your applications and to get access to all the features.
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,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.
@@ -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
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
@@ -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