metro 0.3.4 → 0.3.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/Gemfile +2 -0
- data/README.md +18 -19
- data/changelog.md +5 -1
- data/lib/core_ext/numeric.rb +17 -0
- data/lib/metro.rb +8 -3
- data/lib/metro/animation/on_update_operation.rb +7 -7
- data/lib/metro/events/event_relay.rb +43 -1
- data/lib/metro/events/event_state_manager.rb +7 -0
- data/lib/metro/image.rb +13 -0
- data/lib/metro/models/model.rb +12 -2
- data/lib/metro/models/properties/options_property/options.rb +4 -0
- data/lib/metro/models/ui/physics_sprite.rb +105 -0
- data/lib/metro/models/ui/space.rb +152 -0
- data/lib/metro/models/ui/sprite.rb +2 -2
- data/lib/metro/models/ui/tile_map.rb +133 -0
- data/lib/metro/models/ui/tmx/isometric_position.rb +43 -0
- data/lib/metro/models/ui/tmx/orthogonal_position.rb +15 -0
- data/lib/metro/models/ui/tmx/tile_layer.rb +78 -0
- data/lib/metro/models/ui/ui.rb +3 -0
- data/lib/metro/scene.rb +2 -1
- data/lib/metro/units/rectangle_bounds.rb +75 -5
- data/lib/metro/version.rb +4 -4
- data/lib/metro/window.rb +1 -0
- data/lib/templates/game/assets/missing.png +0 -0
- data/lib/tmx_ext/object.rb +61 -0
- data/lib/tmx_ext/object_shape.rb +93 -0
- data/lib/tmx_ext/tile_set.rb +41 -0
- data/metro.gemspec +3 -1
- data/metro.png +0 -0
- data/spec/core_ext/numeric_spec.rb +28 -0
- data/spec/metro/image_spec.rb +33 -0
- data/spec/metro/units/rectangle_bounds_spec.rb +56 -0
- data/spec/tmx_ext/object_spec.rb +49 -0
- data/spec/tmx_ext/tile_set_spec.rb +24 -0
- metadata +56 -27
data/lib/metro/scene.rb
CHANGED
@@ -375,7 +375,7 @@ module Metro
|
|
375
375
|
def base_update
|
376
376
|
updaters.each { |updater| updater.update }
|
377
377
|
update
|
378
|
-
updaters.reject! { |updater| updater.
|
378
|
+
updaters.reject! { |updater| updater.update_completed? }
|
379
379
|
end
|
380
380
|
|
381
381
|
#
|
@@ -394,6 +394,7 @@ module Metro
|
|
394
394
|
def base_draw
|
395
395
|
drawers.each { |drawer| drawer.draw }
|
396
396
|
draw
|
397
|
+
drawers.reject! { |drawer| drawer.draw_completed? }
|
397
398
|
end
|
398
399
|
|
399
400
|
# This provides the functionality for view handling.
|
@@ -23,24 +23,90 @@ module Metro
|
|
23
23
|
@bottom = params[:bottom].to_f
|
24
24
|
end
|
25
25
|
|
26
|
+
#
|
27
|
+
# Move the bounds by the amount specified in the point.
|
28
|
+
#
|
29
|
+
def shift(point)
|
30
|
+
self.left = self.left + point.x
|
31
|
+
self.right = self.right + point.x
|
32
|
+
self.top = self.top + point.y
|
33
|
+
self.bottom = self.bottom + point.y
|
34
|
+
end
|
35
|
+
|
36
|
+
#
|
37
|
+
# Create a new RectangleBounds that is larger than the
|
38
|
+
# current bounds, given the specifed hash of parameters
|
39
|
+
# that contain the amount to expand in the four directions
|
40
|
+
# left, right, top, bottom.
|
41
|
+
#
|
42
|
+
def enlarge(params = {})
|
43
|
+
self.class.new(left: left - params[:left].to_i,
|
44
|
+
right: right + params[:right].to_i,
|
45
|
+
top: top - params[:top].to_i,
|
46
|
+
bottom: bottom + params[:bottom].to_i)
|
47
|
+
end
|
48
|
+
|
49
|
+
def shrink(params = {})
|
50
|
+
self.class.new(left: left + params[:left].to_i,
|
51
|
+
right: right - params[:right].to_i,
|
52
|
+
top: top + params[:top].to_i,
|
53
|
+
bottom: bottom - params[:bottom].to_i)
|
54
|
+
end
|
55
|
+
|
56
|
+
def clamp(point)
|
57
|
+
return point if contains?(point)
|
58
|
+
|
59
|
+
new_point = Point.new(point.x,point.y)
|
60
|
+
|
61
|
+
if point.x < left
|
62
|
+
new_point.x = left
|
63
|
+
end
|
64
|
+
|
65
|
+
if point.x > right
|
66
|
+
new_point.x = right
|
67
|
+
end
|
68
|
+
|
69
|
+
if point.y < top
|
70
|
+
new_point.y = top
|
71
|
+
end
|
72
|
+
|
73
|
+
if point.y > bottom
|
74
|
+
new_point.y = bottom
|
75
|
+
end
|
76
|
+
|
77
|
+
new_point
|
78
|
+
end
|
79
|
+
|
26
80
|
def top_left
|
27
|
-
|
81
|
+
point_at left, top
|
28
82
|
end
|
29
83
|
|
30
84
|
def top_right
|
31
|
-
|
85
|
+
point_at right, top
|
32
86
|
end
|
33
87
|
|
34
88
|
def bottom_right
|
35
|
-
|
89
|
+
point_at right, bottom
|
36
90
|
end
|
37
91
|
|
38
92
|
def bottom_left
|
39
|
-
|
93
|
+
point_at left, bottom
|
94
|
+
end
|
95
|
+
|
96
|
+
def width
|
97
|
+
(right - left)
|
98
|
+
end
|
99
|
+
|
100
|
+
def height
|
101
|
+
(bottom - top)
|
102
|
+
end
|
103
|
+
|
104
|
+
def center
|
105
|
+
top_left + point_at(width/2,height/2)
|
40
106
|
end
|
41
107
|
|
42
108
|
def dimensions
|
43
|
-
Dimensions.of
|
109
|
+
Dimensions.of width, height
|
44
110
|
end
|
45
111
|
|
46
112
|
def ==(value)
|
@@ -68,6 +134,10 @@ module Metro
|
|
68
134
|
|
69
135
|
private
|
70
136
|
|
137
|
+
def point_at(x,y)
|
138
|
+
Point.at(x,y)
|
139
|
+
end
|
140
|
+
|
71
141
|
def calculation_requirements
|
72
142
|
[ :left, :right, :top, :bottom ]
|
73
143
|
end
|
data/lib/metro/version.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
module Metro
|
2
|
-
VERSION = "0.3.
|
2
|
+
VERSION = "0.3.5"
|
3
3
|
WEBSITE = "https://github.com/burtlo/metro"
|
4
|
-
CONTACT_EMAILS = ["
|
5
|
-
|
4
|
+
CONTACT_EMAILS = ["franklin.webber@gmail.com"]
|
5
|
+
|
6
6
|
def self.changes_for_version(version)
|
7
7
|
|
8
8
|
change = Struct::Changes.new(nil,[])
|
@@ -28,5 +28,5 @@ module Metro
|
|
28
28
|
|
29
29
|
change
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
end
|
data/lib/metro/window.rb
CHANGED
Binary file
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Tmx
|
2
|
+
|
3
|
+
class Object
|
4
|
+
|
5
|
+
# TODO: the mass and moment of interia should configurable through properties
|
6
|
+
def body
|
7
|
+
@body ||= CP::Body.new default_mass, default_moment_of_inertia
|
8
|
+
end
|
9
|
+
|
10
|
+
def shape
|
11
|
+
@poly_shape ||= begin
|
12
|
+
new_shape = CP::Shape::Poly.new(body,poly_vec2s,default_shape_attach_point)
|
13
|
+
new_shape.collision_type = type.to_sym
|
14
|
+
new_shape.e = default_elasticity
|
15
|
+
new_shape.sensor = default_sensor
|
16
|
+
new_shape
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
#
|
23
|
+
# A TMX object currently has an array of points in a format
|
24
|
+
# list of strings. This will convert the points into
|
25
|
+
# list of CP::Vec2 objects which can be used to create the
|
26
|
+
# proper CP::Shape::Poly for the Object.
|
27
|
+
#
|
28
|
+
# @note this assumes that we want to convert the points into
|
29
|
+
# a format of vec2s specifically for a CP::Shape::Poly
|
30
|
+
# shape.
|
31
|
+
#
|
32
|
+
def poly_vec2s
|
33
|
+
points.map do |point|
|
34
|
+
x,y = point.split(",").map {|p| p.to_i }
|
35
|
+
CP::Vec2.new(x,y)
|
36
|
+
end.reverse
|
37
|
+
end
|
38
|
+
|
39
|
+
def default_sensor
|
40
|
+
false
|
41
|
+
end
|
42
|
+
|
43
|
+
def default_mass
|
44
|
+
Float::INFINITY
|
45
|
+
end
|
46
|
+
|
47
|
+
def default_moment_of_inertia
|
48
|
+
Float::INFINITY
|
49
|
+
end
|
50
|
+
|
51
|
+
def default_elasticity
|
52
|
+
0.0
|
53
|
+
end
|
54
|
+
|
55
|
+
def default_shape_attach_point
|
56
|
+
CP::Vec2::ZERO
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module Tmx
|
2
|
+
module ObjectShape
|
3
|
+
extend self
|
4
|
+
|
5
|
+
module ShapeDefaults
|
6
|
+
def default_sensor
|
7
|
+
false
|
8
|
+
end
|
9
|
+
|
10
|
+
def default_elasticity
|
11
|
+
0.0
|
12
|
+
end
|
13
|
+
|
14
|
+
def default_shape_attach_point
|
15
|
+
CP::Vec2::ZERO
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class PolyShape
|
20
|
+
include ShapeDefaults
|
21
|
+
|
22
|
+
def match?(object)
|
23
|
+
object.contents['shape'] == 'polygon'
|
24
|
+
end
|
25
|
+
|
26
|
+
def shape(object)
|
27
|
+
new_shape = CP::Shape::Poly.new(object.body,poly_vec2s(object),default_shape_attach_point)
|
28
|
+
new_shape.collision_type = object.type.to_sym
|
29
|
+
new_shape.e = default_elasticity
|
30
|
+
new_shape.sensor = default_sensor
|
31
|
+
new_shape
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# A TMX object currently has an array of points in a format
|
36
|
+
# list of strings. This will convert the points into
|
37
|
+
# list of CP::Vec2 objects which can be used to create the
|
38
|
+
# proper CP::Shape::Poly for the Object.
|
39
|
+
#
|
40
|
+
# @note this assumes that we want to convert the points into
|
41
|
+
# a format of vec2s specifically for a CP::Shape::Poly
|
42
|
+
# shape.
|
43
|
+
#
|
44
|
+
def poly_vec2s(object)
|
45
|
+
object.points.map do |point|
|
46
|
+
x,y = point.split(",").map {|p| p.to_i }
|
47
|
+
CP::Vec2.new(x,y)
|
48
|
+
end.reverse
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
class CircularShape
|
54
|
+
include ShapeDefaults
|
55
|
+
|
56
|
+
def match?(object)
|
57
|
+
object.contents['shape'] == 'ellipse'
|
58
|
+
# raise "Only circular shapes are allowed to be specified" if (object.width / 2) != (object.height / 2)
|
59
|
+
end
|
60
|
+
|
61
|
+
def shape(object)
|
62
|
+
radius = object.width / 2
|
63
|
+
offset = CP::Vec2.new(0,0)
|
64
|
+
new_shape = CP::Shape::Circle.new(object.body, radius, offset)
|
65
|
+
new_shape.collision_type = object.type.to_sym
|
66
|
+
new_shape.e = default_elasticity
|
67
|
+
new_shape.sensor = default_sensor
|
68
|
+
new_shape
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
class UnknownShape
|
74
|
+
def match?(object)
|
75
|
+
true
|
76
|
+
end
|
77
|
+
|
78
|
+
def shape(object)
|
79
|
+
raise "Invalid Shape defined in Object: #{object}"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def shapes
|
84
|
+
[ PolyShape.new, CircularShape.new, UnknownShape.new ]
|
85
|
+
end
|
86
|
+
|
87
|
+
def create_from_tmx_object(object)
|
88
|
+
shapes.find { |shape| shape.match?(object) }.shape(object)
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Tmx
|
2
|
+
|
3
|
+
#
|
4
|
+
# Define additional functionaly or override existing functionaliy on
|
5
|
+
# the Tmx class to make it compatible with Metro.
|
6
|
+
#
|
7
|
+
class TileSet
|
8
|
+
attr_accessor :window
|
9
|
+
|
10
|
+
def images
|
11
|
+
@images ||= raw_image_tiles.map {|image| crop_image(image) }
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def raw_image_tiles
|
17
|
+
Gosu::Image.load_tiles(window, image_path, full_image_width, full_image_height, false)
|
18
|
+
end
|
19
|
+
|
20
|
+
def crop_image(image)
|
21
|
+
Metro::Image.crop window, image, crop_bounds
|
22
|
+
end
|
23
|
+
|
24
|
+
def full_image_width
|
25
|
+
tilewidth + spacing
|
26
|
+
end
|
27
|
+
|
28
|
+
def full_image_height
|
29
|
+
tileheight + spacing
|
30
|
+
end
|
31
|
+
|
32
|
+
def crop_bounds
|
33
|
+
@crop_bounds ||= Metro::Units::RectangleBounds.new left: margin, top: margin,
|
34
|
+
right: full_image_width, bottom: full_image_height
|
35
|
+
end
|
36
|
+
|
37
|
+
def image_path
|
38
|
+
Metro::AssetPath.with(image).filepath
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/metro.gemspec
CHANGED
@@ -25,9 +25,11 @@ Gem::Specification.new do |gem|
|
|
25
25
|
gem.homepage = Metro::WEBSITE
|
26
26
|
|
27
27
|
gem.add_dependency 'gosu', '~> 0.7'
|
28
|
+
gem.add_dependency 'texplay', '~> 0.4'
|
29
|
+
gem.add_dependency 'tmx', '~> 0.1.2'
|
28
30
|
gem.add_dependency 'thor', '~> 0.16.0'
|
29
31
|
gem.add_dependency 'i18n', '~> 0.6.1'
|
30
|
-
gem.add_dependency '
|
32
|
+
gem.add_dependency 'activesupport', '~> 3.0.0'
|
31
33
|
gem.add_dependency 'listen', '~> 0.6.0'
|
32
34
|
gem.add_development_dependency 'rspec', '~> 2.11'
|
33
35
|
|
data/metro.png
ADDED
Binary file
|
@@ -75,4 +75,32 @@ describe Numeric do
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
|
+
describe "#to_degrees" do
|
79
|
+
context "when using a Float" do
|
80
|
+
it "converts the radians to degrees" do
|
81
|
+
3.1415.radians.to_degrees.should eq 179.99469134034814
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context "when using an Integer" do
|
86
|
+
it "converts the radians to degrees" do
|
87
|
+
4.radians.to_degrees.should eq 229.1831180523293
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe "#to_radians" do
|
93
|
+
context "when using a Float" do
|
94
|
+
it "converts the degrees to radians" do
|
95
|
+
360.5.degrees.to_radians.should eq 6.291911953439557
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context "when using an Integer" do
|
100
|
+
it "converts the degrees to radians" do
|
101
|
+
180.degrees.to_radians.should eq 3.141592653589793
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
78
106
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Metro::Image do
|
4
|
+
|
5
|
+
describe "Class Methods" do
|
6
|
+
|
7
|
+
let(:subject) { described_class }
|
8
|
+
|
9
|
+
describe ".crop" do
|
10
|
+
|
11
|
+
let(:image) { stub('Original Image') }
|
12
|
+
let(:window) { stub('Gosu::Window') }
|
13
|
+
let(:mock_image) { mock("TexPlay Created Image",refresh_cache: nil) }
|
14
|
+
let(:bounds) { Metro::Units::RectangleBounds.new(left: 2,top: 2,right: 30,bottom:30) }
|
15
|
+
|
16
|
+
let(:expected_crop_params) { [ bounds.left, bounds.top, bounds.right, bounds.bottom ]}
|
17
|
+
|
18
|
+
it "crops the image with the bounds provided" do
|
19
|
+
TexPlay.should_receive(:create_image).and_return(mock_image)
|
20
|
+
mock_image.should_receive(:splice).with(image,0,0,crop: expected_crop_params)
|
21
|
+
|
22
|
+
subject.crop(window,image,bounds)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "refreshes the cache for the image so when Metro reloads the images are not corrupt" do
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RectangleBounds do
|
4
|
+
|
5
|
+
let(:subject) { described_class.new left: 20, top: 30, right: 40, bottom: 60 }
|
6
|
+
|
7
|
+
shared_examples "valid point" do
|
8
|
+
it "correct point" do
|
9
|
+
expect(given_point).to eq expected_point
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#top_left" do
|
14
|
+
it_behaves_like "valid point" do
|
15
|
+
let(:given_point) { subject.top_left }
|
16
|
+
let(:expected_point) { Point.at 20, 30 }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#top_right" do
|
21
|
+
it_behaves_like "valid point" do
|
22
|
+
let(:given_point) { subject.top_right }
|
23
|
+
let(:expected_point) { Point.at 40, 30 }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#bottom_left" do
|
28
|
+
it_behaves_like "valid point" do
|
29
|
+
let(:given_point) { subject.bottom_left }
|
30
|
+
let(:expected_point) { Point.at 20, 60 }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#bottom_right" do
|
35
|
+
it_behaves_like "valid point" do
|
36
|
+
let(:given_point) { subject.bottom_right }
|
37
|
+
let(:expected_point) { Point.at 40, 60 }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "#center" do
|
42
|
+
it_behaves_like "valid point" do
|
43
|
+
let(:given_point) { subject.center }
|
44
|
+
let(:expected_point) { Point.at 30, 45 }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
describe "#dimensions" do
|
50
|
+
it "correct dimensions" do
|
51
|
+
expect(subject.dimensions).to eq Dimensions.of(20,30)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
end
|