metro 0.3.4 → 0.3.5

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/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.completed? }
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
- Point.at(left,top)
81
+ point_at left, top
28
82
  end
29
83
 
30
84
  def top_right
31
- Point.at(right,top)
85
+ point_at right, top
32
86
  end
33
87
 
34
88
  def bottom_right
35
- Point.at(right,bottom)
89
+ point_at right, bottom
36
90
  end
37
91
 
38
92
  def bottom_left
39
- Point.at(left,bottom)
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 (right - left), (bottom - top)
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.4"
2
+ VERSION = "0.3.5"
3
3
  WEBSITE = "https://github.com/burtlo/metro"
4
- CONTACT_EMAILS = ["dev@rubymetro.com"]
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
@@ -36,6 +36,7 @@ module Metro
36
36
  # This is called every update interval while the window is being shown.
37
37
  #
38
38
  def update
39
+ state.fire_events_for_mouse_movement
39
40
  state.fire_events_for_held_buttons
40
41
  scene.base_update
41
42
  end
@@ -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 'active_support', '~> 3.0.0'
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