metro-ld25 0.3.3

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.
Files changed (177) hide show
  1. data/.gitignore +17 -0
  2. data/.rspec +2 -0
  3. data/.rvmrc +1 -0
  4. data/.travis.yml +6 -0
  5. data/Gemfile +12 -0
  6. data/Guardfile +4 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +189 -0
  9. data/Rakefile +18 -0
  10. data/bin/metro +16 -0
  11. data/changelog.md +157 -0
  12. data/lib/assets/menu-movement.wav +0 -0
  13. data/lib/assets/menu-selection.wav +0 -0
  14. data/lib/assets/missing.ogg +0 -0
  15. data/lib/assets/missing.png +0 -0
  16. data/lib/assets/missing.wav +0 -0
  17. data/lib/assets/missing_animation.png +0 -0
  18. data/lib/commands/generate_game.rb +13 -0
  19. data/lib/commands/generate_model.rb +25 -0
  20. data/lib/commands/generate_scene.rb +36 -0
  21. data/lib/commands/generate_view.rb +21 -0
  22. data/lib/commands/thor.rb +83 -0
  23. data/lib/core_ext/class.rb +14 -0
  24. data/lib/core_ext/numeric.rb +59 -0
  25. data/lib/gosu_ext/color.rb +62 -0
  26. data/lib/gosu_ext/gosu_constants.rb +53 -0
  27. data/lib/locale/en.yml +35 -0
  28. data/lib/locale/locale.rb +1 -0
  29. data/lib/metro.rb +140 -0
  30. data/lib/metro/animation.rb +135 -0
  31. data/lib/metro/animation/after_interval_factory.rb +12 -0
  32. data/lib/metro/animation/animation_factory.rb +15 -0
  33. data/lib/metro/animation/easing/ease_in.rb +15 -0
  34. data/lib/metro/animation/easing/easing.rb +51 -0
  35. data/lib/metro/animation/easing/linear.rb +15 -0
  36. data/lib/metro/animation/has_animations.rb +70 -0
  37. data/lib/metro/animation/implicit_animation.rb +100 -0
  38. data/lib/metro/animation/on_update_operation.rb +96 -0
  39. data/lib/metro/animation/scene_animation.rb +16 -0
  40. data/lib/metro/asset_path.rb +97 -0
  41. data/lib/metro/events/control_definition.rb +11 -0
  42. data/lib/metro/events/controls.rb +42 -0
  43. data/lib/metro/events/event_data.rb +60 -0
  44. data/lib/metro/events/event_dictionary.rb +52 -0
  45. data/lib/metro/events/event_factory.rb +17 -0
  46. data/lib/metro/events/event_relay.rb +300 -0
  47. data/lib/metro/events/event_state_manager.rb +63 -0
  48. data/lib/metro/events/events.rb +3 -0
  49. data/lib/metro/events/has_events.rb +108 -0
  50. data/lib/metro/events/hit_list.rb +75 -0
  51. data/lib/metro/events/unknown_sender.rb +5 -0
  52. data/lib/metro/font.rb +69 -0
  53. data/lib/metro/game.rb +102 -0
  54. data/lib/metro/game/dsl.rb +68 -0
  55. data/lib/metro/image.rb +68 -0
  56. data/lib/metro/logging.rb +33 -0
  57. data/lib/metro/missing_scene.rb +21 -0
  58. data/lib/metro/models/audio/song.rb +33 -0
  59. data/lib/metro/models/draws.rb +86 -0
  60. data/lib/metro/models/key_value_coding.rb +38 -0
  61. data/lib/metro/models/model.rb +236 -0
  62. data/lib/metro/models/model_factory.rb +32 -0
  63. data/lib/metro/models/models.rb +62 -0
  64. data/lib/metro/models/properties/animation_property.rb +115 -0
  65. data/lib/metro/models/properties/array_property.rb +24 -0
  66. data/lib/metro/models/properties/boolean_property.rb +27 -0
  67. data/lib/metro/models/properties/color_property.rb +116 -0
  68. data/lib/metro/models/properties/dimensions_property.rb +84 -0
  69. data/lib/metro/models/properties/font_property.rb +130 -0
  70. data/lib/metro/models/properties/image_property.rb +96 -0
  71. data/lib/metro/models/properties/model_property.rb +84 -0
  72. data/lib/metro/models/properties/numeric_property.rb +29 -0
  73. data/lib/metro/models/properties/options_property/no_option.rb +29 -0
  74. data/lib/metro/models/properties/options_property/options.rb +94 -0
  75. data/lib/metro/models/properties/options_property/options_property.rb +125 -0
  76. data/lib/metro/models/properties/position_property.rb +90 -0
  77. data/lib/metro/models/properties/property.rb +221 -0
  78. data/lib/metro/models/properties/property_owner.rb +137 -0
  79. data/lib/metro/models/properties/sample_property.rb +84 -0
  80. data/lib/metro/models/properties/scale_property.rb +80 -0
  81. data/lib/metro/models/properties/song_property.rb +89 -0
  82. data/lib/metro/models/properties/text_property.rb +75 -0
  83. data/lib/metro/models/ui/animated_sprite.rb +85 -0
  84. data/lib/metro/models/ui/border.rb +95 -0
  85. data/lib/metro/models/ui/fps.rb +54 -0
  86. data/lib/metro/models/ui/generic.rb +66 -0
  87. data/lib/metro/models/ui/grid_drawer.rb +74 -0
  88. data/lib/metro/models/ui/image.rb +87 -0
  89. data/lib/metro/models/ui/label.rb +175 -0
  90. data/lib/metro/models/ui/menu.rb +214 -0
  91. data/lib/metro/models/ui/model_label.rb +65 -0
  92. data/lib/metro/models/ui/model_labeler.rb +79 -0
  93. data/lib/metro/models/ui/rectangle.rb +59 -0
  94. data/lib/metro/models/ui/sprite.rb +79 -0
  95. data/lib/metro/models/ui/tile_map.rb +162 -0
  96. data/lib/metro/models/ui/ui.rb +13 -0
  97. data/lib/metro/parameters/command_line_args_parser.rb +68 -0
  98. data/lib/metro/parameters/options.rb +25 -0
  99. data/lib/metro/parameters/parameters.rb +2 -0
  100. data/lib/metro/sample.rb +40 -0
  101. data/lib/metro/scene.rb +477 -0
  102. data/lib/metro/scenes.rb +154 -0
  103. data/lib/metro/song.rb +56 -0
  104. data/lib/metro/template_message.rb +60 -0
  105. data/lib/metro/transitions/edit_transition_scene.rb +100 -0
  106. data/lib/metro/transitions/fade_transition_scene.rb +66 -0
  107. data/lib/metro/transitions/scene_transitions.rb +44 -0
  108. data/lib/metro/transitions/transition_scene.rb +19 -0
  109. data/lib/metro/units/bounds.rb +8 -0
  110. data/lib/metro/units/calculation_validations.rb +74 -0
  111. data/lib/metro/units/dimensions.rb +60 -0
  112. data/lib/metro/units/point.rb +51 -0
  113. data/lib/metro/units/rectangle_bounds.rb +85 -0
  114. data/lib/metro/units/scale.rb +46 -0
  115. data/lib/metro/units/units.rb +6 -0
  116. data/lib/metro/version.rb +32 -0
  117. data/lib/metro/views/json_view.rb +60 -0
  118. data/lib/metro/views/no_view.rb +34 -0
  119. data/lib/metro/views/parsers.rb +42 -0
  120. data/lib/metro/views/scene_view.rb +107 -0
  121. data/lib/metro/views/view.rb +133 -0
  122. data/lib/metro/views/writers.rb +43 -0
  123. data/lib/metro/views/yaml_view.rb +94 -0
  124. data/lib/metro/window.rb +94 -0
  125. data/lib/setup_handlers/exit_if_dry_run.rb +26 -0
  126. data/lib/setup_handlers/game_execution.rb +65 -0
  127. data/lib/setup_handlers/load_game_configuration.rb +65 -0
  128. data/lib/setup_handlers/load_game_files.rb +101 -0
  129. data/lib/setup_handlers/move_to_game_directory.rb +25 -0
  130. data/lib/setup_handlers/reload_game_on_game_file_changes.rb +79 -0
  131. data/lib/templates/game/README.md.tt +52 -0
  132. data/lib/templates/game/assets/brand.jpg +0 -0
  133. data/lib/templates/game/assets/hero.png +0 -0
  134. data/lib/templates/game/lib/custom_easing.rb +32 -0
  135. data/lib/templates/game/metro.tt +63 -0
  136. data/lib/templates/game/models/hero.rb +62 -0
  137. data/lib/templates/game/scenes/brand_scene.rb +19 -0
  138. data/lib/templates/game/scenes/brand_to_title_scene.rb +13 -0
  139. data/lib/templates/game/scenes/first_scene.rb +28 -0
  140. data/lib/templates/game/scenes/game_scene.rb +43 -0
  141. data/lib/templates/game/scenes/title_scene.rb +15 -0
  142. data/lib/templates/game/views/brand.yaml +4 -0
  143. data/lib/templates/game/views/brand_to_title.yaml +8 -0
  144. data/lib/templates/game/views/first.yaml +26 -0
  145. data/lib/templates/game/views/title.yaml +11 -0
  146. data/lib/templates/message.erb +23 -0
  147. data/lib/templates/model.rb.tt +111 -0
  148. data/lib/templates/scene.rb.tt +140 -0
  149. data/lib/templates/view.yaml.tt +11 -0
  150. data/lib/tmxed_ext/tile_set.rb +34 -0
  151. data/metro.gemspec +56 -0
  152. data/spec/core_ext/numeric_spec.rb +78 -0
  153. data/spec/core_ext/string_spec.rb +33 -0
  154. data/spec/gosu_ext/color_spec.rb +80 -0
  155. data/spec/metro/events/event_state_manager_spec.rb +5 -0
  156. data/spec/metro/models/key_value_coding_spec.rb +61 -0
  157. data/spec/metro/models/properties/array_property_spec.rb +60 -0
  158. data/spec/metro/models/properties/color_property_spec.rb +85 -0
  159. data/spec/metro/models/properties/dimensions_spec.rb +29 -0
  160. data/spec/metro/models/properties/font_property_spec.rb +127 -0
  161. data/spec/metro/models/properties/numeric_property_spec.rb +46 -0
  162. data/spec/metro/models/properties/options_property/no_option_spec.rb +25 -0
  163. data/spec/metro/models/properties/options_property/options_property_spec.rb +133 -0
  164. data/spec/metro/models/properties/options_property/options_spec.rb +125 -0
  165. data/spec/metro/models/properties/position_property_spec.rb +90 -0
  166. data/spec/metro/models/ui/label_spec.rb +259 -0
  167. data/spec/metro/parameters/command_line_args_parser_spec.rb +42 -0
  168. data/spec/metro/scene_spec.rb +15 -0
  169. data/spec/metro/scene_views/json_view_spec.rb +27 -0
  170. data/spec/metro/scene_views/yaml_view_spec.rb +38 -0
  171. data/spec/metro/scenes_spec.rb +77 -0
  172. data/spec/metro/units/point_spec.rb +132 -0
  173. data/spec/metro/views/view_spec.rb +53 -0
  174. data/spec/setup_handlers/exit_if_dry_run_spec.rb +27 -0
  175. data/spec/setup_handlers/reload_game_on_game_file_changes_spec.rb +68 -0
  176. data/spec/spec_helper.rb +20 -0
  177. metadata +374 -0
