metro 0.3.4 → 0.3.5

Sign up to get free protection for your applications and to get access to all the features.
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