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,47 @@
|
|
1
|
+
class VectoredMovement < Gemini::Behavior
|
2
|
+
attr_accessor :forward_speed, :reverse_speed, :rotation_speed
|
3
|
+
alias_method :set_forward_speed, :forward_speed=
|
4
|
+
alias_method :set_reverse_speed, :reverse_speed=
|
5
|
+
alias_method :set_rotation_speed, :rotation_speed=
|
6
|
+
|
7
|
+
depends_on :Physical
|
8
|
+
depends_on :ReceivesEvents
|
9
|
+
|
10
|
+
def load
|
11
|
+
@target.set_damping 0.0
|
12
|
+
@target.set_angular_damping 0.0
|
13
|
+
|
14
|
+
@forward_speed = 0
|
15
|
+
@reverse_speed = 0
|
16
|
+
@rotation_speed = 0
|
17
|
+
|
18
|
+
@intended_velocity = 0
|
19
|
+
@angular_velocity = 0
|
20
|
+
@movement_vector = Vector.new(0,0)
|
21
|
+
|
22
|
+
@target.on_update do
|
23
|
+
@target.set_angular_velocity(@angular_velocity)
|
24
|
+
@target.add_velocity(Vector.from_polar_vector(@intended_velocity, @target.rotation))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def begin_acceleration(message)
|
29
|
+
@intended_velocity = :forward == message.value ? @forward_speed : @reverse_speed
|
30
|
+
end
|
31
|
+
|
32
|
+
def end_acceleration(message)
|
33
|
+
@intended_velocity = 0
|
34
|
+
end
|
35
|
+
|
36
|
+
def begin_turn(message)
|
37
|
+
if :clockwise == message.value
|
38
|
+
@angular_velocity = @rotation_speed
|
39
|
+
else
|
40
|
+
@angular_velocity = -@rotation_speed
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def end_turn(message)
|
45
|
+
@angular_velocity = 0
|
46
|
+
end
|
47
|
+
end
|
data/src/color.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
class Color
|
2
|
+
attr_reader :native_color
|
3
|
+
|
4
|
+
def initialize(red_or_other, blue = 0.0, green = 0.0, alpha = 1.0)
|
5
|
+
if red_or_other.kind_of? Numeric
|
6
|
+
@native_color = new_native_color(red_or_other, blue, green, alpha)
|
7
|
+
else
|
8
|
+
# create from predefined Slick colors
|
9
|
+
fixed_color = Java::org::newdawn::slick::Color.send(red_or_other.to_s.downcase)
|
10
|
+
# we don't want to change the original, so we copy it
|
11
|
+
@native_color = new_native_color(fixed_color.r, fixed_color.g, fixed_color.b, fixed_color.a)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def red
|
16
|
+
@native_color.r
|
17
|
+
end
|
18
|
+
|
19
|
+
def blue
|
20
|
+
@native_color.b
|
21
|
+
end
|
22
|
+
|
23
|
+
def green
|
24
|
+
@native_color.g
|
25
|
+
end
|
26
|
+
|
27
|
+
def alpha
|
28
|
+
@native_color.a
|
29
|
+
end
|
30
|
+
|
31
|
+
def transparency
|
32
|
+
1.0 - alpha
|
33
|
+
end
|
34
|
+
|
35
|
+
def red=(new_red)
|
36
|
+
@native_color.r = new_red
|
37
|
+
end
|
38
|
+
|
39
|
+
def green=(new_green)
|
40
|
+
@native_color.g = new_green
|
41
|
+
end
|
42
|
+
|
43
|
+
def blue=(new_blue)
|
44
|
+
@native_color.b = new_blue
|
45
|
+
end
|
46
|
+
|
47
|
+
def alpha=(new_alpha)
|
48
|
+
@native_color.a = new_alpha
|
49
|
+
end
|
50
|
+
|
51
|
+
def transparency=(new_transparency)
|
52
|
+
self.alpha = 1.0 - new_transparency
|
53
|
+
end
|
54
|
+
|
55
|
+
def darken_by(amount)
|
56
|
+
@native_color.darken amount
|
57
|
+
end
|
58
|
+
|
59
|
+
def darken_by!(amount)
|
60
|
+
@native_color = @native_color.darken amount
|
61
|
+
end
|
62
|
+
|
63
|
+
def fade_by(amount)
|
64
|
+
self.alpha = alpha * (1.0 - amount)
|
65
|
+
end
|
66
|
+
private
|
67
|
+
def new_native_color(red, blue, green, alpha)
|
68
|
+
Java::org::newdawn::slick::Color.new(red, blue, green, alpha)
|
69
|
+
end
|
70
|
+
end
|
data/src/game_object.rb
ADDED
@@ -0,0 +1,174 @@
|
|
1
|
+
require 'behavior'
|
2
|
+
require 'listenable_mixin'
|
3
|
+
|
4
|
+
module Gemini
|
5
|
+
class GameObject
|
6
|
+
include ListenableMixin
|
7
|
+
attr_reader :game_state
|
8
|
+
|
9
|
+
@@declared_behaviors = Hash.new{|h,k| h[k] = []}
|
10
|
+
def self.has_behavior(behavior)
|
11
|
+
require "behaviors/#{behavior.underscore}"
|
12
|
+
@@declared_behaviors[self] << behavior
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(state, *args)
|
16
|
+
@game_state = state
|
17
|
+
@callbacks = Hash.new {|h,k| h[k] = []}
|
18
|
+
@__behaviors = {}
|
19
|
+
enable_listeners_for :before_remove, :after_remove
|
20
|
+
declared_behaviors.each do |behavior|
|
21
|
+
add_behavior(behavior)
|
22
|
+
end
|
23
|
+
validate_dependant_behaviors
|
24
|
+
load(*args)
|
25
|
+
end
|
26
|
+
|
27
|
+
def has_behavior?(behavior_name)
|
28
|
+
@__behaviors.has_key? behavior_name
|
29
|
+
end
|
30
|
+
|
31
|
+
def add_behavior(behavior_name)
|
32
|
+
klass = nil
|
33
|
+
retried = false
|
34
|
+
begin
|
35
|
+
klass = behavior_name.camelize.constantize
|
36
|
+
rescue NameError
|
37
|
+
raise if retried
|
38
|
+
require "behaviors/#{behavior_name.underscore}"
|
39
|
+
retried = true
|
40
|
+
retry
|
41
|
+
end
|
42
|
+
@__behaviors[behavior_name] = klass.new(self) if @__behaviors[behavior_name].nil?
|
43
|
+
validate_dependant_behaviors
|
44
|
+
rescue NameError => e
|
45
|
+
raise "Unable to load behavior #{behavior_name}, #{e.message}\n#{e.backtrace.join("\n")}"
|
46
|
+
end
|
47
|
+
|
48
|
+
def __destroy
|
49
|
+
notify :before_remove, self
|
50
|
+
#TODO: Perhaps expose this as a method on Behavior
|
51
|
+
#Gemini::Behavior.send(:class_variable_get, :@@depended_on_by).delete self
|
52
|
+
__remove_listeners
|
53
|
+
@__behaviors.each do |name, behavior|
|
54
|
+
#the list is being modified as we go through it, so check before use.
|
55
|
+
next if behavior.nil?
|
56
|
+
behavior.send(:delete)
|
57
|
+
end
|
58
|
+
notify :after_remove, self
|
59
|
+
end
|
60
|
+
|
61
|
+
def unload; end
|
62
|
+
|
63
|
+
def remove_behavior(behavior)
|
64
|
+
@__behaviors.delete(behavior).send(:delete) unless @__behaviors[behavior].nil?
|
65
|
+
end
|
66
|
+
|
67
|
+
# Takes a method and adds a corresponding listener registration method. Given
|
68
|
+
# the method foo, enable_listeners_for would generate the method on_foo and when
|
69
|
+
# notify was called with an event name of :foo, all callback blocks registered
|
70
|
+
# with the on_foo method would be called.
|
71
|
+
def enable_listeners_for(*methods)
|
72
|
+
methods.each do |method|
|
73
|
+
code = <<-ENDL
|
74
|
+
def on_#{method}(callback_method_name = nil, &callback)
|
75
|
+
register_listener(:#{method} , callback_method_name, callback)
|
76
|
+
end
|
77
|
+
|
78
|
+
def remove_#{method}(object, callback_or_callback_method=nil)
|
79
|
+
remove_registered_listener(:#{method}, object, callback_or_callback_method)
|
80
|
+
end
|
81
|
+
ENDL
|
82
|
+
|
83
|
+
self.instance_eval code, __FILE__, __LINE__
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def register_listener(listener_method_name, callback_method_name, callback)
|
88
|
+
if callback_method_name
|
89
|
+
__added_listener_for(self, listener_method_name, callback_method_name)
|
90
|
+
@callbacks[listener_method_name] << callback_method_name
|
91
|
+
else
|
92
|
+
origin = callback.source
|
93
|
+
origin.extend Gemini::ListenableMixin unless origin.kind_of? Gemini::ListenableMixin
|
94
|
+
origin.__added_listener_for(self, "#{listener_method_name}", callback)
|
95
|
+
@callbacks[listener_method_name] << callback
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def remove_registered_listener(listener_method_name, object, callback_or_callback_method)
|
100
|
+
if callback_or_callback_method.nil? || callback_or_callback_method.kind_of?(Symbol)
|
101
|
+
@callbacks[listener_method_name].delete callback_or_callback_method
|
102
|
+
else
|
103
|
+
@callbacks[listener_method_name].delete_if {|callback| callback.source == object }
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def notify(event_name, event = nil, callback_status = nil)
|
108
|
+
@callbacks[event_name.to_sym].each do |callback|
|
109
|
+
if event
|
110
|
+
if callback_status
|
111
|
+
if callback.kind_of? Symbol
|
112
|
+
send(callback, event, callback_status)
|
113
|
+
else
|
114
|
+
callback.call(event, callback_status)
|
115
|
+
end
|
116
|
+
break unless callback_status.nil? or callback_status.continue?
|
117
|
+
else
|
118
|
+
if callback.kind_of? Symbol
|
119
|
+
send(callback, event)
|
120
|
+
else
|
121
|
+
callback.call(event)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
else
|
125
|
+
if callback.kind_of? Symbol
|
126
|
+
send(callback)
|
127
|
+
else
|
128
|
+
callback.call
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def listen_for(message, target=self, &block)
|
135
|
+
target.send("on_#{message}", &block)
|
136
|
+
end
|
137
|
+
|
138
|
+
def kind_of?(klass)
|
139
|
+
super || @__behaviors.values.inject(false){|result, behavior| result || behavior.class == klass}
|
140
|
+
end
|
141
|
+
alias_method :is_a?, :kind_of?
|
142
|
+
|
143
|
+
def load(*args)
|
144
|
+
args.each do |behavior_name|
|
145
|
+
add_behavior behavior_name
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
private
|
150
|
+
def behavior_event_alias(behavior_class, aliases, &block)
|
151
|
+
if behavior = @__behaviors[behavior_class]
|
152
|
+
behavior.set_event_aliases(aliases, block)
|
153
|
+
else
|
154
|
+
raise "No behavior #{behavior_class} for game object #{self}"
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def validate_dependant_behaviors
|
159
|
+
declared_behaviors.each do |behavior|
|
160
|
+
behavior.constantize.kind_of_dependencies.each do |dependant_behavior|
|
161
|
+
dependency = dependant_behavior.constantize
|
162
|
+
#TODO: This code cannot work until the game object has a list of behavior objects (behaviors returns names)
|
163
|
+
#next if behaviors.find {|behavior| p behavior; behavior.last.kind_of?(dependency)}
|
164
|
+
next
|
165
|
+
raise "Dependant behavior '#{dependant_behavior}' was not found on class #{self.class}"
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def declared_behaviors
|
171
|
+
@@declared_behaviors[self.class]
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class FadingImage < Gemini::GameObject
|
2
|
+
has_behavior :Sprite
|
3
|
+
has_behavior :Spatial
|
4
|
+
has_behavior :Timeable
|
5
|
+
|
6
|
+
def load(sprite, color, seconds_to_fade_away)
|
7
|
+
self.image = sprite
|
8
|
+
self.color = color
|
9
|
+
add_countdown :fade_timer, seconds_to_fade_away, 1.0 / 30.0
|
10
|
+
|
11
|
+
on_countdown_complete do
|
12
|
+
game_state.remove self
|
13
|
+
end
|
14
|
+
|
15
|
+
on_timer_tick do |timer|
|
16
|
+
fade(timer.percent_complete)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def fade(percent)
|
21
|
+
color.transparency = percent
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
class IconStripCounterDisplay < Gemini::GameObject
|
2
|
+
TOP_LEFT_TO_BOTTOM_RIGHT_LAYOUT_MODE = :top_left_to_bottom_right
|
3
|
+
BOTTOM_RIGHT_TO_TOP_LEFT_LAYOUT_MODE = :bottom_right_to_top_left
|
4
|
+
|
5
|
+
has_behavior :Countable
|
6
|
+
has_behavior :Spatial
|
7
|
+
#has_behavior :CameraAnchoredDrawable
|
8
|
+
attr_accessor :icon, :background, :rows, :columns, :layout_mode
|
9
|
+
|
10
|
+
def load
|
11
|
+
@rows = 0
|
12
|
+
@columns = nil
|
13
|
+
@icons = []
|
14
|
+
@old_x = 0
|
15
|
+
@old_y = 0
|
16
|
+
@layout_mode = TOP_LEFT_TO_BOTTOM_RIGHT_LAYOUT_MODE
|
17
|
+
self.x = 0
|
18
|
+
self.y = 0
|
19
|
+
on_after_count_changes do
|
20
|
+
puts "count changed #{count}"
|
21
|
+
icon_count = count < 0 ? 0 : count
|
22
|
+
diff = @icons.size - icon_count
|
23
|
+
if diff > 0
|
24
|
+
1.upto diff do
|
25
|
+
last_icon = @icons.pop
|
26
|
+
@game_state.remove_game_object last_icon
|
27
|
+
end
|
28
|
+
elsif diff < 0
|
29
|
+
1.upto diff.abs do
|
30
|
+
sprite = @game_state.create_game_object :GameObject
|
31
|
+
sprite.add_behavior :Sprite
|
32
|
+
sprite.add_behavior :CameraAnchoredDrawable
|
33
|
+
sprite.image = @icon
|
34
|
+
position_sprite(x, y, @icons.size, sprite)
|
35
|
+
@icons << sprite
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
on_after_move do
|
40
|
+
@icons.each_with_index do |sprite, index|
|
41
|
+
position_sprite(x, y, index, sprite)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def position_sprite(offset_x, offset_y, sprite_index, sprite)
|
47
|
+
row_number = @rows.nil? ? sprite_index : (sprite_index % @rows)
|
48
|
+
column_number = @columns.nil? ? sprite_index : (sprite_index % @columns)
|
49
|
+
if TOP_LEFT_TO_BOTTOM_RIGHT_LAYOUT_MODE == @layout_mode
|
50
|
+
sprite_x = offset_x + (@icon.width * column_number)
|
51
|
+
sprite_y = offset_y + (@icon.height * row_number)
|
52
|
+
elsif BOTTOM_RIGHT_TO_TOP_LEFT_LAYOUT_MODE == @layout_mode
|
53
|
+
sprite_x = offset_x - (@icon.width * column_number)
|
54
|
+
sprite_y = offset_y - (@icon.height * row_number)
|
55
|
+
end
|
56
|
+
sprite.move(sprite_x, sprite_y)
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class StaticSprite < Gemini::GameObject
|
2
|
+
has_behavior :TangibleSprite
|
3
|
+
def load(sprite_name_or_image, x=nil, y=nil, width=nil, height=nil, *tags)
|
4
|
+
set_image sprite_name_or_image
|
5
|
+
if width.nil? || height.nil?
|
6
|
+
set_shape :Box, image_size.x, image_size.y
|
7
|
+
else
|
8
|
+
set_shape :Box, width, height
|
9
|
+
end
|
10
|
+
set_mass Tangible::INFINITE_MASS
|
11
|
+
set_static_body
|
12
|
+
set_restitution 1.0
|
13
|
+
set_friction 0.0
|
14
|
+
unless x.nil? || y.nil?
|
15
|
+
move(x, y)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
include_class "org.newdawn.slick.TrueTypeFont"
|
2
|
+
include_class "java.awt.Font"
|
3
|
+
require 'behaviors/drawable'
|
4
|
+
|
5
|
+
class Text < Gemini::GameObject
|
6
|
+
has_behavior :Spatial
|
7
|
+
PLAIN = Font::PLAIN
|
8
|
+
ITALIC = Font::ITALIC
|
9
|
+
BOLD = Font::BOLD
|
10
|
+
|
11
|
+
attr_accessor :text, :size, :style, :font_name
|
12
|
+
|
13
|
+
def load(x = 0, y = 0, text = "")
|
14
|
+
move(x, y)
|
15
|
+
@font_name = "Arial"
|
16
|
+
@size = 12
|
17
|
+
@text = text
|
18
|
+
@style = PLAIN
|
19
|
+
load_font
|
20
|
+
end
|
21
|
+
|
22
|
+
def text_width
|
23
|
+
@font.get_width(@text)
|
24
|
+
end
|
25
|
+
|
26
|
+
def text_height
|
27
|
+
@font.get_height(@text)
|
28
|
+
end
|
29
|
+
|
30
|
+
def draw(graphics)
|
31
|
+
half_width = @font.get_width(@text) / 2
|
32
|
+
half_height = @font.get_height(@text) / 2
|
33
|
+
@font.draw_string(x - half_width , y - half_height, @text)
|
34
|
+
end
|
35
|
+
|
36
|
+
def font_name=(name)
|
37
|
+
@font_name = name
|
38
|
+
load_font
|
39
|
+
end
|
40
|
+
alias_method :set_font_name, :font_name=
|
41
|
+
|
42
|
+
def size=(size)
|
43
|
+
@size = size
|
44
|
+
load_font
|
45
|
+
end
|
46
|
+
alias_method :set_size, :size=
|
47
|
+
|
48
|
+
def style=(style)
|
49
|
+
raise "Invalid font style, must be PLAIN, ITALIC or BOLD" unless [PLAIN, ITALIC, BOLD].member? style
|
50
|
+
@style = style
|
51
|
+
load_font
|
52
|
+
end
|
53
|
+
alias_method :set_style, :style=
|
54
|
+
|
55
|
+
private
|
56
|
+
def load_font
|
57
|
+
@font = TrueTypeFont.new(Font.new(@font_name, @style, @size), true)
|
58
|
+
end
|
59
|
+
end
|