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.
- 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/src/inflector.rb
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# This code is a modified version of the Inflector class
|
|
2
|
+
# from the Ruby on Rails project (http://www.rubyonrails.com)
|
|
3
|
+
|
|
4
|
+
module Monkeybars
|
|
5
|
+
module Inflector
|
|
6
|
+
# The reverse of +camelize+. Makes an underscored form from the expression in the string.
|
|
7
|
+
#
|
|
8
|
+
# Changes '::' to '/' to convert namespaces to paths.
|
|
9
|
+
#
|
|
10
|
+
# Examples
|
|
11
|
+
# "ActiveRecord".underscore #=> "active_record"
|
|
12
|
+
# "ActiveRecord::Errors".underscore #=> active_record/errors
|
|
13
|
+
def underscore()
|
|
14
|
+
self.to_s.gsub(/::/, '/').
|
|
15
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
|
16
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
|
17
|
+
tr("-", "_").
|
|
18
|
+
downcase
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Constantize tries to find a declared constant with the name specified
|
|
22
|
+
# in the string. It raises a NameError when the name is not in CamelCase
|
|
23
|
+
# or is not initialized.
|
|
24
|
+
#
|
|
25
|
+
# Examples
|
|
26
|
+
# "Module".constantize #=> Module
|
|
27
|
+
# "Class".constantize #=> Class
|
|
28
|
+
def constantize()
|
|
29
|
+
# unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ self.to_s
|
|
30
|
+
# raise NameError, "#{self.inspect} is not a valid constant name!"
|
|
31
|
+
# end
|
|
32
|
+
|
|
33
|
+
Object.module_eval("::#{to_s}", __FILE__, __LINE__)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# By default, camelize converts strings to UpperCamelCase. If the argument to camelize
|
|
37
|
+
# is set to ":lower" then camelize produces lowerCamelCase.
|
|
38
|
+
#
|
|
39
|
+
# camelize will also convert '/' to '::' which is useful for converting paths to namespaces
|
|
40
|
+
#
|
|
41
|
+
# Examples
|
|
42
|
+
# "active_record".camelize #=> "ActiveRecord"
|
|
43
|
+
# "active_record".camelize(:lower) #=> "activeRecord"
|
|
44
|
+
# "active_record/errors".camelize #=> "ActiveRecord::Errors"
|
|
45
|
+
# "active_record/errors".camelize(:lower) #=> "activeRecord::Errors"
|
|
46
|
+
def camelize(first_letter_in_uppercase = true)
|
|
47
|
+
if first_letter_in_uppercase
|
|
48
|
+
self.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
|
|
49
|
+
else
|
|
50
|
+
self.to_s[0..0] + camelize(self.to_s)[1..-1]
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
class String
|
|
57
|
+
include Monkeybars::Inflector
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
class Symbol
|
|
61
|
+
include Monkeybars::Inflector
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
class Class
|
|
65
|
+
def constantize
|
|
66
|
+
self
|
|
67
|
+
end
|
|
68
|
+
end
|
data/src/jemini.rb
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
$LOAD_PATH << File.expand_path(File.dirname(__FILE__) + '/managers').gsub('%20', ' ')
|
|
2
|
+
$LOAD_PATH << File.expand_path(File.dirname(__FILE__) + '/game_objects').gsub('%20', ' ')
|
|
3
|
+
#$LOAD_PATH << File.expand_path(File.dirname(__FILE__) + '/states')
|
|
4
|
+
$LOAD_PATH << File.expand_path(File.dirname(__FILE__) + '/input_helpers').gsub('%20', ' ')
|
|
5
|
+
|
|
6
|
+
# Because Windows isn't friendly with JRuby
|
|
7
|
+
$LOAD_PATH << 'managers'
|
|
8
|
+
$LOAD_PATH << 'game_objects'
|
|
9
|
+
#$LOAD_PATH << 'states'
|
|
10
|
+
$LOAD_PATH << 'input_helpers'
|
|
11
|
+
|
|
12
|
+
require 'file_system'
|
|
13
|
+
require 'platform'
|
|
14
|
+
require 'color'
|
|
15
|
+
require 'vector'
|
|
16
|
+
require 'spline'
|
|
17
|
+
require 'inflector'
|
|
18
|
+
|
|
19
|
+
require 'math'
|
|
20
|
+
require 'proc_enhancement'
|
|
21
|
+
require 'resource'
|
|
22
|
+
require 'game_object'
|
|
23
|
+
require 'message_queue'
|
|
24
|
+
require 'managers/input_manager'
|
|
25
|
+
require 'resource_manager'
|
|
26
|
+
require 'game_state'
|
|
27
|
+
require 'inflector'
|
|
28
|
+
require 'basic_game_object_manager'
|
|
29
|
+
require 'basic_update_manager'
|
|
30
|
+
require 'basic_render_manager'
|
|
31
|
+
require 'game'
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module Jemini
|
|
2
|
+
module ListenableMixin
|
|
3
|
+
def __added_listener_for(game_object, method_name, callback)
|
|
4
|
+
@__methods_registered ||= {}
|
|
5
|
+
@__methods_registered[game_object] = [method_name, callback]
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def __remove_listeners
|
|
9
|
+
return if @__methods_registered.nil?
|
|
10
|
+
@__methods_registered.each do |game_object, listener_method_name_and_callback|
|
|
11
|
+
game_object.send("remove_#{listener_method_name_and_callback.first}", self, listener_method_name_and_callback.last)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
data/src/logger_mixin.rb
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
require 'logger'
|
|
2
|
+
|
|
3
|
+
module LoggerMixin
|
|
4
|
+
|
|
5
|
+
#Get the Logger object (see the Ruby standard library documentation).
|
|
6
|
+
#The log level is set to match the $LOG_LEVEL environment variable, or Logger::ERROR by default.
|
|
7
|
+
def log
|
|
8
|
+
@log ||= Logger.new(STDOUT, ENV['LOG_LEVEL'] || Logger::ERROR)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
end
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
#Controls the objects in the game world.
|
|
2
|
+
class BasicGameObjectManager < Jemini::GameObject
|
|
3
|
+
attr_reader :layers
|
|
4
|
+
FRONT_LAYER = 'front'
|
|
5
|
+
BACK_LAYER = 'back'
|
|
6
|
+
|
|
7
|
+
def load
|
|
8
|
+
enable_listeners_for :before_add_game_object, :after_add_game_object, :before_remove_game_object, :after_remove_game_object
|
|
9
|
+
#@layers = Hash.new{|h,k| h[k] = []}
|
|
10
|
+
@layer_order = [:default]
|
|
11
|
+
@layers = {:default => []}
|
|
12
|
+
@game_objects_to_remove = []
|
|
13
|
+
@game_objects_to_add = []
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def __process_pending_game_objects
|
|
17
|
+
@game_objects_to_remove.pop.__destroy until @game_objects_to_remove.empty?
|
|
18
|
+
until @game_objects_to_add.empty?
|
|
19
|
+
layer, game_object = @game_objects_to_add.pop
|
|
20
|
+
@layers[layer] << game_object
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
#Called when GameState#create is called.
|
|
25
|
+
#Triggers :before_add_game_object, :after_add_game_object callbacks.
|
|
26
|
+
def add_game_object(game_object)
|
|
27
|
+
notify :before_add_game_object, game_object, :default
|
|
28
|
+
@layers[:default] << game_object
|
|
29
|
+
notify :after_add_game_object, game_object, :default
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
#Called when GameState#remove is called.
|
|
33
|
+
#Triggers :before_remove_game_object, :after_remove_game_object callbacks.
|
|
34
|
+
def remove_game_object(game_object)
|
|
35
|
+
owning_layer = @layers.values.find {|layer| layer.include? game_object}
|
|
36
|
+
return if owning_layer.nil? #NOTE: Not sure if this is the right thing to do, but at least no exception is thrown
|
|
37
|
+
notify :before_remove_game_object, game_object
|
|
38
|
+
owning_layer.delete game_object
|
|
39
|
+
game_object.unload
|
|
40
|
+
notify :after_remove_game_object, game_object
|
|
41
|
+
@game_objects_to_remove.push game_object
|
|
42
|
+
#game_object.unload
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
#Adds game object to named layer.
|
|
46
|
+
#Triggers :before_add_game_object, :after_add_game_object callbacks.
|
|
47
|
+
#TODO: If layers are desired for the add game object call, then include them in the notify.
|
|
48
|
+
# This cannot be as an extra param
|
|
49
|
+
def add_game_object_to_layer(game_object, layer_name)
|
|
50
|
+
notify :before_add_game_object, game_object
|
|
51
|
+
@layers[layer_name] << game_object
|
|
52
|
+
#@game_objects_to_add.push [layer_name, game_object]
|
|
53
|
+
notify :after_add_game_object, game_object
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
#Moves given object from one layer to another.
|
|
57
|
+
def move_game_object_to_layer(game_object, layer_name)
|
|
58
|
+
owning_layer = @layers.values.find {|layer| layer.include? game_object}
|
|
59
|
+
owning_layer.delete game_object
|
|
60
|
+
@layers[layer_name] << game_object
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
#Returns Array of all game objects.
|
|
64
|
+
def game_objects
|
|
65
|
+
game_objects = []
|
|
66
|
+
@layers.values.each do |layer|
|
|
67
|
+
layer.each do |game_object|
|
|
68
|
+
game_objects << game_object
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
game_objects
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
#Returns Array of all layers by drawing order.
|
|
75
|
+
def layers_by_order
|
|
76
|
+
@layer_order.map {|layer_name| @layers[layer_name]}.compact
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
#Add the named layer at the given drawing order position.
|
|
80
|
+
#Position can be a number or one of the constants FRONT_LAYER or BACK_LAYER.
|
|
81
|
+
def add_layer_at(layer_name, location)
|
|
82
|
+
if location.kind_of? Numeric
|
|
83
|
+
@layer_order.delete_at(location) if @layer_order[location].nil?
|
|
84
|
+
@layer_order.insert(location, layer_name)
|
|
85
|
+
else # string/symbol
|
|
86
|
+
case location.to_s
|
|
87
|
+
when FRONT_LAYER
|
|
88
|
+
@layer_order << layer_name
|
|
89
|
+
when BACK_LAYER
|
|
90
|
+
@layer_order.unshift(layer_name)
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
@layers[layer_name] = []
|
|
94
|
+
end
|
|
95
|
+
end
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
require 'behaviors/physical'
|
|
2
|
+
require 'events/physical_message'
|
|
3
|
+
|
|
4
|
+
#Controls objects that collide, fall with gravity, roll, etc.
|
|
5
|
+
class BasicPhysicsManager < Jemini::GameObject
|
|
6
|
+
INTERPOLATION_THESHOLD = 6.0
|
|
7
|
+
MILLISECONDS_PER_UPDATE = 1000 / 60
|
|
8
|
+
PHYS2D_UPDATE_DIFF = (1000.to_f / 60.to_f) - MILLISECONDS_PER_UPDATE.to_f
|
|
9
|
+
DELTA_FACTOR = 0.01
|
|
10
|
+
include_class 'net.phys2d.math.Vector2f'
|
|
11
|
+
include_class 'net.phys2d.raw.World'
|
|
12
|
+
include_class 'net.phys2d.raw.strategies.QuadSpaceStrategy'
|
|
13
|
+
include_class 'net.phys2d.raw.strategies.BruteCollisionStrategy'
|
|
14
|
+
has_behavior :HandlesEvents
|
|
15
|
+
|
|
16
|
+
def load
|
|
17
|
+
@delta_debt = 0
|
|
18
|
+
@world = World.new(Vector2f.new(0, 0), 5, QuadSpaceStrategy.new(20, 5))
|
|
19
|
+
# @world = World.new(Vector2f.new(0, 0), 10, BruteCollisionStrategy.new)
|
|
20
|
+
@world.add_listener self
|
|
21
|
+
game_state.manager(:update).on_update do |delta|
|
|
22
|
+
update delta
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
game_state.manager(:game_object).on_after_add_game_object do |game_object|
|
|
26
|
+
add_to_world game_object if game_object.has_behavior? :Physical
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
game_state.manager(:game_object).on_after_remove_game_object do |game_object|
|
|
30
|
+
game_object.remove_from_world(@world) if game_object.has_behavior? :Physical
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
handle_event :toggle_debug_mode, :toggle_debug_mode
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def update(delta)
|
|
37
|
+
delta += @delta_debt
|
|
38
|
+
@delta_debt = 0
|
|
39
|
+
if delta == MILLISECONDS_PER_UPDATE
|
|
40
|
+
sleep PHYS2D_UPDATE_DIFF / 1000.0
|
|
41
|
+
step
|
|
42
|
+
else
|
|
43
|
+
temp_delta = delta
|
|
44
|
+
until temp_delta <= 0
|
|
45
|
+
new_delta = temp_delta > MILLISECONDS_PER_UPDATE ? MILLISECONDS_PER_UPDATE : temp_delta
|
|
46
|
+
if new_delta < MILLISECONDS_PER_UPDATE
|
|
47
|
+
@delta_debt = new_delta
|
|
48
|
+
return #don't step, we'll try again next update
|
|
49
|
+
else
|
|
50
|
+
step
|
|
51
|
+
temp_delta -= new_delta
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# there's a typo in the API, I swears it.
|
|
58
|
+
def collision_occured(event)
|
|
59
|
+
event.body_a.user_data.notify :physical_collided, PhysicsMessage.new(event, event.body_b.user_data)
|
|
60
|
+
event.body_b.user_data.notify :physical_collided, PhysicsMessage.new(event, event.body_a.user_data)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
#Turns drawing of physical bodies on/off.
|
|
64
|
+
def toggle_debug_mode(message)
|
|
65
|
+
@debug_mode = !@debug_mode
|
|
66
|
+
@game_state.manager(:game_object).game_objects.each do |game_object|
|
|
67
|
+
game_object.set_physical_debug_mode(@debug_mode) if game_object.has_behavior? :Physical
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
#Takes a number representing the downward force to apply to physical objects.
|
|
72
|
+
def gravity=(gravity_or_x)
|
|
73
|
+
if gravity_or_x.kind_of? Numeric
|
|
74
|
+
@world.set_gravity(0, gravity_or_x)
|
|
75
|
+
else
|
|
76
|
+
raise "Not implemented yet"
|
|
77
|
+
# @world.set_gravity(gravity_or_x)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
private
|
|
82
|
+
def step
|
|
83
|
+
@world.step # must step at fixed rate (1/60f) or results are unpredictable
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def add_to_world(game_object)
|
|
87
|
+
game_object.add_to_world(@world)
|
|
88
|
+
game_object.set_physical_debug_mode(true) if @debug_mode
|
|
89
|
+
end
|
|
90
|
+
# def colliding?(body)
|
|
91
|
+
# 0 < @world.get_contacts(body).size
|
|
92
|
+
# end
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
require 'managers/render_support/hardware_cursor'
|
|
2
|
+
|
|
3
|
+
class BasicRenderManager < Jemini::GameObject
|
|
4
|
+
java_import 'org.newdawn.slick.geom.Circle'
|
|
5
|
+
|
|
6
|
+
include HardwareCursor
|
|
7
|
+
|
|
8
|
+
def load
|
|
9
|
+
enable_listeners_for :before_render, :after_render
|
|
10
|
+
@debug_queue = []
|
|
11
|
+
use_available_hardware_cursor
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def unload
|
|
15
|
+
revert_hardware_cursor
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
#Render all game objects to the given graphics context.
|
|
19
|
+
#Triggers :before_render, :after_render callbacks.
|
|
20
|
+
def render(graphics)
|
|
21
|
+
notify :before_render, graphics
|
|
22
|
+
#game_state.manager(:game_object).game_objects.each { |game_object| game_object.draw if game_object.respond_to? :draw}
|
|
23
|
+
game_state.manager(:game_object).layers_by_order.each do |game_objects|
|
|
24
|
+
game_objects.each { |game_object| game_object.draw(graphics) if game_object.respond_to? :draw}
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
render_debug_overlay(graphics)
|
|
28
|
+
notify :after_render, graphics
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def debug(type, color, options)
|
|
32
|
+
@debug_queue << {:type => type, :color => color}.merge(options)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def render_debug_overlay(graphics)
|
|
36
|
+
pre_debug_color = graphics.color
|
|
37
|
+
until @debug_queue.empty?
|
|
38
|
+
debug_render = @debug_queue.shift
|
|
39
|
+
color = debug_render[:color]
|
|
40
|
+
color = Color.new(color) unless color.kind_of? Color
|
|
41
|
+
graphics.color = color.native_color
|
|
42
|
+
case debug_render[:type]
|
|
43
|
+
when :point
|
|
44
|
+
graphics.fill Circle.new(debug_render[:position].x, debug_render[:position].y, 2)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
graphics.color = pre_debug_color
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#Updates all game objects.
|
|
2
|
+
class BasicUpdateManager < Jemini::GameObject
|
|
3
|
+
def load
|
|
4
|
+
enable_listeners_for :update, :before_update, :after_update
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
#Call update method on all game objects that support it.
|
|
8
|
+
#Triggers :before_update, :after_update callbacks.
|
|
9
|
+
def update(delta)
|
|
10
|
+
# delta = 20.0
|
|
11
|
+
return if paused?
|
|
12
|
+
|
|
13
|
+
notify :before_update, delta
|
|
14
|
+
game_state.manager(:game_object).game_objects.each { |game_object| game_object.update(delta) if game_object.respond_to? :update}
|
|
15
|
+
notify :update, delta
|
|
16
|
+
notify :after_update, delta
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def pause
|
|
20
|
+
@paused = true
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def resume
|
|
24
|
+
@paused = false
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def paused?
|
|
28
|
+
@paused
|
|
29
|
+
end
|
|
30
|
+
end
|
|
File without changes
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
java_import 'org.newdawn.slick.Input'
|
|
2
|
+
|
|
3
|
+
require 'message_queue'
|
|
4
|
+
|
|
5
|
+
require 'managers/input_support/input_listener'
|
|
6
|
+
require 'managers/input_support/mouse_listener'
|
|
7
|
+
require 'managers/input_support/key_listener'
|
|
8
|
+
require 'managers/input_support/joystick_listener'
|
|
9
|
+
require 'managers/input_support/input_builder'
|
|
10
|
+
|
|
11
|
+
require 'managers/input_support/input_message'
|
|
12
|
+
require 'managers/input_support/slick_input_listener'
|
|
13
|
+
require 'managers/input_support/slick_input_message'
|
|
14
|
+
|
|
15
|
+
if Platform.using_osx?
|
|
16
|
+
# buttons
|
|
17
|
+
XBOX_360_DPAD_UP = 0
|
|
18
|
+
XBOX_360_DPAD_DOWN = 1
|
|
19
|
+
XBOX_360_DPAD_LEFT = 2
|
|
20
|
+
XBOX_360_DPAD_RIGHT = 3
|
|
21
|
+
XBOX_360_START = 4
|
|
22
|
+
XBOX_360_BACK = 5
|
|
23
|
+
XBOX_360_LEFT_STICK = 6
|
|
24
|
+
XBOX_360_RIGHT_STICK = 7
|
|
25
|
+
XBOX_360_LEFT_BUMPER = 8
|
|
26
|
+
XBOX_360_RIGHT_BUMPER = 9
|
|
27
|
+
XBOX_360_GUIDE_BUTTON = 10
|
|
28
|
+
XBOX_360_A = 11
|
|
29
|
+
XBOX_360_B = 12
|
|
30
|
+
XBOX_360_X = 13
|
|
31
|
+
XBOX_360_Y = 14
|
|
32
|
+
# axes
|
|
33
|
+
XBOX_360_LEFT_X_AXIS = 'x'
|
|
34
|
+
XBOX_360_LEFT_Y_AXIS = 'y'
|
|
35
|
+
XBOX_360_LEFT_TRIGGER_AXIS = 'z' # On Windows, both triggers serve as one axis
|
|
36
|
+
XBOX_360_RIGHT_X_AXIS = 'rx'
|
|
37
|
+
XBOX_360_RIGHT_Y_AXIS = 'ry'
|
|
38
|
+
XBOX_360_RIGHT_TRIGGER_AXIS = 'rz' # On Windows, both triggers serve as one axis
|
|
39
|
+
elsif Platform.using_windows?
|
|
40
|
+
# buttons
|
|
41
|
+
XBOX_360_A = 0
|
|
42
|
+
XBOX_360_B = 1
|
|
43
|
+
XBOX_360_X = 2
|
|
44
|
+
XBOX_360_Y = 3
|
|
45
|
+
XBOX_360_LEFT_BUMPER = 4
|
|
46
|
+
XBOX_360_RIGHT_BUMPER = 5
|
|
47
|
+
XBOX_360_BACK = 6
|
|
48
|
+
XBOX_360_START = 7
|
|
49
|
+
XBOX_360_LEFT_STICK = 8
|
|
50
|
+
XBOX_360_RIGHT_STICK = 9
|
|
51
|
+
#axes
|
|
52
|
+
XBOX_360_LEFT_X_AXIS = 'X Axis'
|
|
53
|
+
XBOX_360_LEFT_Y_AXIS = 'Y Axis'
|
|
54
|
+
XBOX_360_TRIGGER_AXIS = 'Z Axis' # On OSX, both triggers serve as individual axes
|
|
55
|
+
XBOX_360_RIGHT_X_AXIS = 'X Rotation'
|
|
56
|
+
XBOX_360_RIGHT_Y_AXIS = 'Y Rotation'
|
|
57
|
+
elsif Platform.using_linux?
|
|
58
|
+
XBOX_360_A = 0
|
|
59
|
+
XBOX_360_B = 1
|
|
60
|
+
XBOX_360_X = 2
|
|
61
|
+
XBOX_360_Y = 3
|
|
62
|
+
XBOX_360_LEFT_BUMPER = 4
|
|
63
|
+
XBOX_360_RIGHT_BUMPER = 5
|
|
64
|
+
XBOX_360_BACK = 6
|
|
65
|
+
XBOX_360_START = 7
|
|
66
|
+
XBOX_360_GUIDE = 8
|
|
67
|
+
XBOX_360_LEFT_STICK = 9
|
|
68
|
+
XBOX_360_RIGHT_STICK = 10
|
|
69
|
+
XBOX_360_LEFT_X_AXIS = 'x'
|
|
70
|
+
XBOX_360_LEFT_Y_AXIS = 'y'
|
|
71
|
+
XBOX_360_LEFT_TRIGGER_AXIS = 'z'
|
|
72
|
+
XBOX_360_RIGHT_X_AXIS = 'rx'
|
|
73
|
+
XBOX_360_RIGHT_Y_AXIS = 'ry'
|
|
74
|
+
XBOX_360_RIGHT_TRIGGER_AXIS = 'rz'
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# LWJGL can't poll for buttons in the negative range yet. Possible bug to report?
|
|
78
|
+
# 360 controller provides button presses for analog in for convienence
|
|
79
|
+
XBOX_360_LEFT_STICK_LEFT = -1
|
|
80
|
+
XBOX_360_LEFT_STICK_RIGHT = -2
|
|
81
|
+
XBOX_360_LEFT_STICK_UP = -3
|
|
82
|
+
XBOX_360_LEFT_STICK_DOWN = -4
|
|
83
|
+
|
|
84
|
+
class MouseEvent
|
|
85
|
+
PRESSED = :pressed
|
|
86
|
+
RELEASED = :released
|
|
87
|
+
attr_accessor :state, :location
|
|
88
|
+
def initialize(state, location)
|
|
89
|
+
@state, @location = state, location
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
module Jemini
|
|
94
|
+
# Consumes raw slick_input events and outputs events based on
|
|
95
|
+
# registered key bindings.
|
|
96
|
+
class InputManager < Jemini::GameObject
|
|
97
|
+
attr_reader :listeners
|
|
98
|
+
|
|
99
|
+
@@loading_input_manager = nil
|
|
100
|
+
def self.loading_input_manager
|
|
101
|
+
@@loading_input_manager
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def load(container)
|
|
105
|
+
@listeners = []
|
|
106
|
+
@held_keys = []
|
|
107
|
+
@raw_input = container.input
|
|
108
|
+
@input_listener = SlickInputListener.new(@game_state)
|
|
109
|
+
@raw_input.add_listener @input_listener
|
|
110
|
+
@held_buttons = {}
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def use_input(input)
|
|
114
|
+
@@loading_input_manager = self
|
|
115
|
+
file_name = File.join('inputs', "#{input}_input")
|
|
116
|
+
log.debug "Using input mapping: #{file_name}"
|
|
117
|
+
require file_name
|
|
118
|
+
@@loading_input_manager = nil
|
|
119
|
+
$".pop # remove the entry so we can require it again
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
#Check for keypresses and send messages to message queue accordingly.
|
|
123
|
+
def poll(screen_width, screen_height, delta)
|
|
124
|
+
@keymap ||= {}
|
|
125
|
+
# return if @keymap.nil?
|
|
126
|
+
@input_listener.delta = delta
|
|
127
|
+
@raw_input.poll(screen_width, screen_height)
|
|
128
|
+
all_keymappings_to_game_messages.each do |game_message|
|
|
129
|
+
@game_state.manager(:message_queue).post_message game_message
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
#The number of connected game controllers.
|
|
134
|
+
def connected_joystick_size
|
|
135
|
+
@raw_input.controller_count
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
private
|
|
139
|
+
|
|
140
|
+
def all_keymappings_to_game_messages
|
|
141
|
+
# @keymap.values.map {|keymap_array| poll_to_game_messages(keymap_array)}.flatten.compact
|
|
142
|
+
poll_to_game_messages(listeners).compact
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def poll_to_game_messages(keymaps)
|
|
146
|
+
messages = []
|
|
147
|
+
keymaps.reject! do |keymap|
|
|
148
|
+
begin
|
|
149
|
+
messages << keymap.poll(@raw_input)
|
|
150
|
+
false # don't delete me
|
|
151
|
+
rescue => e
|
|
152
|
+
# TODO: puts in test, warn in production. Is there a better way?
|
|
153
|
+
puts "error in poll: #{e}"
|
|
154
|
+
puts "removing keymap #{keymap}"
|
|
155
|
+
true # I've been bad, delete me
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
messages
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|