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
@@ -0,0 +1,16 @@
|
|
1
|
+
#Makes an object emit sounds.
|
2
|
+
class Audible < Jemini::Behavior
|
3
|
+
|
4
|
+
#Load a sound file and assign a reference to it, which can later be passed to emit_sound.
|
5
|
+
def load_sound(reference, path)
|
6
|
+
game_state.manager(:sound).add_sound(reference, path)
|
7
|
+
end
|
8
|
+
|
9
|
+
#Plays a sound whose reference was assigned via load_sound.
|
10
|
+
#Pass in volume to play it back quieter or louder (1.0 is normal).
|
11
|
+
#Pass in pitch for a higher or lower tone (1.0 is normal).
|
12
|
+
def emit_sound(reference, volume = 1.0, pitch = 1.0)
|
13
|
+
game_state.manager(:sound).play_sound(reference, volume, pitch)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
#Makes an object transition between several states in succession.
|
2
|
+
class AxisStateful < Jemini::Behavior
|
3
|
+
#Indicates that an object has transitioned from one state to another along an axis.
|
4
|
+
class AxialStateTransferEvent
|
5
|
+
attr_accessor :before_state, :after_state, :axis
|
6
|
+
def initialize(axis, before_state, after_state)
|
7
|
+
@axis = axis
|
8
|
+
@before_state = before_state
|
9
|
+
@after_state = after_state
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_accessor :default_state_on_axis, :current_state_on_axis
|
14
|
+
wrap_with_callbacks :transfer_state_on_axis
|
15
|
+
|
16
|
+
def load
|
17
|
+
@state_transitions = {}
|
18
|
+
@game_object.enable_listeners_for :axis_state_transfer_accepted
|
19
|
+
@game_object.enable_listeners_for :axis_state_transfer_rejected
|
20
|
+
end
|
21
|
+
|
22
|
+
def set_state_transisions_on_axis(axis, transitions)
|
23
|
+
@state_transitisions[axis] = transitions
|
24
|
+
end
|
25
|
+
|
26
|
+
def transfer_state_on_axis(axis, state)
|
27
|
+
event = AxialStateTransferEvent.new(axis, @current_state[axis], state)
|
28
|
+
if @state_transitions[axis][@current_state[axis]].include? state
|
29
|
+
@current_state = state
|
30
|
+
notify :axis_state_transfer_accepted, event
|
31
|
+
else
|
32
|
+
notify :axis_state_transfer_rejected, event
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'behavior_event'
|
2
|
+
include_class 'org.newdawn.slick.geom.Rectangle'
|
3
|
+
|
4
|
+
#Makes an object generate a BoundingBoxCollisionEvent if its bounding box intersects another's.
|
5
|
+
class BoundingBoxCollidable < Jemini::Behavior
|
6
|
+
depends_on :Spatial2d
|
7
|
+
|
8
|
+
def load
|
9
|
+
@game_object.enable_listeners_for :collided
|
10
|
+
end
|
11
|
+
|
12
|
+
def collision_check(collidable)
|
13
|
+
return if self == collidable || @game_object == collidable
|
14
|
+
|
15
|
+
notify :collided, BoundingBoxCollisionEvent.new(@game_object, collidable) if bounds.intersects(collidable.bounds)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
#Indicates that one object has collided with another.
|
20
|
+
class BoundingBoxCollisionEvent < Jemini::BehaviorEvent
|
21
|
+
attr_accessor :colliding_object, :collided_object
|
22
|
+
|
23
|
+
def load(source, other)
|
24
|
+
@colliding_object = source
|
25
|
+
@collided_object = other
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# A CardinalMovable can move north, east, south and west.
|
2
|
+
# Movement along certain axis can be constrained, for example, pong has horizonal (north/east)
|
3
|
+
# TODO: Allow disabling of diagonal easily
|
4
|
+
# TODO: Allow disabling of directions
|
5
|
+
# TODO: Allow speed limit per axis
|
6
|
+
# TODO: Allow speed limit per direction
|
7
|
+
class CardinalMovable < Jemini::Behavior
|
8
|
+
NORTH = :north
|
9
|
+
EAST = :east
|
10
|
+
SOUTH = :south
|
11
|
+
WEST = :west
|
12
|
+
NORTH_EAST = :north_east
|
13
|
+
SOUTH_EAST = :south_east
|
14
|
+
SOUTH_WEST = :south_west
|
15
|
+
NORTH_WEST = :north_west
|
16
|
+
DIAGONAL_DIRECTIONS = [NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST]
|
17
|
+
CARDINAL_DIRECTIONS = [NORTH, EAST, SOUTH, WEST] + DIAGONAL_DIRECTIONS
|
18
|
+
DIRECTION_TRANSLATION_IN_DEGREES = []
|
19
|
+
|
20
|
+
depends_on :Tangible
|
21
|
+
depends_on :HandlesEvents
|
22
|
+
attr_accessor :facing_direction
|
23
|
+
#TODO: Rename to cardinal facing direction
|
24
|
+
wrap_with_callbacks :facing_direction=, :set_facing_drection
|
25
|
+
|
26
|
+
def load
|
27
|
+
@facing_direction = NORTH
|
28
|
+
@allowed_directions = CARDINAL_DIRECTIONS.dup
|
29
|
+
# @cardinal_speed = 25
|
30
|
+
end
|
31
|
+
|
32
|
+
# direct input events here to keep "pushing".
|
33
|
+
# TODO: After the update, clear the directions.
|
34
|
+
def set_cardinal_movement_for_update(directions)
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
def facing_direction=(direction)
|
39
|
+
if @allowed_directions.include? direction
|
40
|
+
if @moving && orthogonal_directions?(@facing_direction, direction)
|
41
|
+
diagonal_direction = begin
|
42
|
+
"#{self.class}::#{@facing_direction.to_s.upcase}_#{direction.to_s.upcase}".constantize
|
43
|
+
rescue
|
44
|
+
"#{self.class}::#{direction.to_s.upcase}_#{@facing_direction.to_s.upcase}".constantize
|
45
|
+
end
|
46
|
+
@facing_direction = diagonal_direction
|
47
|
+
else
|
48
|
+
@facing_direction = direction
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
alias_method :set_facing_direction, :facing_direction=
|
53
|
+
|
54
|
+
#Set direction(s) the object is allowed to move in.
|
55
|
+
#Takes either a single directional constant, or an Array of them.
|
56
|
+
def constrain_direction(directions)
|
57
|
+
directions = [directions] unless directions.kind_of? Array
|
58
|
+
directions.each
|
59
|
+
directions.each { |direction| @allowed_directions.delete direction }
|
60
|
+
end
|
61
|
+
|
62
|
+
#Initiate movement in a given direction.
|
63
|
+
#Takes a message with a directional constant as its value.
|
64
|
+
def begin_cardinal_movement(message)
|
65
|
+
direction = message.value
|
66
|
+
return unless @allowed_directions.include? direction
|
67
|
+
set_facing_direction direction
|
68
|
+
@moving = true
|
69
|
+
@cardinal_velocity = direction_to_polar_vector(@facing_direction)
|
70
|
+
end
|
71
|
+
|
72
|
+
#Halt movement in a given direction.
|
73
|
+
#Takes a message with a directional constant as its value.
|
74
|
+
def end_cardinal_movement(message)
|
75
|
+
direction = message.value
|
76
|
+
@facing_direction = other_direction(@facing_direction, direction) if diagonal_direction? @facing_direction
|
77
|
+
if @facing_direction == direction
|
78
|
+
@cardinal_velocity = Vector.new(0,0)
|
79
|
+
@moving = false
|
80
|
+
else
|
81
|
+
@cardinal_velocity = direction_to_polar_vector(@facing_direction)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
def direction_to_polar_vector(direction)
|
88
|
+
angle = case direction
|
89
|
+
when NORTH
|
90
|
+
0
|
91
|
+
when NORTH_EAST
|
92
|
+
45
|
93
|
+
when EAST
|
94
|
+
90
|
95
|
+
when SOUTH_EAST
|
96
|
+
135
|
97
|
+
when SOUTH
|
98
|
+
180
|
99
|
+
when SOUTH_WEST
|
100
|
+
225
|
101
|
+
when WEST
|
102
|
+
270
|
103
|
+
when NORTH_WEST
|
104
|
+
315
|
105
|
+
end
|
106
|
+
Vector.from_polar_vector(@cardinal_speed, angle)
|
107
|
+
end
|
108
|
+
|
109
|
+
def diagonal_direction?(direction)
|
110
|
+
DIAGONAL_DIRECTIONS.include? direction
|
111
|
+
end
|
112
|
+
|
113
|
+
def other_direction(diagonal_direction, direction)
|
114
|
+
diagonal_direction.to_s.sub(direction.to_s, '').sub('_', '').to_sym
|
115
|
+
end
|
116
|
+
|
117
|
+
def orthogonal_directions?(direction_a, direction_b)
|
118
|
+
([NORTH, SOUTH].include?(direction_a) && [EAST, WEST].include?(direction_b)) ||
|
119
|
+
([NORTH, SOUTH].include?(direction_b) && [EAST, WEST].include?(direction_a))
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#Makes an object clickable with the mouse.
|
2
|
+
class Clickable < Jemini::Behavior
|
3
|
+
depends_on :HandlesEvents
|
4
|
+
depends_on :Regional
|
5
|
+
wrap_with_callbacks :pressed, :released
|
6
|
+
|
7
|
+
def load
|
8
|
+
@game_object.handle_event :mouse_button1_pressed do |mouse_event|
|
9
|
+
pressed if @game_object.within_region? mouse_event.value.location
|
10
|
+
end
|
11
|
+
|
12
|
+
@game_object.handle_event :mouse_button1_released do |mouse_event|
|
13
|
+
released if @game_object.within_region? mouse_event.value.location
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def pressed; end
|
18
|
+
def released; end
|
19
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
#Makes an object receive events when its numbers have changed.
|
2
|
+
class Countable < Jemini::Behavior
|
3
|
+
attr_accessor :count
|
4
|
+
wrap_with_callbacks :count=
|
5
|
+
|
6
|
+
def load
|
7
|
+
@count = 0
|
8
|
+
@game_object.enable_listeners_for :incremented
|
9
|
+
@game_object.enable_listeners_for :decremented
|
10
|
+
end
|
11
|
+
|
12
|
+
def count=(count)
|
13
|
+
comparison = @count <=> count
|
14
|
+
@count = count
|
15
|
+
case comparison
|
16
|
+
when -1
|
17
|
+
@game_object.notify :decremented
|
18
|
+
when 0
|
19
|
+
# do nothing
|
20
|
+
when 1
|
21
|
+
@game_object.notify :incremented
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def decrement
|
26
|
+
self.count = count - 1
|
27
|
+
end
|
28
|
+
|
29
|
+
def increment
|
30
|
+
self.count = count + 1
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
#Makes an object draw its interactions with the physics engine on the screen.
|
2
|
+
class DebugPhysical < Jemini::Behavior
|
3
|
+
|
4
|
+
PhysVector = Java::net::phys2d::math::Vector2f
|
5
|
+
PhysCircle = Java::net.phys2d.raw.shapes.Circle
|
6
|
+
PhysPolygon = Java::net.phys2d.raw.shapes.Polygon
|
7
|
+
PhysLine = Java::net.phys2d.raw.shapes.Line
|
8
|
+
SlickVector = Java::org::newdawn::slick::geom::Vector2f
|
9
|
+
SlickPolygon = Java::org.newdawn.slick.geom.Polygon
|
10
|
+
SlickCircle = Java::org.newdawn.slick.geom.Circle
|
11
|
+
SlickLine = Java::org.newdawn.slick.geom.Line
|
12
|
+
|
13
|
+
include_class 'net.phys2d.raw.shapes.Box'
|
14
|
+
|
15
|
+
def load
|
16
|
+
game_state.manager(:render).on_after_render do |graphics|
|
17
|
+
draw(graphics)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def unload
|
22
|
+
# TODO: Remove listener for after render?
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
def draw(graphics)
|
27
|
+
#TODO: Support joints and composite bodies(?)
|
28
|
+
body = @game_object.instance_variable_get(:@__behaviors)[:Physical].instance_variable_get(:@body)
|
29
|
+
physics_shape = body.shape
|
30
|
+
graphics_shape = if physics_shape.kind_of? Box
|
31
|
+
SlickPolygon.new(physics_shape.get_points(body.position, body.rotation).map{|point| [point.x, point.y]}.flatten.to_java(:float))
|
32
|
+
elsif physics_shape.kind_of? PhysPolygon
|
33
|
+
SlickPolygon.new(physics_shape.get_vertices(body.position, body.rotation).map{|point| [point.x, point.y]}.flatten.to_java(:float))
|
34
|
+
elsif physics_shape.kind_of? PhysCircle
|
35
|
+
SlickCircle.new(body.position.x, body.position.y, physics_shape.radius)
|
36
|
+
# elsif physics_shape.kind_of? PhysLine
|
37
|
+
# SlickLine.new(body_position.x, )
|
38
|
+
else
|
39
|
+
raise "#{self.class} does not know how to draw the shape #{physics_shape.class}"
|
40
|
+
end
|
41
|
+
graphics.draw(graphics_shape)
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#Makes an object draw its collisions on the screen.
|
2
|
+
class DebugTangible < Jemini::Behavior
|
3
|
+
#declared_methods :draw
|
4
|
+
PhysVector = Java::net::phys2d::math::Vector2f
|
5
|
+
SlickVector = Java::org::newdawn::slick::geom::Vector2f
|
6
|
+
|
7
|
+
def load
|
8
|
+
game_state.manager(:render).on_after_render do |graphics|
|
9
|
+
draw(graphics)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def unload
|
14
|
+
# Remove listener for after render
|
15
|
+
end
|
16
|
+
|
17
|
+
def draw(graphics)
|
18
|
+
#TODO: Support joints and composite bodies(?)
|
19
|
+
tangible_shape = @game_object.instance_variable_get(:@__behaviors)[:Tangible].instance_variable_get(:@tangible_shape)
|
20
|
+
graphics_shape = if tangible_shape.kind_of? TangibleBox
|
21
|
+
Java::org.newdawn.slick.geom.Polygon.new(tangible_shape.get_points(@game_object.top_left_position, 0).map{|point| [point.x, point.y]}.flatten.to_java(:float))
|
22
|
+
# elsif tangible_shape.kind_of?(Java::net.phys2d.raw.shapes.Polygon)
|
23
|
+
# Java::org.newdawn.slick.geom.Polygon.new(tangible_shape.get_vertices(body.position, body.rotation).map{|point| [point.x, point.y]}.flatten.to_java(:float))
|
24
|
+
# elsif tangible_shape.kind_of? Java::net.phys2d.raw.shapes.Circle
|
25
|
+
# Java::org.newdawn.slick.geom.Circle.new(body.position.x, body.position.y, tangible_shape.radius)
|
26
|
+
else
|
27
|
+
raise "#{self.class} does not know how to draw the shape #{tangible_shape.class}"
|
28
|
+
end
|
29
|
+
graphics.draw(graphics_shape)
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'behaviors/drawable'
|
2
|
+
|
3
|
+
#Makes an object draw itself as a bitmap image.
|
4
|
+
class DrawableImage < Drawable
|
5
|
+
include_class 'org.newdawn.slick.Image'
|
6
|
+
depends_on :Spatial
|
7
|
+
attr_accessor :image, :color, :texture_coords, :image_size
|
8
|
+
alias_method :set_image_size, :image_size=
|
9
|
+
wrap_with_callbacks :draw
|
10
|
+
|
11
|
+
def load
|
12
|
+
@color = Color.new(1.0, 1.0, 1.0, 1.0)
|
13
|
+
@texture_coords = [Vector.new(0.0, 0.0), Vector.new(1.0, 1.0)]
|
14
|
+
@rotation = 0.0
|
15
|
+
end
|
16
|
+
|
17
|
+
#Takes a reference to an image loaded via the resource manager, and sets the bitmap.
|
18
|
+
def image=(reference)
|
19
|
+
store_image(game_state.manager(:resource).get_image(reference))
|
20
|
+
end
|
21
|
+
alias_method :set_image, :image=
|
22
|
+
|
23
|
+
#Assign a Color to the image.
|
24
|
+
def color=(color)
|
25
|
+
@color = color
|
26
|
+
end
|
27
|
+
alias_method :set_color, :color=
|
28
|
+
|
29
|
+
#Increase or decrease horizontal and vertical scale for the image. 1.0 is identical to the current scale. If y_scale is omitted, x_scale is used for both axes.
|
30
|
+
#TODO: Take vectors for first args as well
|
31
|
+
def image_scaling(x_scale, y_scale = nil)
|
32
|
+
y_scale = x_scale if y_scale.nil?
|
33
|
+
store_image(@image.get_scaled_copy(x_scale.to_f * image_size.x, y_scale.to_f * image_size.y))
|
34
|
+
end
|
35
|
+
|
36
|
+
#Set horizontal and vertical scale for the image relative to the original. 1.0 is original scale. If y_scale is omitted, x_scale is used for both axes.
|
37
|
+
#TODO: Take vectors for first args as well
|
38
|
+
def scale_image_from_original(x_scale, y_scale = nil)
|
39
|
+
y_scale = x_scale if y_scale.nil?
|
40
|
+
@original_image = @image.copy if @original_image.nil?
|
41
|
+
store_image(@original_image.get_scaled_copy(x_scale.to_f * @original_image.width, y_scale.to_f * @original_image.height))
|
42
|
+
end
|
43
|
+
|
44
|
+
# WARNING: Using Slick's image for rotation can cause some odd quirks with it
|
45
|
+
# not quite rotating correctly (especially noticable around 180 degress).
|
46
|
+
# @rotation stands alone for this reason, instead of using Slick's rotation
|
47
|
+
def image_rotation
|
48
|
+
@rotation
|
49
|
+
end
|
50
|
+
|
51
|
+
def image_rotation=(rotation)
|
52
|
+
@rotation = rotation
|
53
|
+
end
|
54
|
+
alias_method :set_image_rotation, :image_rotation=
|
55
|
+
|
56
|
+
#Increment the image rotation.
|
57
|
+
def add_rotation(rotation)
|
58
|
+
@rotation += rotation
|
59
|
+
end
|
60
|
+
|
61
|
+
#Flip the texture horizontally.
|
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
|
+
#Flip the texture vertically.
|
67
|
+
def flip_vertically
|
68
|
+
@texture_coords[1].y, @texture_coords[0].y = @texture_coords[0].y, @texture_coords[1].y
|
69
|
+
end
|
70
|
+
|
71
|
+
#Returns a Vector with the x/y coordinates of the image's top left corner.
|
72
|
+
def top_left_position
|
73
|
+
#Vector.new(center_position.x - image_size.x / 2.0, center_position.y - image_size.y / 2.0)
|
74
|
+
Vector.new(@game_object.x - image_size.x / 2.0, @game_object.y - image_size.y / 2.0)
|
75
|
+
end
|
76
|
+
|
77
|
+
#Takes either a single Vector or the x/y coordinates to move the image's top left corner to.
|
78
|
+
def move_by_top_left(move_x_or_vector, move_y = nil)
|
79
|
+
half_width = image_size.x / 2.0
|
80
|
+
half_height = image_size.y / 2.0
|
81
|
+
if move_y.nil?
|
82
|
+
@game_object.move(move_x_or_vector.x + half_width, move_x_or_vector.y + half_height)
|
83
|
+
else
|
84
|
+
@game_object.move(move_x_or_vector + half_width, move_y + half_height)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
#Draw the image to the given graphic context.
|
89
|
+
def draw(graphics)
|
90
|
+
return if @image.nil? || @image_size.nil?
|
91
|
+
half_width = image_size.x / 2.0
|
92
|
+
half_height = image_size.y / 2.0
|
93
|
+
center_x = @game_object.x - half_width
|
94
|
+
center_y = @game_object.y - half_height
|
95
|
+
unless 0 == @rotation
|
96
|
+
graphics.rotate @game_object.x, @game_object.y, @rotation
|
97
|
+
end
|
98
|
+
@image.draw(center_x, center_y, @game_object.x + half_width, @game_object.y + half_height,
|
99
|
+
@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,
|
100
|
+
@color.native_color)
|
101
|
+
graphics.reset_transform
|
102
|
+
end
|
103
|
+
|
104
|
+
private
|
105
|
+
|
106
|
+
def store_image(value)
|
107
|
+
@image = value
|
108
|
+
set_image_size(Vector.new(@image.width, @image.height))
|
109
|
+
@image
|
110
|
+
end
|
111
|
+
end
|