metro 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +6 -0
- data/Gemfile +1 -0
- data/README.md +37 -7
- data/Rakefile +17 -0
- data/changelog.md +10 -2
- data/lib/locale/en.yml +11 -0
- data/lib/metro.rb +62 -92
- data/lib/metro/game.rb +32 -1
- data/lib/metro/logging.rb +2 -2
- 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/version.rb +2 -2
- 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 +74 -0
- data/lib/templates/game/lib/custom_easing.rb +32 -0
- data/lib/templates/game/metro.tt +2 -3
- data/lib/templates/game/scenes/game_scene.rb +4 -3
- data/lib/templates/message.erb +10 -11
- data/metro.gemspec +2 -1
- data/spec/metro/parameters/command_line_args_parser_spec.rb +42 -0
- metadata +39 -6
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -11,24 +11,33 @@ Metro is a framework built around [gosu](https://github.com/jlnr/gosu) (the 2D g
|
|
11
11
|
|
12
12
|
[![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/burtlo/metro)
|
13
13
|
|
14
|
+
[![Build Status](https://travis-ci.org/burtlo/metro.png)](https://travis-ci.org/burtlo/metro)
|
15
|
+
|
16
|
+
[![Dependency Status](https://gemnasium.com/burtlo/metro.png)](https://gemnasium.com/burtlo/metro)
|
17
|
+
|
14
18
|
## Why Use Metro?
|
15
19
|
|
16
20
|
You want to develop games in Ruby.
|
17
21
|
|
18
22
|
### Why not just use Gosu?
|
19
23
|
|
20
|
-
Gosu does
|
24
|
+
Gosu does a lot of great work bringing OpenGL to Ruby. However, when you finish the [initial tutorial](https://github.com/jlnr/gosu/wiki/Ruby-Tutorial) you are left with a brittle game that is very resistant to changes or new features.
|
21
25
|
|
22
26
|
* Metro provides the concept of a [Scene](https://github.com/burtlo/metro/wiki/Scenes) which is the first abstraction you would likely build after completing the tutorial.
|
23
27
|
|
24
|
-
|
28
|
+
> Developing your game in individual scenes will make it easier to logically layout your game.
|
29
|
+
|
30
|
+
* Sane management of images, animations, fonts, songs, and samples through [model properties](https://github.com/burtlo/metro/wiki/Model-properties).
|
31
|
+
|
32
|
+
> Having to load and cache fonts and images in every one of your models is tedious. It is also is wasteful as several of the same fonts are being used all over the place.
|
25
33
|
|
26
|
-
* [
|
34
|
+
* [Key-frame animations](https://github.com/burtlo/metro/wiki/Animations)
|
35
|
+
|
36
|
+
> Metro makes it simple to move an actor from one position to another position. So simple movements, fades, color changes, and really any property change over time is defined very simply.
|
27
37
|
|
28
38
|
* [Event Handling](https://github.com/burtlo/metro/wiki/Events)
|
29
39
|
|
30
|
-
Metro
|
31
|
-
development joyful.
|
40
|
+
> Delete those huge `if ... elsif ... else` input checking structures for keyboard, gamepad, and mouse button presses (down,up, and held). Metro makes it easy to define them and an attach a course of action to take when the event happens.
|
32
41
|
|
33
42
|
### Why not use Chingu or Gamebox?
|
34
43
|
|
@@ -37,8 +46,29 @@ Both [Gamebox](https://github.com/shawn42/gamebox) and
|
|
37
46
|
larger set of features.
|
38
47
|
|
39
48
|
With Metro the focus is on a smaller set of features with an emphasis on an
|
40
|
-
implementation that leads to joyful development.
|
41
|
-
|
49
|
+
implementation that leads to joyful development. An emphasis has been applied to creating elegant solutions which have documentation and examples.
|
50
|
+
|
51
|
+
* Active Reloading while building your scenes.
|
52
|
+
|
53
|
+
> Adjustments to your game code while working on a scene will automatically
|
54
|
+
reload your game code. The template game sets up a shortcut key (**Ctrl+R**) that allows you to explicitly reload the game and the current scene.
|
55
|
+
|
56
|
+
* Scene Edit Support
|
57
|
+
|
58
|
+
> All scenes can have their visual component layout re-adjusted through an edit
|
59
|
+
mode. The edit mode layout works for all labels, images, and menus.
|
60
|
+
|
61
|
+
### Why you shouldn't use Metro?
|
62
|
+
|
63
|
+
Metro has some the following limitations:
|
64
|
+
|
65
|
+
* Limited to the gems defined within Metro
|
66
|
+
|
67
|
+
> At this point in time you are not able to define and package additional dependencies with your game. This means if you are using a gem that is not already defined by Metro you will run into trouble when running it on alternate systems. This will likely be addressed in the future when more demand arises.
|
68
|
+
|
69
|
+
* Difficult Deployment
|
70
|
+
|
71
|
+
> For individuals to play your game, they will also have to install Metro. However, work is being made to bring some simple packaging to Metro games to make them stand-along executables.
|
42
72
|
|
43
73
|
## Installation
|
44
74
|
|
data/Rakefile
CHANGED
@@ -1 +1,18 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
|
+
|
3
|
+
begin
|
4
|
+
|
5
|
+
require 'rspec/core/rake_task'
|
6
|
+
|
7
|
+
desc "Run all rspecs"
|
8
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
9
|
+
t.pattern = 'spec/**/*_spec.rb'
|
10
|
+
t.rspec_opts = '-c'
|
11
|
+
end
|
12
|
+
|
13
|
+
task :default => :spec
|
14
|
+
|
15
|
+
rescue LoadError
|
16
|
+
puts "please install rspec to run tests"
|
17
|
+
puts "install with gem install rspec"
|
18
|
+
end
|
data/changelog.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
# Metro
|
2
2
|
|
3
|
+
## 0.3.2 / 2012-11-26
|
4
|
+
|
5
|
+
* Debug Mode will now automatically reload the game and scene on source
|
6
|
+
file changes.
|
7
|
+
* Reloading the game will no longer take down the app for syntax errors
|
8
|
+
and other errors that are easily detected by simply loading the code.
|
9
|
+
* Template game is now automatically has debug mode enabled by default
|
10
|
+
|
3
11
|
## 0.3.1 / 2012-11-25
|
4
12
|
|
5
13
|
* FIX issue with some Gosu example code left in the oven
|
@@ -63,11 +71,11 @@
|
|
63
71
|
|
64
72
|
## 0.2.1 / 2012-11-08
|
65
73
|
|
66
|
-
* FIX Scene fade transition color changing and implicit animations
|
74
|
+
* FIX Scene fade transition color changing and implicit animations
|
67
75
|
for colors
|
68
76
|
* Games creating custom properties will appear in the property list
|
69
77
|
* Properties now correctly default to numeric properties
|
70
|
-
* Point objects can be added to other point objects.
|
78
|
+
* Point objects can be added to other point objects.
|
71
79
|
|
72
80
|
## 0.2.0 / 2012-11-07
|
73
81
|
|
data/lib/locale/en.yml
CHANGED
@@ -2,6 +2,10 @@
|
|
2
2
|
en:
|
3
3
|
website: "%{website}"
|
4
4
|
error:
|
5
|
+
unloadable_source:
|
6
|
+
title: "Metro CANNOT load your game code!"
|
7
|
+
message: "There is an error within your game code that needs to be fixed before Metro\nis able to replace the current running game code:\n\n%{output}"
|
8
|
+
actions: []
|
5
9
|
missing_metro_file:
|
6
10
|
title: "Unable to find Metro game file"
|
7
11
|
message: "The specified file `%{file}` which is required to run the game could not be found."
|
@@ -22,3 +26,10 @@ en:
|
|
22
26
|
actions:
|
23
27
|
- "Ensure that the control name is not already defined."
|
24
28
|
- "Replace the use of this control name with name"
|
29
|
+
dry_run:
|
30
|
+
success:
|
31
|
+
title: "Metro Game Dependencies Have Been Met!"
|
32
|
+
message: "Your game should be able to be run."
|
33
|
+
actions:
|
34
|
+
- "Metro dependencies have successfully been loaded"
|
35
|
+
- "Game dependencies have successfully been loaded"
|
data/lib/metro.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
require 'delegate'
|
2
2
|
require 'logger'
|
3
3
|
require 'erb'
|
4
|
+
require 'open3'
|
4
5
|
|
5
6
|
require 'gosu'
|
6
7
|
require 'i18n'
|
8
|
+
require 'listen'
|
7
9
|
require 'active_support'
|
8
10
|
require 'active_support/dependencies'
|
9
11
|
require 'active_support/inflector'
|
@@ -16,6 +18,7 @@ require 'core_ext/numeric'
|
|
16
18
|
|
17
19
|
require 'locale/locale'
|
18
20
|
|
21
|
+
require 'metro/parameters/parameters'
|
19
22
|
require 'metro/asset_path'
|
20
23
|
require 'metro/units/units'
|
21
24
|
require 'metro/logging'
|
@@ -31,8 +34,7 @@ require 'metro/game'
|
|
31
34
|
require 'metro/scene'
|
32
35
|
require 'metro/scenes'
|
33
36
|
require 'metro/models/model'
|
34
|
-
|
35
|
-
require_relative 'metro/missing_scene'
|
37
|
+
require 'metro/missing_scene'
|
36
38
|
|
37
39
|
#
|
38
40
|
# To allow an author an easier time accessing the Game object from within their game.
|
@@ -45,123 +47,91 @@ module Metro
|
|
45
47
|
extend GosuConstants
|
46
48
|
|
47
49
|
#
|
48
|
-
# @return [String] the
|
50
|
+
# @return [String] the filepath to the Metro executable
|
49
51
|
#
|
50
|
-
def
|
51
|
-
|
52
|
+
def executable_path
|
53
|
+
File.absolute_path File.join(File.dirname(__FILE__), "..", "bin", "metro")
|
52
54
|
end
|
53
55
|
|
56
|
+
#
|
57
|
+
# @return [String] the filepath to the Metro assets
|
58
|
+
#
|
54
59
|
def asset_dir
|
55
60
|
File.join File.dirname(__FILE__), "assets"
|
56
61
|
end
|
57
62
|
|
58
63
|
#
|
59
|
-
#
|
60
|
-
#
|
61
|
-
# calling run with no parameter will look for a game file
|
62
|
-
#
|
63
|
-
# @param [String] filename the name of the game file to run. When not specified
|
64
|
-
# the value uses the default filename.
|
64
|
+
# @return [Array] an array of all the handlers that will be executed prior
|
65
|
+
# to the game being launched.
|
65
66
|
#
|
66
|
-
def
|
67
|
-
|
68
|
-
load_game_files!
|
69
|
-
load_game_configuration(filename)
|
70
|
-
configure_controls!
|
71
|
-
start_game
|
67
|
+
def setup_handlers
|
68
|
+
@setup_handlers ||= []
|
72
69
|
end
|
73
70
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
71
|
+
#
|
72
|
+
# Register a setup handler. While this method is present, it is far
|
73
|
+
# too late for game code to be executed as these pregame handlers will already
|
74
|
+
# have started executing. This allows for modularity within the Metro library
|
75
|
+
# with the possibility that this functionality could become available to
|
76
|
+
# individual games if the load process were to be updated.
|
77
|
+
#
|
78
|
+
def register_setup_handler(handler)
|
79
|
+
setup_handlers.push handler
|
79
80
|
end
|
80
81
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
82
|
+
#
|
83
|
+
# Run will load the contents of the game contents and game files
|
84
|
+
# within the current working directory and start the game.
|
85
|
+
#
|
86
|
+
# @param [Array<String>] parameters an array of parameters that contains
|
87
|
+
# the commands in the format that would normally be parsed into the
|
88
|
+
# ARGV array.
|
89
|
+
#
|
90
|
+
def run(*parameters)
|
91
|
+
options = Parameters::CommandLineArgsParser.parse(parameters)
|
92
|
+
setup_handlers.each { |handler| handler.setup(options) }
|
93
|
+
start_game
|
88
94
|
end
|
89
95
|
|
90
96
|
#
|
91
|
-
#
|
92
|
-
#
|
93
|
-
# those objects to be reloaded.
|
97
|
+
# Start the game by lanunching a window with the game configuration and data
|
98
|
+
# that has been loaded.
|
94
99
|
#
|
95
|
-
def
|
96
|
-
|
100
|
+
def start_game
|
101
|
+
Game.start!
|
97
102
|
end
|
98
103
|
|
99
104
|
#
|
100
|
-
#
|
101
|
-
#
|
105
|
+
# When called all the game-related code will be unloaded and reloaded.
|
106
|
+
# Providding an opportunity for a game author to tweak the code without having
|
107
|
+
# to restart the game.
|
102
108
|
#
|
103
|
-
def
|
104
|
-
|
105
|
-
watcher.watch_namespaces([ Object ])
|
109
|
+
def reload!
|
110
|
+
SetupHandlers::LoadGameFiles.new.load_game_files!
|
106
111
|
end
|
107
112
|
|
108
113
|
#
|
109
|
-
#
|
110
|
-
#
|
111
|
-
#
|
114
|
+
# When called the game-related code will be loaded in a sub-process to see
|
115
|
+
# if the code is valid. This is used in tandem with {#reload} and should be
|
116
|
+
# called prior to ensure that the code that is replacing the current code
|
117
|
+
# is valid.
|
112
118
|
#
|
113
|
-
# @
|
114
|
-
#
|
119
|
+
# @return [TrueClass,FalseClass] true if the game code that was loaded was
|
120
|
+
# loaded successfully. false if the game code was not able to be loaded.
|
115
121
|
#
|
116
|
-
def
|
117
|
-
|
118
|
-
end
|
122
|
+
def game_has_valid_code?
|
123
|
+
execution = SetupHandlers::LoadGameFiles.new.launch_game_in_dry_run_mode
|
119
124
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
load_path 'scenes', prioritize: 'game_scene.rb'
|
124
|
-
load_path 'models', prioritize: 'game_model.rb'
|
125
|
-
end
|
126
|
-
|
127
|
-
def load_paths(*paths)
|
128
|
-
paths.flatten.compact.each {|path| load_path path }
|
129
|
-
end
|
130
|
-
|
131
|
-
def load_path(path,options = {})
|
132
|
-
files = Dir["#{path}/**/*.rb"]
|
133
|
-
files.sort! {|file| File.basename(file) == options[:prioritize] ? -1 : 1 }
|
134
|
-
files.each {|file| require_or_load file }
|
135
|
-
end
|
125
|
+
if execution.invalid?
|
126
|
+
error! 'error.unloadable_source', output: execution.output, exit: false
|
127
|
+
end
|
136
128
|
|
137
|
-
|
138
|
-
gamefile = File.basename(filename)
|
139
|
-
game_files_exist!(gamefile)
|
140
|
-
game_contents = File.read(gamefile)
|
141
|
-
game_block = lambda {|instance| eval(game_contents) }
|
142
|
-
game = Game::DSL.parse(&game_block)
|
143
|
-
Game.setup game
|
129
|
+
execution.valid?
|
144
130
|
end
|
145
|
-
|
146
|
-
def configure_controls!
|
147
|
-
EventRelay.define_controls Game.controls
|
148
|
-
end
|
149
|
-
|
150
|
-
def start_game
|
151
|
-
window = Window.new Game.width, Game.height, Game.fullscreen?
|
152
|
-
window.caption = Game.name
|
153
|
-
window.scene = Scenes.generate(Game.first_scene)
|
154
|
-
window.show
|
155
|
-
end
|
156
|
-
|
157
|
-
def game_files_exist!(*files)
|
158
|
-
files.compact.flatten.each { |file| game_file_exists?(file) }
|
159
|
-
end
|
160
|
-
|
161
|
-
|
162
|
-
def game_file_exists?(file)
|
163
|
-
error!("error.missing_metro_file",file: file) unless File.exists?(file)
|
164
|
-
error!("error.specified_directory",directory: file) if File.directory?(file)
|
165
|
-
end
|
166
|
-
|
167
131
|
end
|
132
|
+
|
133
|
+
require 'setup_handlers/move_to_game_directory'
|
134
|
+
require 'setup_handlers/load_game_files'
|
135
|
+
require 'setup_handlers/load_game_configuration'
|
136
|
+
require 'setup_handlers/exit_if_dry_run'
|
137
|
+
require 'setup_handlers/reload_game_on_game_file_changes'
|
data/lib/metro/game.rb
CHANGED
@@ -8,7 +8,37 @@ module Metro
|
|
8
8
|
@config = game_configuration
|
9
9
|
end
|
10
10
|
|
11
|
-
|
11
|
+
#
|
12
|
+
# Creates a window and starts the game with the game parameters.
|
13
|
+
#
|
14
|
+
def start!
|
15
|
+
@window = Window.new width, height, fullscreen?
|
16
|
+
window.caption = name
|
17
|
+
window.scene = Scenes.generate(first_scene)
|
18
|
+
window.show
|
19
|
+
end
|
20
|
+
|
21
|
+
# The original parameters specified during execution. These are the args
|
22
|
+
# found on the command-line that are passed in when the game started.
|
23
|
+
def execution_parameters
|
24
|
+
@execution_parameters ||= []
|
25
|
+
end
|
26
|
+
|
27
|
+
attr_writer :execution_parameters
|
28
|
+
|
29
|
+
#
|
30
|
+
# @return the current game window.
|
31
|
+
#
|
32
|
+
attr_reader :window
|
33
|
+
|
34
|
+
#
|
35
|
+
# @return [Scene,NilClass] the current scene that is being displayed. If
|
36
|
+
# this is called before the window is being displayed when this will return
|
37
|
+
# a nil value.
|
38
|
+
#
|
39
|
+
def current_scene
|
40
|
+
window ? window.scene : nil
|
41
|
+
end
|
12
42
|
|
13
43
|
def first_scene
|
14
44
|
fetch(:first_scene)
|
@@ -62,6 +92,7 @@ module Metro
|
|
62
92
|
config.send(name) rescue fallback
|
63
93
|
end
|
64
94
|
|
95
|
+
attr_reader :config
|
65
96
|
|
66
97
|
end
|
67
98
|
end
|
data/lib/metro/logging.rb
CHANGED
@@ -23,11 +23,11 @@ end
|
|
23
23
|
# for the localized error messages.
|
24
24
|
#
|
25
25
|
def error!(messages, details = {})
|
26
|
-
details = { show: true }.merge details
|
26
|
+
details = { show: true, exit: true }.merge details
|
27
27
|
|
28
28
|
message = TemplateMessage.new messages: messages, details: details,
|
29
29
|
website: Game.website, contact: Game.contact
|
30
30
|
|
31
31
|
warn message if details[:show]
|
32
|
-
exit 1
|
32
|
+
exit 1 if details[:exit]
|
33
33
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Metro
|
2
|
+
module Parameters
|
3
|
+
|
4
|
+
#
|
5
|
+
# The CommandLineArgsParser converts the argument list passed in from the
|
6
|
+
# command-line and generates an Metro::Parameters::Options object.
|
7
|
+
#
|
8
|
+
module CommandLineArgsParser
|
9
|
+
extend self
|
10
|
+
|
11
|
+
#
|
12
|
+
# Given the array of parameters usually from the Command-Line ARGV and
|
13
|
+
# convert that information into various parameters
|
14
|
+
#
|
15
|
+
def parse(*parameters)
|
16
|
+
parameters = parameters.flatten.compact
|
17
|
+
options = { execution_parameters: parameters.dup }
|
18
|
+
|
19
|
+
command_flags = extract_command_flags!(parameters)
|
20
|
+
filename = extract_game_file!(parameters)
|
21
|
+
|
22
|
+
Options.new options.merge(filename: filename).merge(command_flags)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
#
|
28
|
+
# Find all the flags within the array of parameters, extract them and
|
29
|
+
# generate a hash. Their presence within the array means that they should
|
30
|
+
# have a true value.
|
31
|
+
#
|
32
|
+
# @return [Hash] a hash that contains all the flags as keys and true as
|
33
|
+
# their values. As the presence of the flag means the value is true.
|
34
|
+
#
|
35
|
+
def extract_command_flags!(parameters)
|
36
|
+
raw_command_flags = parameters.flatten.find_all { |arg| arg.start_with? "--" }
|
37
|
+
parameters.delete_if { |param| raw_command_flags.include? param }
|
38
|
+
|
39
|
+
flag_names = raw_command_flags.map { |flag| flag[/--(.+)$/,1].underscore.to_sym }
|
40
|
+
flag_values = [ true ] * flag_names.count
|
41
|
+
Hash[flag_names.zip(flag_values)]
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
# From the current parameters array remove the first element which should
|
46
|
+
# be the default game file. When there is no value then use the default
|
47
|
+
# game filename
|
48
|
+
#
|
49
|
+
# @return [String] the game file name to use
|
50
|
+
#
|
51
|
+
def extract_game_file!(parameters)
|
52
|
+
parameters.delete_at(0) || default_game_filename
|
53
|
+
end
|
54
|
+
|
55
|
+
#
|
56
|
+
# The default for games is to have a game file called 'metro'. So if they
|
57
|
+
# do not provide the file parameter we assume that it is this file.
|
58
|
+
#
|
59
|
+
# @return [String] the default filename that contains the game contents
|
60
|
+
#
|
61
|
+
def default_game_filename
|
62
|
+
'metro'
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Metro
|
2
|
+
module Parameters
|
3
|
+
|
4
|
+
#
|
5
|
+
# Options are the result of a parameters parser. The options class defines
|
6
|
+
# a read-only structure that provides getters for all the parameters
|
7
|
+
# specified within the has.
|
8
|
+
#
|
9
|
+
# @see CommandLineArgsParser
|
10
|
+
#
|
11
|
+
class Options
|
12
|
+
def initialize(params = {})
|
13
|
+
params.each do |key,value|
|
14
|
+
self.class.send(:define_method,key) { value }
|
15
|
+
self.class.send(:define_method,"#{key}?") { value }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def method_missing(name,*args,&block)
|
20
|
+
return false
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
data/lib/metro/version.rb
CHANGED
@@ -0,0 +1,26 @@
|
|
1
|
+
module Metro
|
2
|
+
module SetupHandlers
|
3
|
+
|
4
|
+
#
|
5
|
+
# If the user has enabled the dry-run flag, this is the point at which the
|
6
|
+
# game will exit.
|
7
|
+
#
|
8
|
+
# Dry run mode is useful for determine if all dependencies have successfully
|
9
|
+
# been met and the source code will load successfully.
|
10
|
+
#
|
11
|
+
class ExitIfDryRun
|
12
|
+
#
|
13
|
+
# @param [Metro::Parameters::Options] options the options that the game
|
14
|
+
# was provided when it was launched.
|
15
|
+
#
|
16
|
+
def setup(options)
|
17
|
+
return unless options.dry_run?
|
18
|
+
puts TemplateMessage.new message: 'dry_run.success'
|
19
|
+
exit
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
register_setup_handler SetupHandlers::ExitIfDryRun.new
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Metro
|
2
|
+
module SetupHandlers
|
3
|
+
|
4
|
+
#
|
5
|
+
# The GameExecution allows for a game to be executed. This is used by Metro
|
6
|
+
# to validate that the code can be loaded and run before actually running
|
7
|
+
# it (specifically when reloading live running code)
|
8
|
+
#
|
9
|
+
class GameExecution
|
10
|
+
|
11
|
+
#
|
12
|
+
# Perform a game execution with the specified parameters and return the
|
13
|
+
# result of that game execution.
|
14
|
+
#
|
15
|
+
def self.execute(parameters)
|
16
|
+
execution = new(parameters)
|
17
|
+
execution.execute!
|
18
|
+
execution
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return the output generated from the execution of code.
|
22
|
+
attr_reader :output
|
23
|
+
|
24
|
+
# @return an array of parameters that will be provided to the execution
|
25
|
+
# of the game.
|
26
|
+
attr_reader :parameters
|
27
|
+
|
28
|
+
#
|
29
|
+
# @param [Array] parameters an array of the game parameters that are
|
30
|
+
# to be provided to this execution of the game.
|
31
|
+
#
|
32
|
+
def initialize(parameters)
|
33
|
+
@parameters = parameters
|
34
|
+
end
|
35
|
+
|
36
|
+
# @return the status code that was returned when the game execution
|
37
|
+
# has completed.
|
38
|
+
def status
|
39
|
+
@status ||= 0
|
40
|
+
end
|
41
|
+
|
42
|
+
# Perform the game execution.
|
43
|
+
def execute!
|
44
|
+
@output, @status = Open3.capture2e(game_execution_string)
|
45
|
+
end
|
46
|
+
|
47
|
+
# @return [TrueClass,FalseClass] true if the execution was successful.
|
48
|
+
def valid?
|
49
|
+
status == 0
|
50
|
+
end
|
51
|
+
|
52
|
+
# @return [TrueClass,FalseClass] true if the execution was a failure.
|
53
|
+
def invalid?
|
54
|
+
status != 0
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def game_execution_string
|
60
|
+
"#{Metro.executable_path} #{parameters.join(" ")}"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Metro
|
2
|
+
module SetupHandlers
|
3
|
+
|
4
|
+
#
|
5
|
+
# LoadGameConfiguration is a meta pregame setup handler as it defines multiple
|
6
|
+
# setup handlers to be executed related to game configuration.
|
7
|
+
#
|
8
|
+
class GameConfiguration
|
9
|
+
#
|
10
|
+
# @param [Metro::Parameters::Options] options the options that the game
|
11
|
+
# was provided when it was launched.
|
12
|
+
#
|
13
|
+
def setup(options)
|
14
|
+
ParseAndLoadGameConfiguration.new.setup(options)
|
15
|
+
ConfigureControls.new.setup(options)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
#
|
20
|
+
# Loads the game configuration information and sets up a Game object with the
|
21
|
+
# content loaded from the game configuration.
|
22
|
+
#
|
23
|
+
class ParseAndLoadGameConfiguration
|
24
|
+
|
25
|
+
#
|
26
|
+
# @param [Metro::Parameters::Options] options the options that the game
|
27
|
+
# was provided when it was launched.
|
28
|
+
#
|
29
|
+
def setup(options)
|
30
|
+
filename = options.filename
|
31
|
+
|
32
|
+
Game.execution_parameters = options.execution_parameters
|
33
|
+
|
34
|
+
gamefile = File.basename(filename)
|
35
|
+
game_files_exist!(gamefile)
|
36
|
+
game_contents = File.read(gamefile)
|
37
|
+
game_block = lambda {|instance| eval(game_contents) }
|
38
|
+
game = Game::DSL.parse(&game_block)
|
39
|
+
Game.setup game
|
40
|
+
end
|
41
|
+
|
42
|
+
def game_files_exist!(*files)
|
43
|
+
files.compact.flatten.each { |file| game_file_exists?(file) }
|
44
|
+
end
|
45
|
+
|
46
|
+
def game_file_exists?(file)
|
47
|
+
error!("error.missing_metro_file",file: file) unless File.exists?(file)
|
48
|
+
error!("error.specified_directory",directory: file) if File.directory?(file)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
#
|
53
|
+
# After the game has been configured it is time to configure the controls for
|
54
|
+
# the game.
|
55
|
+
#
|
56
|
+
class ConfigureControls
|
57
|
+
def setup(options)
|
58
|
+
EventRelay.define_controls Game.controls
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
register_setup_handler SetupHandlers::GameConfiguration.new
|
64
|
+
|
65
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require_relative 'game_execution'
|
2
|
+
|
3
|
+
module Metro
|
4
|
+
module SetupHandlers
|
5
|
+
|
6
|
+
#
|
7
|
+
# LoadGameFiles will load all the game files within the current working
|
8
|
+
# directory that are in the pre-defined Metro game folders.
|
9
|
+
#
|
10
|
+
# LoadGameFiles uses ActiveSupport::Dependencies::WatchStack to spy on all
|
11
|
+
# the constants that are added when the game runs. This grants the class
|
12
|
+
# the ability to provide dynamic reloading of the classes as they change.
|
13
|
+
#
|
14
|
+
class LoadGameFiles
|
15
|
+
|
16
|
+
#
|
17
|
+
# @param [Metro::Parameters::Options] options the options that the game
|
18
|
+
# was provided when it was launched.
|
19
|
+
#
|
20
|
+
def setup(options)
|
21
|
+
load_game_files!
|
22
|
+
end
|
23
|
+
|
24
|
+
#
|
25
|
+
# Drop any already defined events. Drop all the existing classes, reload
|
26
|
+
# the game files, and prepare the new game files for unloading the next
|
27
|
+
# time around that reload has been called.
|
28
|
+
#
|
29
|
+
def load_game_files!
|
30
|
+
EventDictionary.reset!
|
31
|
+
Image.images.clear
|
32
|
+
Animation.images.clear
|
33
|
+
Song.songs.clear
|
34
|
+
Font.fonts.clear
|
35
|
+
|
36
|
+
prepare_watcher!
|
37
|
+
load_game_files
|
38
|
+
execute_watcher!
|
39
|
+
end
|
40
|
+
|
41
|
+
#
|
42
|
+
# Launch the game in a sub-process in dry-run mode. Starting the
|
43
|
+
# game in dry-run mode here makes it so it will not launch a window
|
44
|
+
# and simply check to see if the code is valid and working correctly.
|
45
|
+
#
|
46
|
+
def launch_game_in_dry_run_mode
|
47
|
+
GameExecution.execute Game.execution_parameters + [ "--dry-run" ]
|
48
|
+
end
|
49
|
+
|
50
|
+
#
|
51
|
+
# The watcher should watch the Object Namespace for any changes. Any constants
|
52
|
+
# that are added will be tracked from this point forward.
|
53
|
+
#
|
54
|
+
def prepare_watcher!
|
55
|
+
ActiveSupport::Dependencies.clear
|
56
|
+
watcher.watch_namespaces([ Object ])
|
57
|
+
end
|
58
|
+
|
59
|
+
#
|
60
|
+
# The watcher will keep track of all the constants that were added to the Object
|
61
|
+
# Namespace after the start of the execution of the game. This will allow for only
|
62
|
+
# those objects to be reloaded.
|
63
|
+
#
|
64
|
+
def watcher
|
65
|
+
@watcher ||= ActiveSupport::Dependencies::WatchStack.new
|
66
|
+
end
|
67
|
+
|
68
|
+
def load_game_files
|
69
|
+
$LOAD_PATH.unshift(Dir.pwd) unless $LOAD_PATH.include?(Dir.pwd)
|
70
|
+
load_paths 'lib'
|
71
|
+
load_path 'scenes', prioritize: 'game_scene.rb'
|
72
|
+
load_path 'models', prioritize: 'game_model.rb'
|
73
|
+
end
|
74
|
+
|
75
|
+
def load_paths(*paths)
|
76
|
+
paths.flatten.compact.each {|path| load_path path }
|
77
|
+
end
|
78
|
+
|
79
|
+
def load_path(path,options = {})
|
80
|
+
files = Dir["#{path}/**/*.rb"]
|
81
|
+
files.sort! {|file| File.basename(file) == options[:prioritize] ? -1 : 1 }
|
82
|
+
files.each {|file| require_or_load file }
|
83
|
+
end
|
84
|
+
|
85
|
+
#
|
86
|
+
# The watcher will now mark all the constants that it has watched being loaded
|
87
|
+
# as unloadable. Doing so exhausts the list of constants found so the watcher
|
88
|
+
# will be empty.
|
89
|
+
#
|
90
|
+
# @note an exception is raised if the watcher is not prepared every time this
|
91
|
+
# is called.
|
92
|
+
#
|
93
|
+
def execute_watcher!
|
94
|
+
watcher.new_constants.each { |constant| unloadable constant }
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
register_setup_handler SetupHandlers::LoadGameFiles.new
|
100
|
+
|
101
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Metro
|
2
|
+
module SetupHandlers
|
3
|
+
|
4
|
+
#
|
5
|
+
# If the filename provide contains path information, then we need to move the
|
6
|
+
# current working directory into the root of the game directory. This is
|
7
|
+
# important because assets and other various paths are dependent on that
|
8
|
+
# being the location during execution.
|
9
|
+
#
|
10
|
+
class MoveToGameDirectory
|
11
|
+
#
|
12
|
+
# @param [Metro::Parameters::Options] options the options that the game
|
13
|
+
# was provided when it was launched.
|
14
|
+
#
|
15
|
+
def setup(options)
|
16
|
+
filename = options.filename
|
17
|
+
game_directory = File.dirname(filename)
|
18
|
+
Dir.chdir game_directory
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
register_setup_handler SetupHandlers::MoveToGameDirectory.new
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Metro
|
2
|
+
module SetupHandlers
|
3
|
+
|
4
|
+
#
|
5
|
+
# When the game is launched in **debug** mode the game directories will be
|
6
|
+
# monitored for changes. When a change occurs within one of the game source
|
7
|
+
# files the game and scene will be reloaded.
|
8
|
+
#
|
9
|
+
class ReloadGameOnGameFileChanges
|
10
|
+
|
11
|
+
#
|
12
|
+
# @NOTE this is duplication of the paths is also defined in LoadGameFiles.
|
13
|
+
# @see Metro::SetupHandlers::LoadGameFiles
|
14
|
+
#
|
15
|
+
def source_filepaths
|
16
|
+
[ 'lib', 'scenes', 'models' ]
|
17
|
+
end
|
18
|
+
|
19
|
+
def view_filepaths
|
20
|
+
[ 'views' ]
|
21
|
+
end
|
22
|
+
|
23
|
+
def asset_filepaths
|
24
|
+
[ 'assets' ]
|
25
|
+
end
|
26
|
+
|
27
|
+
def all_filepaths
|
28
|
+
source_filepaths + view_filepaths + asset_filepaths
|
29
|
+
end
|
30
|
+
|
31
|
+
#
|
32
|
+
# @param [Metro::Parameters::Options] options the options that the game
|
33
|
+
# was provided when it was launched.
|
34
|
+
#
|
35
|
+
def setup(options)
|
36
|
+
start_watcher if Game.debug?
|
37
|
+
end
|
38
|
+
|
39
|
+
def start_watcher
|
40
|
+
Thread.abort_on_exception = true
|
41
|
+
Thread.new { watch_filepaths(all_filepaths) }
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
# Defines the listener that will watch the filepaths
|
46
|
+
#
|
47
|
+
def watch_filepaths(filepaths)
|
48
|
+
listener = Listen.to(*filepaths)
|
49
|
+
listener.change(&on_change)
|
50
|
+
listener.start
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
# @return [Proc] the body of code to execute when a file change event has
|
55
|
+
# been received.
|
56
|
+
#
|
57
|
+
def on_change
|
58
|
+
Proc.new { |modified,added,removed| reload_game_because_files_changed(modified + added + removed) }
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
# Perform a game reload if the game source is valid.
|
63
|
+
#
|
64
|
+
def reload_game_because_files_changed(changed)
|
65
|
+
log.debug "Metro has detected #{changed.count} game source #{changed.count != 1 ? 'files have' : 'file has'} changed. RELOADING GAME CODE!"
|
66
|
+
if Metro.game_has_valid_code?
|
67
|
+
Game.current_scene.after(1.tick) { Metro.reload! ; transition_to(scene_name) }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
register_setup_handler SetupHandlers::ReloadGameOnGameFileChanges.new
|
74
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
#
|
2
|
+
# The lib folder is a great place for you to define:
|
3
|
+
#
|
4
|
+
# * New Units
|
5
|
+
# * Monkey Patches for Metro
|
6
|
+
# * New model properties
|
7
|
+
# * Custom Easings
|
8
|
+
# * Custom View Parers/Writers
|
9
|
+
# * Anything that isn't quite a model, scene, or view
|
10
|
+
#
|
11
|
+
|
12
|
+
#
|
13
|
+
# This custom easing is an exact copy of the 'Ease In' easing defined in Metro.
|
14
|
+
# It is present here as an example.
|
15
|
+
#
|
16
|
+
class CustomEasing < Metro::Easing
|
17
|
+
|
18
|
+
#
|
19
|
+
# @param [Float] moment the point in time within the interval. For example for
|
20
|
+
# a 60 tick interval, this would be the values 0, 1, 2, 3, 4, 5, 6, ... 59.
|
21
|
+
# @param [Float] start the starting value of the property
|
22
|
+
# @param [Float] change the final value for the property
|
23
|
+
# @param [Float] interval the total length of the interval
|
24
|
+
#
|
25
|
+
# @return [Float] the value at the particular moment of the interval
|
26
|
+
def self.calculation(moment,start,change,interval)
|
27
|
+
# @note this is the exact same as the already defined Ease In
|
28
|
+
change * (moment = moment / interval) * moment + start
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
Metro::Easing.register :custom, CustomEasing
|
data/lib/templates/game/metro.tt
CHANGED
@@ -15,7 +15,7 @@ name "<%= name %>"
|
|
15
15
|
# The author of the game. This method can be executed
|
16
16
|
# twice if more people are working on this game.
|
17
17
|
#
|
18
|
-
author "
|
18
|
+
author "Your Name"
|
19
19
|
|
20
20
|
#
|
21
21
|
# The website where the person playing this game
|
@@ -42,7 +42,6 @@ resolution 640, 480
|
|
42
42
|
#
|
43
43
|
first_scene :brand
|
44
44
|
|
45
|
-
|
46
45
|
#
|
47
46
|
# Defines controls which are meta events. They can be used group button
|
48
47
|
# events together under a single name so that you can use it throughout
|
@@ -61,4 +60,4 @@ end
|
|
61
60
|
# Game.debug? method will return a true
|
62
61
|
# value.
|
63
62
|
#
|
64
|
-
|
63
|
+
debug true
|
@@ -11,8 +11,9 @@ class GameScene < Metro::Scene
|
|
11
11
|
#
|
12
12
|
event :on_up, KbR do |event|
|
13
13
|
if event.control?
|
14
|
-
Metro.
|
15
|
-
|
14
|
+
if Metro.game_has_valid_code?
|
15
|
+
after(1.tick) { Metro.reload! ; transition_to(scene_name) }
|
16
|
+
end
|
16
17
|
end
|
17
18
|
end
|
18
19
|
|
@@ -28,7 +29,7 @@ class GameScene < Metro::Scene
|
|
28
29
|
|
29
30
|
#
|
30
31
|
# This animation helper will fade in and fade out information.
|
31
|
-
#
|
32
|
+
#
|
32
33
|
def fade_in_and_out(name)
|
33
34
|
animate name, to: { alpha: 255 }, interval: 2.seconds do
|
34
35
|
after 1.second do
|
data/lib/templates/message.erb
CHANGED
@@ -1,24 +1,23 @@
|
|
1
1
|
********************************************************************************
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
/_/ /_/ \___/ \__/ /_/ \____/
|
2
|
+
______ ___ _____
|
3
|
+
___ |/ /_____ __ /_______________
|
4
|
+
__ /|_/ / _ _ \_ __/__ ___/_ __ \
|
5
|
+
_ / / / / __// /_ _ / / /_/ /
|
6
|
+
/_/ /_/ \___/ \__/ /_/ \____/
|
8
7
|
|
9
|
-
|
10
|
-
-------------------------------------------------------------------------------
|
8
|
+
--------------------------------------------------------------------------------
|
11
9
|
<% messages.each do |message| %>
|
12
10
|
## <%= message.title %>
|
13
11
|
|
14
12
|
<%= message.message %>
|
15
13
|
|
16
|
-
|
14
|
+
<% unless message.actions.empty? %>## Details
|
17
15
|
|
18
|
-
<%= message.actions %>
|
19
|
-
<%
|
16
|
+
<%= message.actions %><% end %><% end %>
|
17
|
+
<% if website.present? || email.present? %>
|
20
18
|
## Contact
|
21
19
|
|
22
20
|
<%= website %>
|
23
21
|
<%= email %>
|
22
|
+
<% end %>
|
24
23
|
********************************************************************************
|
data/metro.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |gem|
|
|
10
10
|
gem.version = Metro::VERSION
|
11
11
|
gem.authors = ["Franklin Webber"]
|
12
12
|
gem.email = Metro::CONTACT_EMAILS
|
13
|
-
|
13
|
+
gem.license = "MIT"
|
14
14
|
gem.summary = <<-EOS
|
15
15
|
Metro is a 2D Gaming framework built around gosu (game development library).
|
16
16
|
Metro makes it easy to create games by enforcing common conceptual structures
|
@@ -28,6 +28,7 @@ Gem::Specification.new do |gem|
|
|
28
28
|
gem.add_dependency 'thor', '~> 0.16.0'
|
29
29
|
gem.add_dependency 'i18n', '~> 0.6.1'
|
30
30
|
gem.add_dependency 'active_support', '~> 3.0.0'
|
31
|
+
gem.add_dependency 'listen', '~> 0.6.0'
|
31
32
|
gem.add_development_dependency 'rspec', '~> 2.11'
|
32
33
|
|
33
34
|
gem.files = `git ls-files`.split($/)
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Metro::Parameters::CommandLineArgsParser do
|
4
|
+
|
5
|
+
describe "Class Methods" do
|
6
|
+
|
7
|
+
subject { described_class }
|
8
|
+
|
9
|
+
describe "#parse" do
|
10
|
+
context "when given no parameters" do
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
context "when given an array of parameters" do
|
15
|
+
|
16
|
+
subject { described_class.parse parameters }
|
17
|
+
let(:parameters) { [ '--upset-the-world', expected_filename, '--check-dependencies', 'unread_command' ] }
|
18
|
+
let(:expected_filename) { 'metro' }
|
19
|
+
|
20
|
+
it "should maintain an original parameter list" do
|
21
|
+
subject.execution_parameters.should eq parameters
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should consider the first non-flag the game file" do
|
25
|
+
subject.filename.should eq expected_filename
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should find all the flags" do
|
29
|
+
subject.upset_the_world?.should be_true
|
30
|
+
subject.check_dependencies?.should be_true
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should return false when non-existant flags are present" do
|
34
|
+
subject.wants_food_mild?.should be_false
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: metro
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -75,6 +75,22 @@ dependencies:
|
|
75
75
|
- - ~>
|
76
76
|
- !ruby/object:Gem::Version
|
77
77
|
version: 3.0.0
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: listen
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ~>
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 0.6.0
|
86
|
+
type: :runtime
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 0.6.0
|
78
94
|
- !ruby/object:Gem::Dependency
|
79
95
|
name: rspec
|
80
96
|
requirement: !ruby/object:Gem::Requirement
|
@@ -95,7 +111,7 @@ description: ! " Metro is a 2D Gaming framework built around gosu (game devel
|
|
95
111
|
library).\n Metro makes it easy to create games by enforcing common conceptual
|
96
112
|
structures\n and conventions.\n"
|
97
113
|
email:
|
98
|
-
-
|
114
|
+
- dev@rubymetro.com
|
99
115
|
executables:
|
100
116
|
- metro
|
101
117
|
extensions: []
|
@@ -103,6 +119,7 @@ extra_rdoc_files: []
|
|
103
119
|
files:
|
104
120
|
- .gitignore
|
105
121
|
- .rspec
|
122
|
+
- .travis.yml
|
106
123
|
- Gemfile
|
107
124
|
- Guardfile
|
108
125
|
- LICENSE.txt
|
@@ -182,6 +199,9 @@ files:
|
|
182
199
|
- lib/metro/models/ui/label.rb
|
183
200
|
- lib/metro/models/ui/menu.rb
|
184
201
|
- lib/metro/models/ui/rectangle.rb
|
202
|
+
- lib/metro/parameters/command_line_args_parser.rb
|
203
|
+
- lib/metro/parameters/options.rb
|
204
|
+
- lib/metro/parameters/parameters.rb
|
185
205
|
- lib/metro/sample.rb
|
186
206
|
- lib/metro/scene.rb
|
187
207
|
- lib/metro/scenes.rb
|
@@ -206,9 +226,16 @@ files:
|
|
206
226
|
- lib/metro/views/writers.rb
|
207
227
|
- lib/metro/views/yaml_view.rb
|
208
228
|
- lib/metro/window.rb
|
229
|
+
- lib/setup_handlers/exit_if_dry_run.rb
|
230
|
+
- lib/setup_handlers/game_execution.rb
|
231
|
+
- lib/setup_handlers/load_game_configuration.rb
|
232
|
+
- lib/setup_handlers/load_game_files.rb
|
233
|
+
- lib/setup_handlers/move_to_game_directory.rb
|
234
|
+
- lib/setup_handlers/reload_game_on_game_file_changes.rb
|
209
235
|
- lib/templates/game/README.md.tt
|
210
236
|
- lib/templates/game/assets/brand.jpg
|
211
237
|
- lib/templates/game/assets/hero.png
|
238
|
+
- lib/templates/game/lib/custom_easing.rb
|
212
239
|
- lib/templates/game/metro.tt
|
213
240
|
- lib/templates/game/models/hero.rb
|
214
241
|
- lib/templates/game/scenes/brand_scene.rb
|
@@ -239,6 +266,7 @@ files:
|
|
239
266
|
- spec/metro/models/properties/options_property/options_spec.rb
|
240
267
|
- spec/metro/models/properties/position_property_spec.rb
|
241
268
|
- spec/metro/models/ui/label_spec.rb
|
269
|
+
- spec/metro/parameters/command_line_args_parser_spec.rb
|
242
270
|
- spec/metro/scene_spec.rb
|
243
271
|
- spec/metro/scene_views/json_view_spec.rb
|
244
272
|
- spec/metro/scene_views/yaml_view_spec.rb
|
@@ -246,13 +274,17 @@ files:
|
|
246
274
|
- spec/metro/views/view_spec.rb
|
247
275
|
- spec/spec_helper.rb
|
248
276
|
homepage: https://github.com/burtlo/metro
|
249
|
-
licenses:
|
277
|
+
licenses:
|
278
|
+
- MIT
|
250
279
|
post_install_message: ! " ______ ___ _____\n ___ |/ /_____ __ /_______________\n
|
251
280
|
\ __ /|_/ / _ _ \\_ __/__ ___/_ __ \\\n _ / / / / __// /_ _ / /
|
252
281
|
/_/ /\n /_/ /_/ \\___/ \\__/ /_/ \\____/\n\n Thank you for installing
|
253
|
-
metro 0.3.
|
254
|
-
\ Changes:\n \n *
|
255
|
-
\
|
282
|
+
metro 0.3.2 / 2012-11-26.\n ---------------------------------------------------------------------\n
|
283
|
+
\ Changes:\n \n * Debug Mode will now automatically reload the game and scene
|
284
|
+
on source\n file changes.\n * Reloading the game will no longer take down the
|
285
|
+
app for syntax errors\n and other errors that are easily detected by simply loading
|
286
|
+
the code.\n * Template game is now automatically has debug mode enabled by default\n
|
287
|
+
\ \n\n ---------------------------------------------------------------------\n"
|
256
288
|
rdoc_options: []
|
257
289
|
require_paths:
|
258
290
|
- lib
|
@@ -291,6 +323,7 @@ test_files:
|
|
291
323
|
- spec/metro/models/properties/options_property/options_spec.rb
|
292
324
|
- spec/metro/models/properties/position_property_spec.rb
|
293
325
|
- spec/metro/models/ui/label_spec.rb
|
326
|
+
- spec/metro/parameters/command_line_args_parser_spec.rb
|
294
327
|
- spec/metro/scene_spec.rb
|
295
328
|
- spec/metro/scene_views/json_view_spec.rb
|
296
329
|
- spec/metro/scene_views/yaml_view_spec.rb
|