@@ -0,0 +1,54 @@
1
+ module Metro
2
+ module UI
3
+
4
+ class FPS < Model
5
+
6
+ property :placement, type: :text, default: 'top'
7
+ property :color, default: "rgba(255,255,255,1.0)"
8
+
9
+ property :label, type: :model do
10
+ create "metro::ui::label", text: "FPS: 0", color: color
11
+ end
12
+
13
+ def valid_placements
14
+ @valid_placements ||= begin
15
+ {
16
+ top_left: { position: Game.bounds.top_left, align: 'left', vertical_align: 'top' },
17
+ top: { position: Point.at(Game.center.x, Game.bounds.top), align: 'center', vertical_align: 'top' },
18
+ top_right: { position: Game.bounds.top_right, align: 'right', vertical_align: 'top' },
19
+ right: { position: Point.at(Game.bounds.right, Game.center.y), align: 'right', vertical_align: 'center' },
20
+ bottom_right: { position: Game.bounds.bottom_right, align: 'right', vertical_align: 'bottom' },
21
+ bottom: { position: Point.at(Game.center.x, Game.bounds.bottom), align: 'right', vertical_align: 'bottom' },
22
+ bottom_left: { position: Game.bounds.bottom_right, align: 'left', vertical_align: 'bottom' },
23
+ left: { position: Point.at(Game.bounds.left, Game.center.y), align: 'left', vertical_align: 'center' }
24
+ }
25
+ end
26
+
27
+ @valid_placements.default = :top
28
+ @valid_placements
29
+ end
30
+
31
+ def show
32
+ place_label
33
+ end
34
+
35
+ def place_label
36
+ placement_hash = valid_placements[placement.to_sym]
37
+
38
+ label.align = placement_hash[:align]
39
+ label.vertical_align = placement_hash[:vertical_align]
40
+ label.position = placement_hash[:position]
41
+ end
42
+
43
+ def update
44
+ label.text = "FPS: #{Gosu.fps}"
45
+ end
46
+
47
+ def draw
48
+ label.draw
49
+ end
50
+
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,66 @@
1
+ module Metro
2
+ module UI
3
+
4
+ #
5
+ # Generic model is used when no model can be found.
6
+ #
7
+ # @example Defining an actor in a scene without the model
8
+ #
9
+ # class IntroScene < GameScene
10
+ #
11
+ # draw :game_title, text: "Super Game Title", position: Game.center
12
+ # color: "rgba(255,255,255,1.0)"
13
+ #
14
+ # end
15
+ #
16
+ # The above `game_title` actor was likely suppose to be a `metro::ui::label`, but
17
+ # the model was not specified. So this warning would be generated.
18
+ #
19
+ class Generic < Model
20
+
21
+ # @attribute
22
+ # Sets whether the generic model has warned the user in the logs about it
23
+ # being a generic model.
24
+ property :warned, type: :boolean, default: false
25
+
26
+ def show
27
+ self.saveable_to_view = false
28
+ end
29
+
30
+ def draw
31
+ log.warn cannot_draw_message unless warned
32
+ self.warned = true
33
+ end
34
+
35
+ private
36
+
37
+ def cannot_draw_message
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
62
+ end
63
+
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,74 @@
1
+ module Metro
2
+ module UI
3
+
4
+ #
5
+ # The grid drawer will draw a grid from the specified position out to the specified
6
+ # dimensions at the spacing interval provided. This is currently used when the edit
7
+ # mode is enabled.
8
+ #
9
+ # @example Drawing a white, translucent, 100 by 100 grid starting at (20,20).
10
+ #
11
+ # class BuildScene < GameScene
12
+ # draw :grid, model: "metro::ui::grid_drawer", position: "20,20",
13
+ # color: "rgba(255,255,255,0.5)", spacing: 20, dimensions: "100,100"
14
+ # end
15
+ #
16
+ class GridDrawer < Model
17
+
18
+ # @attribute
19
+ # The position to start drawing the grid
20
+ property :position, default: Point.at(0,0,100)
21
+
22
+ # @attribute
23
+ # The color of the grid lines
24
+ property :color, default: "rgba(255,255,255,0.1)"
25
+
26
+ # @attribute
27
+ # The interval which to draw the lines
28
+ property :spacing, type: :numeric, default: 10
29
+
30
+ # @attribute
31
+ # The dimension of the grid
32
+ property :dimensions do
33
+ Dimensions.of Game.width, Game.height
34
+ end
35
+
36
+ # @attribute
37
+ # This controls whether the grid should be drawn. By default
38
+ # the grid will be drawn.
39
+ property :enabled, type: :boolean, default: true
40
+
41
+ def show
42
+ self.saveable_to_view = false
43
+ end
44
+
45
+ def draw
46
+ return unless enabled
47
+ draw_horizontal_lines
48
+ draw_vertical_lines
49
+ end
50
+
51
+ private
52
+
53
+ def draw_vertical_lines
54
+ xs = (width / spacing + 1).to_i.times.map {|segment| segment * spacing }
55
+ xs.each do |x|
56
+ draw_line(x,1,x,height)
57
+ end
58
+ end
59
+
60
+ def draw_horizontal_lines
61
+ ys = (height / spacing + 1).to_i.times.map {|segment| segment * spacing }
62
+ ys.each do |y|
63
+ draw_line(1,y,width,y)
64
+ end
65
+ end
66
+
67
+ def draw_line(start_x,start_y,finish_x,finish_y)
68
+ window.draw_line(position.x + start_x, position.y + start_y, color,
69
+ position.x + finish_x, position.y + finish_y, color, 0, :additive)
70
+ end
71
+
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,87 @@
1
+ module Metro
2
+ module UI
3
+
4
+ #
5
+ # The image will draw an image with the specifie path, color, rotation, and scale.
6
+ #
7
+ # @example Drawing the 'player.png' image at (320,240)
8
+ #
9
+ # class MainScene < GameScene
10
+ # draw :player, model: "metro::ui::image", position: "320,240",
11
+ # image: "player.png"
12
+ # end
13
+ #
14
+ class Image < Model
15
+
16
+ # @attribute
17
+ # The position of the image
18
+ property :position
19
+
20
+ # @attribute
21
+ # The scale of the image
22
+ property :scale, default: Scale.one
23
+
24
+ # @attribute
25
+ # The color of the image, by default this is white to display the image
26
+ # as normal, but this can be used to augment the look of the image. Mostly
27
+ # color is use for the sub-property :alpha which allows an image to be
28
+ # faded-in and faded-out
29
+ property :color
30
+
31
+ # @attribute
32
+ # The angle at which to draw the image
33
+ property :angle, type: :numeric, default: 0
34
+
35
+ # @attribute
36
+ # The center x position of the image as expressed in a scale of from left
37
+ # to right (0.0 to 1.0).
38
+ property :center_x, type: :numeric, default: 0.5
39
+
40
+ # @attribute
41
+ # The center y position of the image as expressed in a scale of from top
42
+ # to bottom (0.0 to 1.0).
43
+ property :center_y, type: :numeric, default: 0.5
44
+
45
+ # @attribute
46
+ # The image asset to draw.
47
+ property :image
48
+
49
+ # @attribute
50
+ # The dimensions of the image.
51
+ property :dimensions do
52
+ image.dimensions
53
+ end
54
+
55
+ def bounds
56
+ Bounds.new left: left_x, right: right_x, top: top_y, bottom: bottom_y
57
+ end
58
+
59
+ def draw
60
+ image.draw_rot x, y, z_order,
61
+ angle.to_f,
62
+ center_x, center_y,
63
+ x_factor, y_factor,
64
+ color
65
+ end
66
+
67
+ private
68
+
69
+ def left_x
70
+ x - (width * center_x)
71
+ end
72
+
73
+ def right_x
74
+ left_x + width
75
+ end
76
+
77
+ def top_y
78
+ y - (height * center_y)
79
+ end
80
+
81
+ def bottom_y
82
+ top_y + height
83
+ end
84
+ end
85
+
86
+ end
87
+ end
@@ -0,0 +1,175 @@
1
+ module Metro
2
+ module UI
3
+
4
+ #
5
+ # The label will draw the specified text with the font, position, color,
6
+ # and alignment provided.
7
+ #
8
+ # @example Drawing a label
9
+ #
10
+ # class TitleScene < GameScene
11
+ # draw :game_title, model: "metro::ui::label", position: "320,240",
12
+ # vertical_align: "center", align: "center", color: "rgba(255,255,255,1.0)",
13
+ # text: "Super Awesome Game\n2"
14
+ # end
15
+ #
16
+ class Label < Model
17
+
18
+ # @attribute
19
+ # The position of the label
20
+ property :position
21
+
22
+ # @attribute
23
+ # The scale of the text
24
+ property :scale, default: Scale.one
25
+
26
+ # @attribute
27
+ # The text color
28
+ property :color, default: "rgba(255,255,255,1.0)"
29
+
30
+ # @attribute
31
+ # The font to use for the label text
32
+ property :font, default: { size: 20 }
33
+
34
+ # @attribute
35
+ # The text to appear on the label
36
+ property :text
37
+
38
+ # @attribute
39
+ # The alignment for the label. This influences where the text draws in
40
+ # relation to the specified position. Your choices are 'left', 'center',
41
+ # and 'right'. The default is 'left'.
42
+ property :align, type: :text, default: "left"
43
+
44
+ # @attribute
45
+ # The vertical alignment for the label. This influences where the text
46
+ # draws in relation to the specified position. Your choices are 'top',
47
+ # 'center', and 'bottom'. This default is 'top'
48
+ property :vertical_align, type: :text, default: "top"
49
+
50
+ # @attribute
51
+ # When calculating the dimensions of the label, this is the minimum
52
+ # dimensions. This is necessary in cases when the text is blank. This
53
+ # allows for the label to have size when in the edit mode.
54
+ property :minimum_dimensions, type: :dimensions, default: "16,16"
55
+
56
+ # @attribute
57
+ # The dimensions of label. If the label text is blank, then the dimensions
58
+ # of the label will return a minimum dimension.
59
+ property :dimensions do
60
+ calculated = Dimensions.of (longest_line * x_factor), (line_height * line_count * y_factor)
61
+ [ calculated, minimum_dimensions ].max
62
+ end
63
+
64
+ def bounds
65
+ Bounds.new left: left_x, right: right_x, top: top_y, bottom: bottom_y
66
+ end
67
+
68
+ def draw
69
+ parsed_text.each_with_index do |line,index|
70
+ font.draw line, x_position(index), y_position(index), z_order, x_factor, y_factor, color
71
+ end
72
+ end
73
+
74
+ private
75
+
76
+ def left_x
77
+ line_count.times.map { |index| x_position(index) }.min
78
+ end
79
+
80
+ def right_x
81
+ left_x + width
82
+ end
83
+
84
+ def top_y
85
+ y_position(0)
86
+ end
87
+
88
+ def bottom_y
89
+ top_y + height
90
+ end
91
+
92
+ def line_height
93
+ font.height
94
+ end
95
+
96
+ def line_width(line)
97
+ font.text_width(line)
98
+ end
99
+
100
+ def half_line_height
101
+ line_height / 2
102
+ end
103
+
104
+ def longest_line
105
+ parsed_text.map { |line| line_width(line) }.max || 0
106
+ end
107
+
108
+ def line_count
109
+ parsed_text.count
110
+ end
111
+
112
+ def parsed_text
113
+ text.split("\n")
114
+ end
115
+
116
+ def x_left_alignment(index)
117
+ x
118
+ end
119
+
120
+ def x_center_alignment(index)
121
+ x - line_width(parsed_text[index]) / 2
122
+ end
123
+
124
+ def x_right_alignment(index)
125
+ x - line_width(parsed_text[index])
126
+ end
127
+
128
+ def horizontal_alignments
129
+ { left: :x_left_alignment,
130
+ center: :x_center_alignment,
131
+ right: :x_right_alignment }
132
+ end
133
+
134
+ def x_position(index)
135
+ alignment = horizontal_alignments[align.to_sym]
136
+ send(alignment,index)
137
+ end
138
+
139
+ def y_top_alignment(index)
140
+ y + (index * line_height)
141
+ end
142
+
143
+ def y_bottom_alignment(index)
144
+ y - line_height * (line_count - index)
145
+ end
146
+
147
+ def y_center_alignment(index)
148
+ if line_count.even?
149
+ full_height = (line_count / 2 - index) * line_height
150
+ else
151
+ offset = (line_count / 2 - index)
152
+ if offset < 0
153
+ full_height = (offset + 1) * line_height - half_line_height
154
+ else
155
+ full_height = offset * line_height + half_line_height
156
+ end
157
+ end
158
+
159
+ y - full_height
160
+ end
161
+
162
+ def vertical_alignments
163
+ { top: :y_top_alignment,
164
+ center: :y_center_alignment,
165
+ bottom: :y_bottom_alignment }
166
+ end
167
+
168
+ def y_position(index)
169
+ alignment = vertical_alignments[vertical_align.to_sym]
170
+ send(alignment,index)
171
+ end
172
+
173
+ end
174
+ end
175
+ end