chingu_vectors 1.0.1 → 1.0.2
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/README +2 -0
- data/lib/actual_vectors.rb +119 -0
- data/lib/chingu_vectors.rb +5 -0
- data/lib/vector.rb +165 -0
- data/spec/vector_spec.rb +120 -0
- metadata +27 -10
data/README
CHANGED
@@ -40,6 +40,8 @@ This would be a method that lets a ball follow another ball ("follow") nice and
|
|
40
40
|
end
|
41
41
|
|
42
42
|
== Changelog
|
43
|
+
[1.0.2] * Fixed problem with gemspec
|
44
|
+
* Fixed Example a
|
43
45
|
[1.0.0] * Vector no longer inherits from Array
|
44
46
|
* Vector is constructable via []
|
45
47
|
* Added debug mode
|
@@ -0,0 +1,119 @@
|
|
1
|
+
module Chingu
|
2
|
+
module Traits
|
3
|
+
module Vectors
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
#
|
7
|
+
# Initializes trait with no costum options
|
8
|
+
#
|
9
|
+
def initialize_trait(options = { })
|
10
|
+
trait_options[:vectors] = { apply: true, debug: false }.merge(options)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
#
|
15
|
+
# Position of game object with [x,y] in pixel
|
16
|
+
#
|
17
|
+
attr_accessor :position
|
18
|
+
|
19
|
+
# Speed of game object with [x,y] in pixels per second
|
20
|
+
attr_accessor :speed
|
21
|
+
|
22
|
+
# Hasteing (acceleration) of game object with [x,y] in pixels per second^2
|
23
|
+
attr_accessor :hastening
|
24
|
+
|
25
|
+
# Position of game object in last tick
|
26
|
+
attr_reader :last_position
|
27
|
+
|
28
|
+
|
29
|
+
#
|
30
|
+
# Sets up the trait. Possible options are position, speed and hastening
|
31
|
+
# (with defaults [0,0] respectively) <br>
|
32
|
+
#
|
33
|
+
def setup_trait options
|
34
|
+
vectors_options = { :position => [0, 0],
|
35
|
+
:speed => [0, 0],
|
36
|
+
:hastening => [0, 0] }.merge(options)
|
37
|
+
self.position = vectors_options[:position]
|
38
|
+
self.speed = vectors_options[:speed]
|
39
|
+
self.hastening = vectors_options[:hastening]
|
40
|
+
#super
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
# Sets position to given vector or array(needs to have size 2)
|
45
|
+
# with [x,y] in pixels
|
46
|
+
#
|
47
|
+
def position= vector
|
48
|
+
@position = Vector[vector]
|
49
|
+
self.x = position.x
|
50
|
+
self.y = position.y
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
# Set speed to given vector or array(needs to have size 2)
|
55
|
+
# with [x,y] in pixels per second
|
56
|
+
#
|
57
|
+
def speed= vector
|
58
|
+
@speed = Vector[vector]
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
# Set hastening to given vector or array(needs to have size 2)
|
63
|
+
# with [x,y] in pixels per second^2
|
64
|
+
#
|
65
|
+
def hastening= vector
|
66
|
+
@hastening = Vector[vector]
|
67
|
+
end
|
68
|
+
|
69
|
+
#
|
70
|
+
# Moves the game object apropriate to the time that passed since last tick
|
71
|
+
#
|
72
|
+
def update_trait
|
73
|
+
if trait_options[:vectors][:apply]
|
74
|
+
seconds = $window.milliseconds_since_last_tick / 1000.0
|
75
|
+
@last_position = position
|
76
|
+
self.position = position + (speed * seconds)
|
77
|
+
self.speed = speed + (hastening * seconds)
|
78
|
+
end
|
79
|
+
super
|
80
|
+
end
|
81
|
+
|
82
|
+
def draw_trait
|
83
|
+
if trait_options[:vectors][:debug]
|
84
|
+
x = position.x
|
85
|
+
y = position.y
|
86
|
+
#draw speed
|
87
|
+
$window.draw_line(x, y, Gosu::Color::GREEN, x+speed.x, y+speed.y, Gosu::Color::GREEN, 1)
|
88
|
+
#draw hastening
|
89
|
+
$window.draw_line(x, y, Gosu::Color::CYAN, x+hastening.x, y+hastening.y, Gosu::Color::CYAN, 1)
|
90
|
+
end
|
91
|
+
super
|
92
|
+
end
|
93
|
+
|
94
|
+
#
|
95
|
+
# Stopes the game object. Speed = 0 and hastening = 0
|
96
|
+
#
|
97
|
+
def stop
|
98
|
+
self.speed = [0, 0]
|
99
|
+
self.hastening = [0, 0]
|
100
|
+
end
|
101
|
+
|
102
|
+
#
|
103
|
+
# Checks if game object is on move are hastening
|
104
|
+
#
|
105
|
+
def stopped?
|
106
|
+
speed == [0, 0]
|
107
|
+
hastening == [0, 0]
|
108
|
+
end
|
109
|
+
|
110
|
+
#
|
111
|
+
# Checks if game object hast moved since last tick
|
112
|
+
#
|
113
|
+
def moved?
|
114
|
+
last_position != position
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
data/lib/vector.rb
ADDED
@@ -0,0 +1,165 @@
|
|
1
|
+
module Chingu
|
2
|
+
module Traits
|
3
|
+
module Vectors
|
4
|
+
#A two dimensional vector
|
5
|
+
class Vector
|
6
|
+
|
7
|
+
Object.const_set(:Vector, Vector) unless Object.const_defined?(:Vector)
|
8
|
+
|
9
|
+
include NamedParameters
|
10
|
+
|
11
|
+
attr_accessor :x, :y
|
12
|
+
|
13
|
+
include Comparable
|
14
|
+
|
15
|
+
def <=>(other)
|
16
|
+
length <=> other.length
|
17
|
+
end
|
18
|
+
|
19
|
+
include Enumerable
|
20
|
+
|
21
|
+
def each
|
22
|
+
yield x
|
23
|
+
yield y
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
# @param [Number,Symbol] index Accessing the dimensions of the vector with 1, 2, :x or :y
|
28
|
+
# @return [Object] The object at the specified index
|
29
|
+
def [](index)
|
30
|
+
(index == 0 || index == :x) ? x : (index == 1 || index == :y) ? y : (raise IndexError.new("Vectors have only
|
31
|
+
two dimensions"))
|
32
|
+
end
|
33
|
+
|
34
|
+
# @param [Number,Symbol] index Accessing the dimensions of the vector with 1, 2, :x or :y
|
35
|
+
# @param [Object] object
|
36
|
+
def []=(index, object)
|
37
|
+
if (index == 0 || index == :x)
|
38
|
+
self.x = object
|
39
|
+
object
|
40
|
+
elsif (index == 1 || index == :y)
|
41
|
+
self.y = object
|
42
|
+
object
|
43
|
+
else
|
44
|
+
raise IndexError.new("Vectors have only two dimensions")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
named_parameters(x: 0, y: 0)
|
50
|
+
# @param [Numeric] x (0)
|
51
|
+
# @param [Numeric] y (0)
|
52
|
+
def initialize(x, y)
|
53
|
+
self[0] = x
|
54
|
+
self[1] = y
|
55
|
+
end
|
56
|
+
|
57
|
+
# @overload self.[](x,y)
|
58
|
+
# Create a new Vector with x and y values
|
59
|
+
# @param [Numeric] x
|
60
|
+
# @param [Numeric] y
|
61
|
+
# @overload self.[](array)
|
62
|
+
# Convert the +array+ into a new Vector
|
63
|
+
# @param [Array<Numeric>] array Needs Numerics at index 0 and 1
|
64
|
+
# @overload self.[](vector)
|
65
|
+
# Copies a vector
|
66
|
+
# @param [Vector] vector The Vector to be copied
|
67
|
+
def self.[](x, y=0)
|
68
|
+
if (x.is_a?(Numeric) && y.is_a?(Numeric))
|
69
|
+
new(x: x,
|
70
|
+
y: y)
|
71
|
+
elsif (x.is_a? Array)
|
72
|
+
new(x: x[0],
|
73
|
+
y: x[1])
|
74
|
+
elsif (x.is_a? Vector)
|
75
|
+
new(x: x.x,
|
76
|
+
y: x.y)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
ZERO = Vector.new(x: 0, y: 0)
|
81
|
+
UP = Vector.new(x: 0, y: -1)
|
82
|
+
DOWN = Vector.new(x: 0, y: 1)
|
83
|
+
LEFT = Vector.new(x: -1, y: 0)
|
84
|
+
RIGHT = Vector.new(x: 1, y: 0)
|
85
|
+
|
86
|
+
def to_s
|
87
|
+
"Vector[#{x},#{y}]"
|
88
|
+
end
|
89
|
+
|
90
|
+
#
|
91
|
+
# Returns length of vector
|
92
|
+
#
|
93
|
+
# @return [Numeric] Length of the vector
|
94
|
+
# @example Vector[5,5].length #=> 7.07106781
|
95
|
+
def length()
|
96
|
+
Math.sqrt(x**2 + y**2)
|
97
|
+
end
|
98
|
+
|
99
|
+
#
|
100
|
+
# Adds +vector+ to self, not manipulating
|
101
|
+
#
|
102
|
+
# @param [Vector,Array] vector Vector or Array with Numeric on index 0 and 1
|
103
|
+
# @example Vector[5,3]+Vector[11,-2] #=> Vector[16,1]
|
104
|
+
def + (vector)
|
105
|
+
Vector[x+vector[0], y+vector[1]]
|
106
|
+
end
|
107
|
+
|
108
|
+
#
|
109
|
+
# Substracts +vector+ to self, not manipulating
|
110
|
+
#
|
111
|
+
# @param [Vector,Array] vector Vector or Array with Numeric on index 0 and 1
|
112
|
+
# @example Vector[5,3]-Vector[11,-2] #=> Vector[-6,5]
|
113
|
+
def - (vector)
|
114
|
+
self + (vector * -1)
|
115
|
+
end
|
116
|
+
|
117
|
+
#
|
118
|
+
# Returns a new Vector that is +scalar+ times longer than +self+. Direction stays the same.
|
119
|
+
#
|
120
|
+
# @param [Numeric] scalar
|
121
|
+
# @example Vector[2,1]*5 #=> Vector[10,5]
|
122
|
+
def * (scalar)
|
123
|
+
Vector[x*scalar, y*scalar]
|
124
|
+
end
|
125
|
+
|
126
|
+
#
|
127
|
+
# Returns a new Vector that is +scalar+ times shorter than +self+. Direction stays the same.
|
128
|
+
#
|
129
|
+
# @raise [ZeroDivisionError] When +scalar+ == 0
|
130
|
+
# @param [Numeric] scalar
|
131
|
+
# @example Vector[10,5]/5 #=> Vector[2,1]
|
132
|
+
def / (scalar)
|
133
|
+
if scalar == 0
|
134
|
+
raise ZeroDivisionError("Division of vectors with zero not allowed")
|
135
|
+
else
|
136
|
+
self * (1.0 / scalar)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def -@
|
141
|
+
self * -1
|
142
|
+
end
|
143
|
+
|
144
|
+
#
|
145
|
+
# Returns a new vector with the same direction but with length 1.
|
146
|
+
#
|
147
|
+
def normalize
|
148
|
+
return self if length == 0
|
149
|
+
self / length
|
150
|
+
end
|
151
|
+
|
152
|
+
#
|
153
|
+
# Shortens / lengthnes the vector to length 1
|
154
|
+
#
|
155
|
+
# @return [Vector] self
|
156
|
+
def normalize!
|
157
|
+
normalized = normalize
|
158
|
+
self.x = normalized.x
|
159
|
+
self.y = normalized.y
|
160
|
+
self
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
data/spec/vector_spec.rb
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
require_relative '../lib/chingu_vectors'
|
2
|
+
|
3
|
+
describe Vector do
|
4
|
+
before(:each) do
|
5
|
+
@vector = Vector.new(x: 1, y: 1)
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should be constructable via x and y" do
|
9
|
+
vector2 = Vector.new(x: 1, y: 1)
|
10
|
+
vector2.should == @vector
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should be constructable via []" do
|
14
|
+
vector2 = Vector[1,1]
|
15
|
+
vector2.should == @vector
|
16
|
+
vector3 = Vector[[1,1]]
|
17
|
+
vector3.should == @vector
|
18
|
+
vector4 = Vector[vector2]
|
19
|
+
vector4.should == vector2
|
20
|
+
|
21
|
+
vector4.x = 2
|
22
|
+
vector4.should_not == vector2
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should be constructable with default values" do
|
26
|
+
#noinspection RubyArgCount
|
27
|
+
vector_both = Vector.new
|
28
|
+
vector_both.x.should == 0
|
29
|
+
vector_both.y.should == 0
|
30
|
+
|
31
|
+
vector_x = Vector.new(y: 1)
|
32
|
+
vector_x.x.should == 0
|
33
|
+
vector_x.y.should == 1
|
34
|
+
|
35
|
+
vector_y = Vector.new(x: 1)
|
36
|
+
vector_y.x.should == 1
|
37
|
+
vector_y.y.should == 0
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should be readable via x and y" do
|
41
|
+
@vector.x.should == 1
|
42
|
+
@vector.y.should == 1
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should be settable via x= and y=" do
|
46
|
+
@vector.x = 2
|
47
|
+
@vector.y = 2
|
48
|
+
@vector.should == Vector[2,2]
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should compute its length" do
|
52
|
+
|
53
|
+
@vector.length.should < 1.42
|
54
|
+
@vector.length.should > 1.41
|
55
|
+
|
56
|
+
vector2 = Vector[3.53553391, 3.53553391]
|
57
|
+
(vector2.length-5.0).should < 0.00001
|
58
|
+
|
59
|
+
vector3 = Vector[3.53553391, -3.53553391]
|
60
|
+
(vector3.length-5.0).should < 0.00001
|
61
|
+
|
62
|
+
vector4 = Vector[-3.53553391, 3.53553391]
|
63
|
+
(vector4.length-5.0).should < 0.00001
|
64
|
+
|
65
|
+
vector5 = Vector[0, 0]
|
66
|
+
vector5.length.should == 0
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should have the ZERO constant" do
|
70
|
+
Vector::ZERO.should == Vector[0, 0]
|
71
|
+
Vector::ZERO.should === Vector::ZERO
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should have the UP constant" do
|
75
|
+
Vector::UP.should == Vector[0, -1]
|
76
|
+
Vector::UP.should === Vector::UP
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should have the LEFT constant" do
|
80
|
+
Vector::LEFT.should == Vector[-1, 0]
|
81
|
+
Vector::LEFT.should === Vector::LEFT
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should have the DOWN constant" do
|
85
|
+
Vector::DOWN.should == Vector[0, 1]
|
86
|
+
Vector::DOWN.should === Vector::DOWN
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should have the RIGHT constant" do
|
90
|
+
Vector::RIGHT.should == Vector[1, 0]
|
91
|
+
Vector::RIGHT.should === Vector::RIGHT
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should be addable to other vectors" do
|
95
|
+
(@vector+@vector).should == Vector[2, 2]
|
96
|
+
@vector.should == Vector[1, 1] # + idempotent?
|
97
|
+
(@vector+Vector::ZERO).should == @vector
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should be substractable to other vectors" do
|
101
|
+
(@vector-@vector).should == Vector::ZERO
|
102
|
+
@vector.should == Vector[1, 1] # + idempotent?
|
103
|
+
(@vector-Vector::ZERO).should == @vector
|
104
|
+
|
105
|
+
(Vector[5, 3] - Vector[7, 10]).should == Vector[-2, -7]
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should be multiplied with a scalar" do
|
109
|
+
(Vector::UP * 5).should == Vector[0, -5]
|
110
|
+
(Vector::UP * 1.5).should == Vector[0, -1.5]
|
111
|
+
(Vector::LEFT * 0).should == Vector::ZERO
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should be dividable with a scalar" do
|
115
|
+
(Vector[5, 15] / 5).should == Vector[1, 3]
|
116
|
+
lambda { Vector::UP / 0 }.should raise_error
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chingu_vectors
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-05-
|
12
|
+
date: 2012-05-08 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: chingu
|
@@ -18,7 +18,7 @@ dependencies:
|
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 0.8.
|
21
|
+
version: 0.8.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -26,7 +26,7 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - ! '>='
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: 0.8.
|
29
|
+
version: 0.8.0
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
31
|
name: named_parameters
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -50,7 +50,10 @@ dependencies:
|
|
50
50
|
requirements:
|
51
51
|
- - ! '>='
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version:
|
53
|
+
version: 2.9.0
|
54
|
+
- - <
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: 3.0.0
|
54
57
|
type: :development
|
55
58
|
prerelease: false
|
56
59
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -58,7 +61,10 @@ dependencies:
|
|
58
61
|
requirements:
|
59
62
|
- - ! '>='
|
60
63
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
64
|
+
version: 2.9.0
|
65
|
+
- - <
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: 3.0.0
|
62
68
|
description: A Chingu trait that handles game object movement via vectors. Speed and
|
63
69
|
hastening are in pixels per second instead of pixels per tick, so your games run
|
64
70
|
always with the same speed independed of the current framerate
|
@@ -69,13 +75,22 @@ extra_rdoc_files:
|
|
69
75
|
- README
|
70
76
|
- LICENSE
|
71
77
|
files:
|
78
|
+
- lib/actual_vectors.rb
|
79
|
+
- lib/chingu_vectors.rb
|
80
|
+
- lib/vector.rb
|
72
81
|
- README
|
73
82
|
- LICENSE
|
74
|
-
|
83
|
+
- spec/vector_spec.rb
|
84
|
+
homepage: http://rubygems.org/gems/chingu_vectors
|
75
85
|
licenses:
|
76
86
|
- apache 2.0
|
77
87
|
post_install_message:
|
78
|
-
rdoc_options:
|
88
|
+
rdoc_options:
|
89
|
+
- --title
|
90
|
+
- Chingu vectors
|
91
|
+
- --main
|
92
|
+
- README
|
93
|
+
- --line_numbers
|
79
94
|
require_paths:
|
80
95
|
- lib
|
81
96
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -83,7 +98,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
83
98
|
requirements:
|
84
99
|
- - ! '>='
|
85
100
|
- !ruby/object:Gem::Version
|
86
|
-
version:
|
101
|
+
version: 1.9.0
|
87
102
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
103
|
none: false
|
89
104
|
requirements:
|
@@ -96,4 +111,6 @@ rubygems_version: 1.8.24
|
|
96
111
|
signing_key:
|
97
112
|
specification_version: 3
|
98
113
|
summary: A Chingu trait that handles game object movement via vectors
|
99
|
-
test_files:
|
114
|
+
test_files:
|
115
|
+
- spec/vector_spec.rb
|
116
|
+
has_rdoc:
|