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.
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.rvmrc +1 -0
- data/.travis.yml +6 -0
- data/Gemfile +12 -0
- data/Guardfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +189 -0
- data/Rakefile +18 -0
- data/bin/metro +16 -0
- data/changelog.md +157 -0
- data/lib/assets/menu-movement.wav +0 -0
- data/lib/assets/menu-selection.wav +0 -0
- data/lib/assets/missing.ogg +0 -0
- data/lib/assets/missing.png +0 -0
- data/lib/assets/missing.wav +0 -0
- data/lib/assets/missing_animation.png +0 -0
- data/lib/commands/generate_game.rb +13 -0
- data/lib/commands/generate_model.rb +25 -0
- data/lib/commands/generate_scene.rb +36 -0
- data/lib/commands/generate_view.rb +21 -0
- data/lib/commands/thor.rb +83 -0
- data/lib/core_ext/class.rb +14 -0
- data/lib/core_ext/numeric.rb +59 -0
- data/lib/gosu_ext/color.rb +62 -0
- data/lib/gosu_ext/gosu_constants.rb +53 -0
- data/lib/locale/en.yml +35 -0
- data/lib/locale/locale.rb +1 -0
- data/lib/metro.rb +140 -0
- data/lib/metro/animation.rb +135 -0
- data/lib/metro/animation/after_interval_factory.rb +12 -0
- data/lib/metro/animation/animation_factory.rb +15 -0
- data/lib/metro/animation/easing/ease_in.rb +15 -0
- data/lib/metro/animation/easing/easing.rb +51 -0
- data/lib/metro/animation/easing/linear.rb +15 -0
- data/lib/metro/animation/has_animations.rb +70 -0
- data/lib/metro/animation/implicit_animation.rb +100 -0
- data/lib/metro/animation/on_update_operation.rb +96 -0
- data/lib/metro/animation/scene_animation.rb +16 -0
- data/lib/metro/asset_path.rb +97 -0
- data/lib/metro/events/control_definition.rb +11 -0
- data/lib/metro/events/controls.rb +42 -0
- data/lib/metro/events/event_data.rb +60 -0
- data/lib/metro/events/event_dictionary.rb +52 -0
- data/lib/metro/events/event_factory.rb +17 -0
- data/lib/metro/events/event_relay.rb +300 -0
- data/lib/metro/events/event_state_manager.rb +63 -0
- data/lib/metro/events/events.rb +3 -0
- data/lib/metro/events/has_events.rb +108 -0
- data/lib/metro/events/hit_list.rb +75 -0
- data/lib/metro/events/unknown_sender.rb +5 -0
- data/lib/metro/font.rb +69 -0
- data/lib/metro/game.rb +102 -0
- data/lib/metro/game/dsl.rb +68 -0
- data/lib/metro/image.rb +68 -0
- data/lib/metro/logging.rb +33 -0
- data/lib/metro/missing_scene.rb +21 -0
- data/lib/metro/models/audio/song.rb +33 -0
- data/lib/metro/models/draws.rb +86 -0
- data/lib/metro/models/key_value_coding.rb +38 -0
- data/lib/metro/models/model.rb +236 -0
- data/lib/metro/models/model_factory.rb +32 -0
- data/lib/metro/models/models.rb +62 -0
- data/lib/metro/models/properties/animation_property.rb +115 -0
- data/lib/metro/models/properties/array_property.rb +24 -0
- data/lib/metro/models/properties/boolean_property.rb +27 -0
- data/lib/metro/models/properties/color_property.rb +116 -0
- data/lib/metro/models/properties/dimensions_property.rb +84 -0
- data/lib/metro/models/properties/font_property.rb +130 -0
- data/lib/metro/models/properties/image_property.rb +96 -0
- data/lib/metro/models/properties/model_property.rb +84 -0
- data/lib/metro/models/properties/numeric_property.rb +29 -0
- data/lib/metro/models/properties/options_property/no_option.rb +29 -0
- data/lib/metro/models/properties/options_property/options.rb +94 -0
- data/lib/metro/models/properties/options_property/options_property.rb +125 -0
- data/lib/metro/models/properties/position_property.rb +90 -0
- data/lib/metro/models/properties/property.rb +221 -0
- data/lib/metro/models/properties/property_owner.rb +137 -0
- data/lib/metro/models/properties/sample_property.rb +84 -0
- data/lib/metro/models/properties/scale_property.rb +80 -0
- data/lib/metro/models/properties/song_property.rb +89 -0
- data/lib/metro/models/properties/text_property.rb +75 -0
- data/lib/metro/models/ui/animated_sprite.rb +85 -0
- data/lib/metro/models/ui/border.rb +95 -0
- data/lib/metro/models/ui/fps.rb +54 -0
- data/lib/metro/models/ui/generic.rb +66 -0
- data/lib/metro/models/ui/grid_drawer.rb +74 -0
- data/lib/metro/models/ui/image.rb +87 -0
- data/lib/metro/models/ui/label.rb +175 -0
- data/lib/metro/models/ui/menu.rb +214 -0
- data/lib/metro/models/ui/model_label.rb +65 -0
- data/lib/metro/models/ui/model_labeler.rb +79 -0
- data/lib/metro/models/ui/rectangle.rb +59 -0
- data/lib/metro/models/ui/sprite.rb +79 -0
- data/lib/metro/models/ui/tile_map.rb +162 -0
- data/lib/metro/models/ui/ui.rb +13 -0
- data/lib/metro/parameters/command_line_args_parser.rb +68 -0
- data/lib/metro/parameters/options.rb +25 -0
- data/lib/metro/parameters/parameters.rb +2 -0
- data/lib/metro/sample.rb +40 -0
- data/lib/metro/scene.rb +477 -0
- data/lib/metro/scenes.rb +154 -0
- data/lib/metro/song.rb +56 -0
- data/lib/metro/template_message.rb +60 -0
- data/lib/metro/transitions/edit_transition_scene.rb +100 -0
- data/lib/metro/transitions/fade_transition_scene.rb +66 -0
- data/lib/metro/transitions/scene_transitions.rb +44 -0
- data/lib/metro/transitions/transition_scene.rb +19 -0
- data/lib/metro/units/bounds.rb +8 -0
- data/lib/metro/units/calculation_validations.rb +74 -0
- data/lib/metro/units/dimensions.rb +60 -0
- data/lib/metro/units/point.rb +51 -0
- data/lib/metro/units/rectangle_bounds.rb +85 -0
- data/lib/metro/units/scale.rb +46 -0
- data/lib/metro/units/units.rb +6 -0
- data/lib/metro/version.rb +32 -0
- data/lib/metro/views/json_view.rb +60 -0
- data/lib/metro/views/no_view.rb +34 -0
- data/lib/metro/views/parsers.rb +42 -0
- data/lib/metro/views/scene_view.rb +107 -0
- data/lib/metro/views/view.rb +133 -0
- data/lib/metro/views/writers.rb +43 -0
- data/lib/metro/views/yaml_view.rb +94 -0
- data/lib/metro/window.rb +94 -0
- data/lib/setup_handlers/exit_if_dry_run.rb +26 -0
- data/lib/setup_handlers/game_execution.rb +65 -0
- data/lib/setup_handlers/load_game_configuration.rb +65 -0
- data/lib/setup_handlers/load_game_files.rb +101 -0
- data/lib/setup_handlers/move_to_game_directory.rb +25 -0
- data/lib/setup_handlers/reload_game_on_game_file_changes.rb +79 -0
- data/lib/templates/game/README.md.tt +52 -0
- data/lib/templates/game/assets/brand.jpg +0 -0
- data/lib/templates/game/assets/hero.png +0 -0
- data/lib/templates/game/lib/custom_easing.rb +32 -0
- data/lib/templates/game/metro.tt +63 -0
- data/lib/templates/game/models/hero.rb +62 -0
- data/lib/templates/game/scenes/brand_scene.rb +19 -0
- data/lib/templates/game/scenes/brand_to_title_scene.rb +13 -0
- data/lib/templates/game/scenes/first_scene.rb +28 -0
- data/lib/templates/game/scenes/game_scene.rb +43 -0
- data/lib/templates/game/scenes/title_scene.rb +15 -0
- data/lib/templates/game/views/brand.yaml +4 -0
- data/lib/templates/game/views/brand_to_title.yaml +8 -0
- data/lib/templates/game/views/first.yaml +26 -0
- data/lib/templates/game/views/title.yaml +11 -0
- data/lib/templates/message.erb +23 -0
- data/lib/templates/model.rb.tt +111 -0
- data/lib/templates/scene.rb.tt +140 -0
- data/lib/templates/view.yaml.tt +11 -0
- data/lib/tmxed_ext/tile_set.rb +34 -0
- data/metro.gemspec +56 -0
- data/spec/core_ext/numeric_spec.rb +78 -0
- data/spec/core_ext/string_spec.rb +33 -0
- data/spec/gosu_ext/color_spec.rb +80 -0
- data/spec/metro/events/event_state_manager_spec.rb +5 -0
- data/spec/metro/models/key_value_coding_spec.rb +61 -0
- data/spec/metro/models/properties/array_property_spec.rb +60 -0
- data/spec/metro/models/properties/color_property_spec.rb +85 -0
- data/spec/metro/models/properties/dimensions_spec.rb +29 -0
- data/spec/metro/models/properties/font_property_spec.rb +127 -0
- data/spec/metro/models/properties/numeric_property_spec.rb +46 -0
- data/spec/metro/models/properties/options_property/no_option_spec.rb +25 -0
- data/spec/metro/models/properties/options_property/options_property_spec.rb +133 -0
- data/spec/metro/models/properties/options_property/options_spec.rb +125 -0
- data/spec/metro/models/properties/position_property_spec.rb +90 -0
- data/spec/metro/models/ui/label_spec.rb +259 -0
- data/spec/metro/parameters/command_line_args_parser_spec.rb +42 -0
- data/spec/metro/scene_spec.rb +15 -0
- data/spec/metro/scene_views/json_view_spec.rb +27 -0
- data/spec/metro/scene_views/yaml_view_spec.rb +38 -0
- data/spec/metro/scenes_spec.rb +77 -0
- data/spec/metro/units/point_spec.rb +132 -0
- data/spec/metro/views/view_spec.rb +53 -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
- data/spec/spec_helper.rb +20 -0
- metadata +374 -0
data/lib/metro/image.rb
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
module Metro
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# Image is a wrapper class for a Gosu Image. This allows for additional data
|
|
5
|
+
# to be stored without relying on monkey-patching on functionality.
|
|
6
|
+
#
|
|
7
|
+
class Image < SimpleDelegator
|
|
8
|
+
|
|
9
|
+
def initialize(gosu_image,path,tileable)
|
|
10
|
+
super(gosu_image)
|
|
11
|
+
@path = path
|
|
12
|
+
@tileable = tileable
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# The relative path of the image
|
|
16
|
+
attr_reader :path
|
|
17
|
+
|
|
18
|
+
# The tileability of the image
|
|
19
|
+
attr_reader :tileable
|
|
20
|
+
|
|
21
|
+
def dimensions
|
|
22
|
+
Metro::Units::Dimensions.of width, height
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
#
|
|
26
|
+
# Finds an existing image or creates a new image given the window, path,
|
|
27
|
+
# and tileablilty.
|
|
28
|
+
#
|
|
29
|
+
# @example Finding or creating an Image
|
|
30
|
+
#
|
|
31
|
+
# Metro::Image.find_or_create window: model.window,
|
|
32
|
+
# path: "asset_path", tileable: tileable
|
|
33
|
+
#
|
|
34
|
+
def self.find_or_create(options)
|
|
35
|
+
path = AssetPath.with(options[:path])
|
|
36
|
+
images[path.to_s] or (images[path.to_s] = create(options))
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
#
|
|
40
|
+
# Create an image given the window, path, and tileability.
|
|
41
|
+
#
|
|
42
|
+
# @example Creating an Image
|
|
43
|
+
#
|
|
44
|
+
# Metro::Image.create window: model.window,
|
|
45
|
+
# path: "asset_path", tileable: tileable
|
|
46
|
+
#
|
|
47
|
+
def self.create(options)
|
|
48
|
+
window, asset_path, tileable = create_params(options)
|
|
49
|
+
gosu_image = Gosu::Image.new(window,asset_path.filepath,tileable)
|
|
50
|
+
new gosu_image, asset_path.path, tileable
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
def self.create_params(options)
|
|
56
|
+
options.symbolize_keys!
|
|
57
|
+
asset_path = AssetPath.with(options[:path])
|
|
58
|
+
window = options[:window]
|
|
59
|
+
tileable = !!options[:tileable]
|
|
60
|
+
[ window, asset_path, tileable ]
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def self.images
|
|
64
|
+
@images ||= {}
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
|
|
2
|
+
#
|
|
3
|
+
# Generates a default logger to standard out that can be used within Metro or the game.
|
|
4
|
+
#
|
|
5
|
+
# @example Outputting information at the debug level
|
|
6
|
+
#
|
|
7
|
+
# log.debug "The the screen resolution is #{Game.width},#{Game.height}"
|
|
8
|
+
#
|
|
9
|
+
def log
|
|
10
|
+
@log ||= begin
|
|
11
|
+
logger = Logger.new(STDOUT)
|
|
12
|
+
logger.level = Logger::DEBUG
|
|
13
|
+
logger
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
#
|
|
18
|
+
# Display an error message defined within the localization file. A game error displays
|
|
19
|
+
# a error title, message, and actions that can be taken to possibly address this issue.
|
|
20
|
+
#
|
|
21
|
+
# @param [String] message the I18n string found in the locale file.
|
|
22
|
+
# @param [Hash] details contains all the possible key-value pairs that might be needed
|
|
23
|
+
# for the localized error messages.
|
|
24
|
+
#
|
|
25
|
+
def error!(messages, details = {})
|
|
26
|
+
details = { show: true, exit: true }.merge details
|
|
27
|
+
|
|
28
|
+
message = TemplateMessage.new messages: messages, details: details,
|
|
29
|
+
website: Game.website, contact: Game.contact
|
|
30
|
+
|
|
31
|
+
warn message if details[:show]
|
|
32
|
+
exit 1 if details[:exit]
|
|
33
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Metro
|
|
2
|
+
class MissingScene < Scene
|
|
3
|
+
scene_name :missing_scene
|
|
4
|
+
|
|
5
|
+
class << self
|
|
6
|
+
attr_accessor :missing_scene
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
draw :title, text: "Missing Scene!",
|
|
10
|
+
position: "20,20,1",
|
|
11
|
+
color: "rgb(255,0,0)",
|
|
12
|
+
font: {size: 80},
|
|
13
|
+
model: "metro::ui::label"
|
|
14
|
+
|
|
15
|
+
draw :message, text: 'The scene `#{self.class.missing_scene}` was requested, but is missing!',
|
|
16
|
+
position: "20,100,1",
|
|
17
|
+
color: "rgb(255,255,255)",
|
|
18
|
+
model: "metro::ui::label"
|
|
19
|
+
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module Metro
|
|
2
|
+
module Audio
|
|
3
|
+
|
|
4
|
+
#
|
|
5
|
+
# A song represents an audio representation.
|
|
6
|
+
#
|
|
7
|
+
class Song < Metro::Model
|
|
8
|
+
|
|
9
|
+
property :song
|
|
10
|
+
property :volume, default: 1.0
|
|
11
|
+
property :state, type: :text, default: 'play'
|
|
12
|
+
|
|
13
|
+
def show
|
|
14
|
+
song.volume = self.volume
|
|
15
|
+
play if state == "play"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def stop
|
|
19
|
+
song.stop
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def play
|
|
23
|
+
song.play if not song.playing? and not song.paused?
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def pause
|
|
27
|
+
song.playing? ? song.pause : song.play
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
require_relative 'model_factory'
|
|
2
|
+
|
|
3
|
+
module Metro
|
|
4
|
+
module Draws
|
|
5
|
+
|
|
6
|
+
def self.included(base)
|
|
7
|
+
base.extend ClassMethods
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
module ClassMethods
|
|
11
|
+
|
|
12
|
+
#
|
|
13
|
+
# Define an actor with the given name and options.
|
|
14
|
+
#
|
|
15
|
+
# As a convenience the draw method will define `getter` and `setter`
|
|
16
|
+
# methods for the specified actor.
|
|
17
|
+
#
|
|
18
|
+
# @example Defining a title label within a scene
|
|
19
|
+
#
|
|
20
|
+
# class ExampleScene
|
|
21
|
+
# draw :title, text: 'Title Screen',
|
|
22
|
+
# model: 'metro::ui::label'
|
|
23
|
+
# position: '20,20,0',
|
|
24
|
+
# scale: '3,3',
|
|
25
|
+
# color: 'rgba(255,255,255,1.0)'
|
|
26
|
+
#
|
|
27
|
+
# def show
|
|
28
|
+
# puts "Where is my title? #{title.x},#{title.y}"
|
|
29
|
+
# end
|
|
30
|
+
# end
|
|
31
|
+
#
|
|
32
|
+
def draw(actor_name,options = {})
|
|
33
|
+
|
|
34
|
+
view_content_for_actor = view.content[actor_name.to_s]
|
|
35
|
+
|
|
36
|
+
actor_data = view_content_for_actor.merge(options)
|
|
37
|
+
actor_data[:name] = actor_name
|
|
38
|
+
|
|
39
|
+
scene_actor = ModelFactory.new actor_name, actor_data
|
|
40
|
+
|
|
41
|
+
define_method actor_name do
|
|
42
|
+
instance_variable_get("@#{actor_name}")
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
define_method "#{actor_name}=" do |value|
|
|
46
|
+
instance_variable_set("@#{actor_name}",value)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
drawings.push scene_actor
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
#
|
|
53
|
+
# Define a sound actor with the given anem and options.
|
|
54
|
+
#
|
|
55
|
+
# @see #draw
|
|
56
|
+
#
|
|
57
|
+
def play(song_name,options={})
|
|
58
|
+
draw song_name, options.merge(model: "metro::audio::song")
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
#
|
|
62
|
+
# Define several actors to be drawn.
|
|
63
|
+
#
|
|
64
|
+
def draws(*actor_names)
|
|
65
|
+
actor_names = actor_names.flatten.compact
|
|
66
|
+
|
|
67
|
+
actor_names.each do |actor_name|
|
|
68
|
+
draw actor_name
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
drawings
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
#
|
|
75
|
+
# All of the model factories that have been defined.
|
|
76
|
+
#
|
|
77
|
+
def drawings
|
|
78
|
+
@drawings ||= []
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
alias_method :actors, :drawings
|
|
82
|
+
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module Metro
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# Key-Value coding emulates the functionality found in Objective-C, which allows
|
|
5
|
+
# for an object to be sent a message which contains the method to return. This is
|
|
6
|
+
# the same as Ruby. However, Objective-C also supports the use of the dot notation
|
|
7
|
+
# within the keys to acces the sub-values.
|
|
8
|
+
#
|
|
9
|
+
# @example Setting the red value of the color on a Model.
|
|
10
|
+
#
|
|
11
|
+
# class Elf
|
|
12
|
+
# include KeyValueCoding
|
|
13
|
+
#
|
|
14
|
+
# attr_accessor :color
|
|
15
|
+
# end
|
|
16
|
+
#
|
|
17
|
+
# elf = Elf.new
|
|
18
|
+
# elf.color = Gosu::Color.new "rgb(0,0,0)"
|
|
19
|
+
#
|
|
20
|
+
# elf.get("color.red") # => 0
|
|
21
|
+
# elf.set("color.red",255)
|
|
22
|
+
# elf.get("color.red") # => 255
|
|
23
|
+
#
|
|
24
|
+
module KeyValueCoding
|
|
25
|
+
|
|
26
|
+
def set(name,value)
|
|
27
|
+
keys = name.to_s.split('.')
|
|
28
|
+
key_to_set = keys[0..-2].inject(self) {|target,method| target.send(method) }
|
|
29
|
+
key_to_set.send("#{keys.last}=",value)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def get(name)
|
|
33
|
+
keys = name.to_s.split('.')
|
|
34
|
+
keys.inject(self) {|target,method| target.send(method) }
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
end
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
require_relative 'key_value_coding'
|
|
2
|
+
require_relative 'properties/property'
|
|
3
|
+
require_relative 'models'
|
|
4
|
+
|
|
5
|
+
module Metro
|
|
6
|
+
|
|
7
|
+
#
|
|
8
|
+
# The Model is a basic, generic representation of a game object
|
|
9
|
+
# that has a visual representation within the scene's window.
|
|
10
|
+
#
|
|
11
|
+
# Model is designed to be an abstract class, to be subclassed by
|
|
12
|
+
# other models.
|
|
13
|
+
#
|
|
14
|
+
# @see Models::Generic
|
|
15
|
+
#
|
|
16
|
+
class Model
|
|
17
|
+
include PropertyOwner
|
|
18
|
+
include Units
|
|
19
|
+
|
|
20
|
+
#
|
|
21
|
+
# This is an entry point for customization. As the model's {#initialize}
|
|
22
|
+
# method performs may perform some initialization that may be necessary.
|
|
23
|
+
#
|
|
24
|
+
# At this point the model has been created. However, the window and scene
|
|
25
|
+
# of the model will not have been defined and defined properties rely on
|
|
26
|
+
# the window or scene will return nil values. Other properties also will
|
|
27
|
+
# likely not be set.
|
|
28
|
+
#
|
|
29
|
+
# @note This method should be implemented in the Model subclass.
|
|
30
|
+
#
|
|
31
|
+
def after_initialize ; end
|
|
32
|
+
|
|
33
|
+
#
|
|
34
|
+
# This is an entry point for customization. After the model's properties
|
|
35
|
+
# have been set and the model has been assigned to the window and scene
|
|
36
|
+
# this method is called. Here is where customization of properties or
|
|
37
|
+
# final positioning can be performed.
|
|
38
|
+
#
|
|
39
|
+
# @note This method may be implemented in the Model subclass.
|
|
40
|
+
#
|
|
41
|
+
def show ; end
|
|
42
|
+
|
|
43
|
+
#
|
|
44
|
+
# This is called every update interval while the actor is in the scene
|
|
45
|
+
#
|
|
46
|
+
# @note This method should be implemented in the Model subclass
|
|
47
|
+
#
|
|
48
|
+
def update ; end
|
|
49
|
+
|
|
50
|
+
#
|
|
51
|
+
# This is called after an update. A model normally is not removed after
|
|
52
|
+
# an update, however if the model responds true to #completed? then it
|
|
53
|
+
# will be removed.
|
|
54
|
+
#
|
|
55
|
+
# @note This method should be implemented in the Model sublclass if you
|
|
56
|
+
# are interested in having the model be removed from the scene.
|
|
57
|
+
#
|
|
58
|
+
def completed? ; false ; end
|
|
59
|
+
|
|
60
|
+
#
|
|
61
|
+
# This is called after every {#update} and when the OS wants the window to
|
|
62
|
+
# repaint itself.
|
|
63
|
+
#
|
|
64
|
+
# @note This method should be implemented in the Model subclass.
|
|
65
|
+
#
|
|
66
|
+
def draw ; end
|
|
67
|
+
|
|
68
|
+
def self.model_name(model_name=nil)
|
|
69
|
+
@model_name ||= to_s.underscore
|
|
70
|
+
model_name ? @model_name = model_name.to_s : @model_name
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
#
|
|
74
|
+
# @return [String] the name of the model class.
|
|
75
|
+
#
|
|
76
|
+
property :model, type: :text
|
|
77
|
+
|
|
78
|
+
#
|
|
79
|
+
# @return [String] the name of model as it is used within the view or the scene.
|
|
80
|
+
# This is the common name, the key within the view file, or the name symbol
|
|
81
|
+
# name specified in the scene.
|
|
82
|
+
#
|
|
83
|
+
property :name, type: :text
|
|
84
|
+
|
|
85
|
+
#
|
|
86
|
+
# @return [TrueClass,FalseClass] true if the model should be saved to the
|
|
87
|
+
# view file, false when the model should not be savedable to the view file.
|
|
88
|
+
#
|
|
89
|
+
property :saveable_to_view, type: :boolean, default: true
|
|
90
|
+
|
|
91
|
+
#
|
|
92
|
+
# The window that this model that this window is currently being
|
|
93
|
+
# displayed.
|
|
94
|
+
#
|
|
95
|
+
# The current value of window is managed by the scene
|
|
96
|
+
# as this is set when the Scene is added to the window. All the
|
|
97
|
+
# models gain access to the window.
|
|
98
|
+
#
|
|
99
|
+
# @see Window
|
|
100
|
+
#
|
|
101
|
+
attr_accessor :window
|
|
102
|
+
|
|
103
|
+
#
|
|
104
|
+
# The scene that this model is currently being displayed.
|
|
105
|
+
#
|
|
106
|
+
# The current value of scene is managed by the scene as this
|
|
107
|
+
# is set when the scene is created.
|
|
108
|
+
#
|
|
109
|
+
# @see Scene
|
|
110
|
+
attr_accessor :scene
|
|
111
|
+
|
|
112
|
+
include KeyValueCoding
|
|
113
|
+
|
|
114
|
+
#
|
|
115
|
+
# Generate a custom notification event with the given name.
|
|
116
|
+
#
|
|
117
|
+
# @param [Symbol] event the name of the notification to generate.
|
|
118
|
+
#
|
|
119
|
+
def notification(event)
|
|
120
|
+
scene.notification(event.to_sym,self)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
#
|
|
124
|
+
# Allows for the definition of events within the scene.
|
|
125
|
+
#
|
|
126
|
+
include HasEvents
|
|
127
|
+
|
|
128
|
+
#
|
|
129
|
+
# A helper method that allows the current model to generate another model. This
|
|
130
|
+
# is useful as it allows for the current model to pass window and scene state
|
|
131
|
+
# to the created model.
|
|
132
|
+
#
|
|
133
|
+
# @param [String] model_name the name of the model to be created.
|
|
134
|
+
# @return [Metro::Model] the metro model instance
|
|
135
|
+
#
|
|
136
|
+
def create(model_name,options={})
|
|
137
|
+
# @TODO: this is another path that parallels the ModelFactory
|
|
138
|
+
model_class = Metro::Models.find(model_name)
|
|
139
|
+
mc = model_class.new options
|
|
140
|
+
mc.scene = scene
|
|
141
|
+
mc.window = window
|
|
142
|
+
mc
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
#
|
|
146
|
+
# By default a model has no bounds. Each subclass of model will have to
|
|
147
|
+
# define how their bounds are defined.
|
|
148
|
+
#
|
|
149
|
+
def bounds
|
|
150
|
+
Bounds.none
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
#
|
|
154
|
+
# Create an instance of a model.
|
|
155
|
+
#
|
|
156
|
+
# @note Overridding initialize method should be avoided, using the {#aftter_initialize)
|
|
157
|
+
# method or done with care to ensure that functionality is preserved.
|
|
158
|
+
#
|
|
159
|
+
def initialize(options = {})
|
|
160
|
+
_load(options)
|
|
161
|
+
after_initialize
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
#
|
|
165
|
+
# Loads a hash of content into the model. This process will convert the hash
|
|
166
|
+
# of content into setter and getter methods with appropriate ruby style names.
|
|
167
|
+
#
|
|
168
|
+
# This is used internally when the model is created for the Scene. It is loaded
|
|
169
|
+
# with the contents of the view.
|
|
170
|
+
#
|
|
171
|
+
def _load(options = {})
|
|
172
|
+
# Clean up and symbolize all the keys then merge that with the existing properties
|
|
173
|
+
options.keys.each do |key|
|
|
174
|
+
property_name = key.to_s.underscore.to_sym
|
|
175
|
+
if respond_to? "#{property_name}="
|
|
176
|
+
send("#{property_name}=",options.delete(key))
|
|
177
|
+
else
|
|
178
|
+
options[property_name] = options.delete(key)
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
properties.merge! options
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
#
|
|
186
|
+
# Generate a hash export of all the fields that were previously stored within
|
|
187
|
+
# the model.
|
|
188
|
+
#
|
|
189
|
+
# This is used internally within the scene to transfer the data from one model
|
|
190
|
+
# to another model.
|
|
191
|
+
#
|
|
192
|
+
def _save
|
|
193
|
+
properties
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
#
|
|
197
|
+
# Generate a hash representation of the model.
|
|
198
|
+
#
|
|
199
|
+
def to_hash
|
|
200
|
+
{ name => properties.except(:name) }
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
#
|
|
204
|
+
# @return a common name that can be used through the system as a common identifier.
|
|
205
|
+
#
|
|
206
|
+
def self.metro_name
|
|
207
|
+
name.underscore
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
#
|
|
211
|
+
# @return an array of all ancestor models by name
|
|
212
|
+
#
|
|
213
|
+
def self.hierarchy
|
|
214
|
+
ancestors.find_all {|a| a.respond_to? :metro_name }.map(&:metro_name)
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
#
|
|
218
|
+
# Captures all classes that subclass Model.
|
|
219
|
+
#
|
|
220
|
+
def self.inherited(base)
|
|
221
|
+
models << base.to_s
|
|
222
|
+
Models.add(base)
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
#
|
|
226
|
+
# All subclasses of Model, this should be all the defined
|
|
227
|
+
#
|
|
228
|
+
def self.models
|
|
229
|
+
@models ||= []
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
require_relative 'ui/ui'
|
|
236
|
+
require_relative 'audio/song'
|