metro 0.3.3 → 0.3.4
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/changelog.md +8 -1
- data/lib/core_ext/class.rb +14 -0
- data/lib/metro.rb +1 -0
- data/lib/metro/events/event_data.rb +3 -4
- data/lib/metro/events/event_state_manager.rb +63 -0
- data/lib/metro/events/events.rb +3 -0
- data/lib/metro/events/hit_list.rb +4 -5
- data/lib/metro/events/unknown_sender.rb +1 -1
- data/lib/metro/models/model.rb +14 -25
- data/lib/metro/models/model_factory.rb +1 -1
- data/lib/metro/models/models.rb +62 -0
- data/lib/metro/models/properties/position_property.rb +1 -1
- data/lib/metro/models/ui/animated_sprite.rb +85 -0
- data/lib/metro/models/ui/border.rb +44 -18
- data/lib/metro/models/ui/fps.rb +1 -1
- data/lib/metro/models/ui/generic.rb +24 -3
- data/lib/metro/models/ui/model_label.rb +1 -1
- data/lib/metro/models/ui/model_labeler.rb +2 -2
- data/lib/metro/models/ui/rectangle.rb +1 -1
- data/lib/metro/models/ui/sprite.rb +79 -0
- data/lib/metro/models/ui/ui.rb +12 -0
- data/lib/metro/scene.rb +13 -61
- data/lib/metro/scenes.rb +11 -13
- data/lib/metro/transitions/edit_transition_scene.rb +2 -2
- data/lib/metro/units/calculation_validations.rb +74 -0
- data/lib/metro/units/dimensions.rb +11 -19
- data/lib/metro/units/point.rb +6 -22
- data/lib/metro/units/rectangle_bounds.rb +10 -6
- data/lib/metro/units/scale.rb +7 -0
- data/lib/metro/units/units.rb +1 -0
- data/lib/metro/version.rb +1 -1
- data/lib/metro/window.rb +7 -3
- data/lib/setup_handlers/reload_game_on_game_file_changes.rb +6 -6
- data/lib/templates/game/models/hero.rb +35 -6
- data/lib/templates/model.rb.tt +1 -1
- data/spec/core_ext/string_spec.rb +0 -20
- data/spec/metro/units/point_spec.rb +132 -0
- data/spec/setup_handlers/exit_if_dry_run_spec.rb +27 -0
- data/spec/setup_handlers/reload_game_on_game_file_changes_spec.rb +68 -0
- metadata +21 -9
data/lib/metro/models/ui/fps.rb
CHANGED
@@ -35,9 +35,30 @@ module Metro
|
|
35
35
|
private
|
36
36
|
|
37
37
|
def cannot_draw_message
|
38
|
-
|
39
|
-
|
40
|
-
|
38
|
+
%{Unable to draw #{name} in #{scene}
|
39
|
+
|
40
|
+
The actor named '#{name}' does not specify a suitable model so it could not be drawn in the scene.
|
41
|
+
|
42
|
+
#{properties}
|
43
|
+
|
44
|
+
Did you mean to use one of the following models:
|
45
|
+
|
46
|
+
Models defined in #{Game.name}:
|
47
|
+
|
48
|
+
#{user_defined_models.join(', ')}
|
49
|
+
|
50
|
+
Models defined in Metro:
|
51
|
+
|
52
|
+
#{metro_models.join(', ')}
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
def metro_models
|
57
|
+
Models.list.find_all {|m| m =~ /metro(::|\/).+(::|\/).+/i }
|
58
|
+
end
|
59
|
+
|
60
|
+
def user_defined_models
|
61
|
+
Models.list - metro_models
|
41
62
|
end
|
42
63
|
|
43
64
|
end
|
@@ -9,7 +9,7 @@ module Metro
|
|
9
9
|
# the bounding boxes and labeles around all the actors within the scene
|
10
10
|
# being edited.
|
11
11
|
#
|
12
|
-
class ModelLabeler <
|
12
|
+
class ModelLabeler < Model
|
13
13
|
|
14
14
|
# @attribute
|
15
15
|
# The color use for the border surrounding each actor and the background
|
@@ -58,7 +58,7 @@ module Metro
|
|
58
58
|
label = labels[drawer.name]
|
59
59
|
|
60
60
|
unless label
|
61
|
-
label = create "metro::ui::
|
61
|
+
label = create "metro::ui::model_label", target: drawer
|
62
62
|
labels[drawer.name] = label
|
63
63
|
end
|
64
64
|
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module Metro
|
2
|
+
module UI
|
3
|
+
|
4
|
+
#
|
5
|
+
# A sprite is a Metro model that is specially designed to draw and manage
|
6
|
+
# an image. A sprite maintains an image, location information, and rotation.
|
7
|
+
#
|
8
|
+
class Sprite < Model
|
9
|
+
|
10
|
+
# @attribute
|
11
|
+
# The image that will be drawn for the sprite
|
12
|
+
property :image
|
13
|
+
|
14
|
+
# @attribute
|
15
|
+
# The point at which the sprite should be drawn
|
16
|
+
property :position
|
17
|
+
|
18
|
+
# @attribute
|
19
|
+
# This is the color of the spirte. The color usually remains white, and
|
20
|
+
# the color property is implemented by the `alpha` value is the one thing
|
21
|
+
# that is altered to fade in and fade out the sprite.
|
22
|
+
property :color
|
23
|
+
|
24
|
+
# @attribute
|
25
|
+
# The scale at which to draw the sprite. This is default scale of 1.
|
26
|
+
property :scale
|
27
|
+
|
28
|
+
# @attribute
|
29
|
+
# The center, horizontal position, as expressed in a ratio, of the image.
|
30
|
+
property :center_x, type: :numeric, default: 0.5
|
31
|
+
|
32
|
+
# @attribute
|
33
|
+
# The center, vertical position, as expressed in a ratio, of the image.
|
34
|
+
property :center_y, type: :numeric, default: 0.5
|
35
|
+
|
36
|
+
# @attribute
|
37
|
+
# The angle at which the sprite should be drawn. This is by default 0.
|
38
|
+
property :angle
|
39
|
+
|
40
|
+
# @attribute
|
41
|
+
# The height and width of the sprite is based on the image of the sprite.
|
42
|
+
property :dimensions do
|
43
|
+
image.dimensions
|
44
|
+
end
|
45
|
+
|
46
|
+
# @return [RectangleBounds] the bounds of the sprite.
|
47
|
+
def bounds
|
48
|
+
Bounds.new left: left, right: right, top: top, bottom: bottom
|
49
|
+
end
|
50
|
+
|
51
|
+
# @return [Float] the left-most x position of the sprite
|
52
|
+
def left
|
53
|
+
x - width * center_x
|
54
|
+
end
|
55
|
+
|
56
|
+
# @return [Float] the right-most x position of the sprite
|
57
|
+
def right
|
58
|
+
left + width * x_factor
|
59
|
+
end
|
60
|
+
|
61
|
+
# @return [Float] the top-most y position of the sprite
|
62
|
+
def top
|
63
|
+
y - height * center_y
|
64
|
+
end
|
65
|
+
|
66
|
+
# @return [Float] the bottom-most y position of the sprite
|
67
|
+
def bottom
|
68
|
+
top + height * y_factor
|
69
|
+
end
|
70
|
+
|
71
|
+
#
|
72
|
+
# By default the sprite will draw the image defined for it.
|
73
|
+
#
|
74
|
+
def draw
|
75
|
+
image.draw_rot x, y, z_order, angle, center_x, center_y, x_factor, y_factor, color
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require_relative 'generic'
|
2
|
+
require_relative 'label'
|
3
|
+
require_relative 'menu'
|
4
|
+
require_relative 'image'
|
5
|
+
require_relative 'rectangle'
|
6
|
+
require_relative 'grid_drawer'
|
7
|
+
require_relative 'border'
|
8
|
+
require_relative 'model_label'
|
9
|
+
require_relative 'model_labeler'
|
10
|
+
require_relative 'fps'
|
11
|
+
require_relative 'sprite'
|
12
|
+
require_relative 'animated_sprite'
|
data/lib/metro/scene.rb
CHANGED
@@ -1,9 +1,5 @@
|
|
1
1
|
require_relative 'views/scene_view'
|
2
|
-
|
3
|
-
require_relative 'events/has_events'
|
4
|
-
require_relative 'events/event_relay'
|
5
|
-
require_relative 'events/unknown_sender'
|
6
|
-
|
2
|
+
require_relative 'events/events'
|
7
3
|
require_relative 'models/draws'
|
8
4
|
|
9
5
|
require_relative 'animation/has_animations'
|
@@ -19,7 +15,6 @@ module Metro
|
|
19
15
|
# @see #show
|
20
16
|
# @see #update
|
21
17
|
# @see #draw
|
22
|
-
# @see #events
|
23
18
|
#
|
24
19
|
# A fair number of private methods within Scene are prefaced with an underscore.
|
25
20
|
# These methods often call non-underscored methods within those methods. This allows
|
@@ -102,16 +97,12 @@ module Metro
|
|
102
97
|
end
|
103
98
|
|
104
99
|
#
|
105
|
-
# Post a custom notification event. This will trigger
|
106
|
-
# for
|
100
|
+
# Post a custom notification event. This will trigger an event for all the
|
101
|
+
# objects that are registered for notification with the current state.
|
107
102
|
#
|
108
103
|
def notification(event,sender=nil)
|
109
|
-
|
110
104
|
sender = sender || UnknownSender
|
111
|
-
|
112
|
-
event_relays.each do |relay|
|
113
|
-
relay.fire_events_for_notification(event,sender)
|
114
|
-
end
|
105
|
+
state.fire_events_for_notification(event,sender)
|
115
106
|
end
|
116
107
|
|
117
108
|
#
|
@@ -203,7 +194,8 @@ module Metro
|
|
203
194
|
def window=(window)
|
204
195
|
@window = window
|
205
196
|
|
206
|
-
|
197
|
+
state.window = window
|
198
|
+
state.clear
|
207
199
|
|
208
200
|
register_events!
|
209
201
|
register_actors!
|
@@ -335,11 +327,9 @@ module Metro
|
|
335
327
|
#
|
336
328
|
# Captures all classes that subclass Scene.
|
337
329
|
#
|
338
|
-
# @see #self.scenes
|
339
|
-
#
|
340
330
|
def self.inherited(base)
|
341
331
|
scenes << base.to_s
|
342
|
-
Scenes.
|
332
|
+
Scenes.add(base)
|
343
333
|
end
|
344
334
|
|
345
335
|
#
|
@@ -455,58 +445,20 @@ module Metro
|
|
455
445
|
# be mapped to the specified target.
|
456
446
|
#
|
457
447
|
def register_events_for_target(target,events)
|
458
|
-
|
459
|
-
|
460
|
-
events.each do |target_event|
|
461
|
-
target_relay.send target_event.event, *target_event.buttons, &target_event.block
|
462
|
-
end
|
463
|
-
|
464
|
-
event_relays.push(target_relay)
|
448
|
+
state.add_events_for_target(target,events)
|
465
449
|
end
|
466
450
|
|
467
451
|
#
|
468
|
-
# The
|
469
|
-
# all the gamepad and keyboard events defined. By default a scene
|
470
|
-
#
|
452
|
+
# The event state manager is configured through the {#events} method, which
|
453
|
+
# stores all the gamepad and keyboard events defined. By default a scene is
|
454
|
+
# placed in the default state and events that are added to this basic state.
|
471
455
|
#
|
472
456
|
# @see Events
|
473
|
-
# @see #add_event_relay
|
474
457
|
#
|
475
|
-
def
|
476
|
-
@
|
458
|
+
def state
|
459
|
+
@event_state_manager ||= EventStateManager.new
|
477
460
|
end
|
478
461
|
|
479
|
-
#
|
480
|
-
# This method is called during a scene update and will fire all the events
|
481
|
-
# that have been defined for all held buttons for all defined event relays.
|
482
|
-
#
|
483
|
-
def fire_events_for_held_buttons
|
484
|
-
event_relays.each do |relay|
|
485
|
-
relay.fire_events_for_held_buttons
|
486
|
-
end
|
487
|
-
end
|
488
|
-
|
489
|
-
#
|
490
|
-
# This method is called before a scene update and passes the button up events
|
491
|
-
# to each of the defined event relays.
|
492
|
-
#
|
493
|
-
def button_up(id)
|
494
|
-
event_relays.each do |relay|
|
495
|
-
relay.fire_button_up(id)
|
496
|
-
end
|
497
|
-
end
|
498
|
-
|
499
|
-
#
|
500
|
-
# This method is called before a scene update and passes the button down events
|
501
|
-
# to each of the defined event relays.
|
502
|
-
#
|
503
|
-
def button_down(id)
|
504
|
-
event_relays.each do |relay|
|
505
|
-
relay.fire_button_down(id)
|
506
|
-
end
|
507
|
-
end
|
508
|
-
|
509
|
-
|
510
462
|
#
|
511
463
|
# A Scene represented as a hash currently only contains the drawers
|
512
464
|
#
|
data/lib/metro/scenes.rb
CHANGED
@@ -33,7 +33,7 @@ module Metro
|
|
33
33
|
#
|
34
34
|
# @param [Scene] scene the scene to be added to the hash of Scenes.
|
35
35
|
#
|
36
|
-
def
|
36
|
+
def add(scene)
|
37
37
|
all_scenes_for(scene).each { |scene| scenes_hash[scene.scene_name] = scene.to_s }
|
38
38
|
end
|
39
39
|
|
@@ -44,7 +44,14 @@ module Metro
|
|
44
44
|
# @return the Scene class that is found matching the specified scene name.
|
45
45
|
#
|
46
46
|
def find(scene_name)
|
47
|
-
|
47
|
+
scenes_hash[scene_name].constantize
|
48
|
+
end
|
49
|
+
|
50
|
+
#
|
51
|
+
# @return [Array<String>] all the names supported by the scenes hash.
|
52
|
+
#
|
53
|
+
def list
|
54
|
+
scenes_hash.keys
|
48
55
|
end
|
49
56
|
|
50
57
|
#
|
@@ -119,7 +126,7 @@ module Metro
|
|
119
126
|
#
|
120
127
|
def hash_with_missing_scene_default
|
121
128
|
hash = HashWithIndifferentAccess.new do |hash,key|
|
122
|
-
missing_scene =
|
129
|
+
missing_scene = hash[:missing_scene].constantize
|
123
130
|
missing_scene.missing_scene = key.to_sym
|
124
131
|
missing_scene
|
125
132
|
end
|
@@ -136,20 +143,11 @@ module Metro
|
|
136
143
|
#
|
137
144
|
def all_scenes_for(scenes)
|
138
145
|
Array(scenes).map do |scene_class_name|
|
139
|
-
scene =
|
146
|
+
scene = scene_class_name.constantize
|
140
147
|
[ scene ] + all_scenes_for(scene.scenes)
|
141
148
|
end.flatten.compact
|
142
149
|
end
|
143
150
|
|
144
|
-
#
|
145
|
-
# @param [String,Symbol] class_name the name of the class that you want the class
|
146
|
-
#
|
147
|
-
# @return the class with the given class name
|
148
|
-
#
|
149
|
-
def scene_class(class_or_class_name)
|
150
|
-
class_or_class_name.class == Class ? class_or_class_name : class_or_class_name.constantize
|
151
|
-
end
|
152
|
-
|
153
151
|
end
|
154
152
|
end
|
155
153
|
|
@@ -28,8 +28,8 @@ module Metro
|
|
28
28
|
# easier to dup scenes.
|
29
29
|
#
|
30
30
|
self.class.drawings.clear
|
31
|
-
self.class.draw :overlay, model: "metro::ui::
|
32
|
-
self.class.draw :labeler, model: "metro::ui::
|
31
|
+
self.class.draw :overlay, model: "metro::ui::grid_drawer"
|
32
|
+
self.class.draw :labeler, model: "metro::ui::model_labeler"
|
33
33
|
add_actors_to_scene
|
34
34
|
after_initialize
|
35
35
|
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Metro
|
2
|
+
module Units
|
3
|
+
module CalculationValidations
|
4
|
+
|
5
|
+
#
|
6
|
+
# @param [Object] value the other object that needs to be validated.
|
7
|
+
#
|
8
|
+
def check_calculation_requirements(value)
|
9
|
+
if calculation_requirements.find { |method| ! value.respond_to?(method) }
|
10
|
+
raise "Unable to perform operation with #{value} #{value.class} It is missing a property #{calculation_requirements.join(",")}"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
#
|
15
|
+
# @return [Array] an array of methods that are required to be on the
|
16
|
+
# object for it to be correctly calculated.
|
17
|
+
#
|
18
|
+
# @note this method is intended to be defined in the including class. This
|
19
|
+
# method is included here when one has not been provided.
|
20
|
+
def calculation_requirements
|
21
|
+
[]
|
22
|
+
end
|
23
|
+
|
24
|
+
#
|
25
|
+
# Add this object to another object.
|
26
|
+
#
|
27
|
+
# @return a new object that is the sum of the two objects
|
28
|
+
#
|
29
|
+
def +(value)
|
30
|
+
self.class.new *calculate(value,:+)
|
31
|
+
end
|
32
|
+
|
33
|
+
#
|
34
|
+
# Subtract the other object from this object.
|
35
|
+
#
|
36
|
+
# @return a new object that is the difference of the original object
|
37
|
+
# and the value specified.
|
38
|
+
#
|
39
|
+
def -(value)
|
40
|
+
self.class.new *calculate(value,:-)
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
# Multiply this object and another object.
|
45
|
+
#
|
46
|
+
# @return a new object that is the product of the two objects.
|
47
|
+
#
|
48
|
+
def *(value)
|
49
|
+
self.class.new *calculate(value,:*)
|
50
|
+
end
|
51
|
+
|
52
|
+
#
|
53
|
+
# This generic method will perform the calculation defined by the
|
54
|
+
# operation for all the calculation requirements defined.
|
55
|
+
#
|
56
|
+
# @param [value] value this is the other value that is being added,
|
57
|
+
# subtracted, etc. to the current object.
|
58
|
+
# @param [Symbol] operation this is the mathematical operation that
|
59
|
+
# is being performed between all the calc requirements of the current
|
60
|
+
# object and other value.
|
61
|
+
#
|
62
|
+
# @return [Array] an array of reults from the calculations of all the
|
63
|
+
# requirements.
|
64
|
+
#
|
65
|
+
def calculate(value,operation)
|
66
|
+
check_calculation_requirements(value)
|
67
|
+
calculation_requirements.map do |requirement|
|
68
|
+
send(requirement).send(operation,value.send(requirement))
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -5,6 +5,7 @@ module Metro
|
|
5
5
|
# Represents an object that contains both the width and height.
|
6
6
|
#
|
7
7
|
class Dimensions < Struct.new(:width,:height)
|
8
|
+
include CalculationValidations
|
8
9
|
|
9
10
|
#
|
10
11
|
# Create a dimensions objects with zero width and zero height.
|
@@ -37,30 +38,21 @@ module Metro
|
|
37
38
|
end
|
38
39
|
|
39
40
|
#
|
40
|
-
#
|
41
|
-
# dimensions like structure is anything that responds to width and height.
|
41
|
+
# Compare the dimension to another dimensions-like structure.
|
42
42
|
#
|
43
|
-
# @return
|
43
|
+
# @return [Fixnum] -1 if the dimensions is smaller than the other dimension,
|
44
|
+
# 0 if the dimensions are exactly the same, 1 if the dimensions are bigger
|
45
|
+
# then the other dimensions.
|
44
46
|
#
|
45
|
-
def
|
46
|
-
|
47
|
-
|
47
|
+
def <=>(value)
|
48
|
+
check_calculation_requirements(value)
|
49
|
+
(width * height) <=> (value.width * value.height)
|
48
50
|
end
|
49
51
|
|
50
|
-
|
51
|
-
# Subtract the dimensions-like structure from this dimension. A
|
52
|
-
# dimensions like structure is anything that responds to width and height.
|
53
|
-
#
|
54
|
-
# @return a new dimensions which is the different of the two dimensions
|
55
|
-
#
|
56
|
-
def -(value)
|
57
|
-
raise "Unable to subtract from these dimensions with #{value} #{value.class}" if [ :width, :height ].find { |method| ! value.respond_to?(method) }
|
58
|
-
self.class.of (width - value.width.to_f), (height - value.height.to_f)
|
59
|
-
end
|
52
|
+
private
|
60
53
|
|
61
|
-
def
|
62
|
-
|
63
|
-
(width * height) <=> (value.width * value.height)
|
54
|
+
def calculation_requirements
|
55
|
+
[ :width, :height ]
|
64
56
|
end
|
65
57
|
|
66
58
|
end
|