Class: Rubygame::Ftor
- Inherits:
-
Object
- Object
- Rubygame::Ftor
- Defined in:
- lib/rubygame/ftor.rb
Overview
NOTE: Ftor is DEPRECATED and will be removed in Rubygame 3.0! A mostly-compatible vector class will be provided at or before that time.
NOTE: you must require ‘rubygame/ftor’ manually to gain access to Rubygame::Ftor. It is not imported with Rubygame by default!
Ftor (“Fake vecTOR”), a vector-like class for 2D position/movement.
(NB: See #angle for an important note about why angles appear to be the opposite of what you may expect.)
Ftor is useful for storing 2D coordinates (x,y) as well as vector quantities such as velocity and acceleration (representationally, points and vectors are equivalent.) Although Ftors are always represented internally as Cartesian coordinates (x, y), it is possible to deal with an Ftor as polar coordinates (#angle, #magnitude) instead. See #new_am and #set_am!, for example.
Ftor is a “fake” vector because it has certain convenient properties which differ from “true” vectors (i.e. vectors in a strict mathematical sense).
Unlike vectors, Ftors may be multiplied or divided to another Ftor. This is equivalent to multiplying or dividing each component by the corresponding component in the second Ftor. If you like, you can think of this feature as scaling each component of the Ftor by a separate factor:
Ftor(a,b) * Ftor(c,d) = Ftor(a*c, b*d)
Of course, Ftors also have the usual vector behavior for addition/subraction between two Ftors, and multiplication/division of an Ftor by a scalar:
Ftor(a,b) + Ftor(c,d) = Ftor(a+c, b+d)
Ftor(a,b) * n = Ftor(a*n, b*n)
Additionally, Ftor contains functions for manipulating itself. You can both get and set such properties as #angle, #magnitude, #unit, and #normal, and the Ftor will change in-place as needed. For example, if you set #angle=, the vector will change to have the new angle, but keeps the same magnitude as before.
Ftor attempts to save processing time (at the expense of memory) by storing secondary properties (angle, magnitude, etc.) whenever they are calculated,so that they need not be calculated repeatedly. If the vector changes, the properties will be calculated again the next time they are needed. (In future versions, it may be possible to disable this feature for certain Ftors, for example if they will change very often, to save memory.)
Constant Summary collapse
Instance Attribute Summary collapse
-
#x ⇒ Object
The x component of the Ftor.
-
#y ⇒ Object
The y component of the Ftor.
Class Method Summary collapse
-
.new_am(a, m) ⇒ Object
See also #new.
-
.new_from_to(p1, p2) ⇒ Object
Returns a new Ftor which represents the difference in position of two points
p1andp2.
Instance Method Summary collapse
-
#*(other) ⇒ Object
Perform multiplication of this Ftor by the scalar
other, like so: Ftor(a,b) * n = Ftor(a*n, b*n). -
#+(other) ⇒ Object
Perform vector addition with this Ftor and
other, adding them on a component-by-component basis, like so: Ftor(a,b) + Ftor(c,d) = Ftor(a+c, b+d). -
#-(other) ⇒ Object
Like #+, but performs subtraction instead of addition.
-
#-@ ⇒ Object
The reverse of this Ftor.
-
#/(other) ⇒ Object
Like #*, but performs division instead of multiplication.
-
#==(other) ⇒ Object
True if this Ftor is equal to
other, when both have been converted to Arrays via #to_a. -
#[](i) ⇒ Object
Return the ith component of this Ftor, as if it were the Array returned by #to_a.
-
#_clear ⇒ Object
so that they will be recalculated the next time they are needed.
-
#angle ⇒ Object
(also: #a)
This is the same as the Ftor’s angle in a polar coordinate system.
-
#angle=(a) ⇒ Object
(also: #a=)
Set the angle (radians) of this Ftor from the positive X axis.
-
#angle_with(other) ⇒ Object
Return the difference in angles (radians) between this Ftor and
other. -
#dot(other) ⇒ Object
The dot product of two vectors
v1andv2is: v1.x * v2.x + v1.y * v2.y. -
#initialize(x, y) ⇒ Ftor
constructor
and #new_from_to.
-
#inspect ⇒ Object
Same as #to_s, but this Ftor’s #object_id is also displayed.
-
#inspect_am ⇒ Object
Same as #to_s_am, but this Ftor’s #object_id is also displayed.
-
#magnitude ⇒ Object
(also: #m)
This is the same as the Ftor’s magnitude in a polar coordinate system.
-
#magnitude=(m) ⇒ Object
(also: #m=)
In other words, the Ftor will point in the same direction, but it will be a different length from tail to head.
-
#normal ⇒ Object
(also: #n)
pi/2 radians, to be specific).
-
#normal=(other) ⇒ Object
(also: #n=)
Rotate this Ftor in-place, so that it is perpendicular to
other. -
#pretty ⇒ Object
“Pretty print”.
-
#pretty_am ⇒ Object
“Pretty print” with angle and magnitude.
-
#reverse! ⇒ Object
Like #-@, but reverses this Ftor in-place.
-
#rotate(radians) ⇒ Object
Like #rotate!, but returns a duplicate instead of rotating this Ftor in-place.
-
#rotate!(angle) ⇒ Object
Rotate this Ftor in-place by
angle(radians). -
#set!(x, y) ⇒ Object
Modify the x and y components of the Ftor in-place.
-
#set_am!(a, m) ⇒ Object
Modify the #angle (in radians) and #magnitude of the Ftor in-place.
-
#to_a ⇒ Object
(also: #to_ary)
Returns an Array of this Ftor’s components, [x,y].
-
#to_s ⇒ Object
Display this Ftor in the format: “#<Ftor: [x, y]>”.
-
#to_s_am ⇒ Object
Display this Ftor in the format: “#<Ftor:AM: [angle, magnitude]>”.
-
#udot(other) ⇒ Object
Return the #dot product of #unit vectors of this Ftor and
other. -
#unit ⇒ Object
(also: #u)
but a #magnitude of 1.
-
#unit=(other) ⇒ Object
(also: #u=, #align!)
vector of the given Ftor.
Constructor Details
#initialize(x, y) ⇒ Ftor
and #new_from_to.
82 83 84 85 |
# File 'lib/rubygame/ftor.rb', line 82 def initialize(x,y) Rubygame.deprecated("Rubygame::Ftor", "3.0") @x, @y = x, y end |
Instance Attribute Details
#x ⇒ Object
The x component of the Ftor.
105 106 107 |
# File 'lib/rubygame/ftor.rb', line 105 def x @x end |
#y ⇒ Object
The y component of the Ftor.
112 113 114 |
# File 'lib/rubygame/ftor.rb', line 112 def y @y end |
Class Method Details
.new_am(a, m) ⇒ Object
See also #new.
89 90 91 92 93 |
# File 'lib/rubygame/ftor.rb', line 89 def self.new_am(a,m) v = self.new(1,0) v.a, v.m = a, m return v end |
.new_from_to(p1, p2) ⇒ Object
Returns a new Ftor which represents the difference in position of two points p1 and p2. (p1 and p2 can be Ftors, size-2 Arrays, or anything else which has two numerical components and responds to #[].)
In other words, assuming v is the Ftor returned by this function:
p1 + v = p2
101 102 103 |
# File 'lib/rubygame/ftor.rb', line 101 def self.new_from_to(p1,p2) return self.new(p2[0]-p1[0],p2[1]-p1[1]) end |
Instance Method Details
#*(other) ⇒ Object
Perform multiplication of this Ftor by the scalar other, like so:
Ftor(a,b) * n = Ftor(a*n, b*n)
However, if this causes TypeError, attempt to extract indices 0 and 1 with other‘s #[] operator, and multiply them into the corresponding components of this Ftor, like so:
Ftor(a,b) * Ftor(c,d) = Ftor(a*c, b*d)
Ftor(a,b) * [c,d] = Ftor(a*c, b*d)
215 216 217 218 219 |
# File 'lib/rubygame/ftor.rb', line 215 def *(other) return self.class.new(@x*other,@y*other) rescue TypeError return self.class.new(@x*other[0],@y*other[1]) end |
#+(other) ⇒ Object
Perform vector addition with this Ftor and other, adding them on a component-by-component basis, like so:
Ftor(a,b) + Ftor(c,d) = Ftor(a+c, b+d)
198 199 200 |
# File 'lib/rubygame/ftor.rb', line 198 def +(other) return self.class.new(@x+other[0],@y+other[1]) end |
#-(other) ⇒ Object
Like #+, but performs subtraction instead of addition.
203 204 205 |
# File 'lib/rubygame/ftor.rb', line 203 def -(other) return self.class.new(@x-other[0],@y-other[1]) end |
#-@ ⇒ Object
The reverse of this Ftor. I.e., all components are negated. See also #reverse!.
186 187 188 |
# File 'lib/rubygame/ftor.rb', line 186 def -@ self.class.new(-@x,-@y) end |
#/(other) ⇒ Object
Like #*, but performs division instead of multiplication.
222 223 224 225 226 227 |
# File 'lib/rubygame/ftor.rb', line 222 def /(other) x, y = @x.to_f, @y.to_f return self.class.new(x/other,y/other) rescue TypeError return self.class.new(x/other[0],y/other[1]) end |
#==(other) ⇒ Object
True if this Ftor is equal to other, when both have been converted to Arrays via #to_a. In other words, a component-by-component equality check.
180 181 182 |
# File 'lib/rubygame/ftor.rb', line 180 def ==(other) to_a() == other.to_a end |
#[](i) ⇒ Object
Return the ith component of this Ftor, as if it were the Array returned by #to_a.
174 175 176 |
# File 'lib/rubygame/ftor.rb', line 174 def [](i) [@x,@y][i] end |
#_clear ⇒ Object
so that they will be recalculated the next time they are needed. Intended for internal use, but might be useful in other situations.
369 370 371 372 373 374 375 |
# File 'lib/rubygame/ftor.rb', line 369 def _clear @angle = nil @magnitude = nil @normal = nil @unit = nil return self end |
#angle ⇒ Object Also known as: a
This is the same as the Ftor’s angle in a polar coordinate system.
IMPORTANT: Because the positive Y axis on the Rubygame::Screen points downwards, an angle in the range 0..PI will appear to point downwards, rather than upwards! This also means that positive rotation will appear clockwise, and negative rotation will appear counterclockwise! This is the opposite of what you would expect in geometry class!
238 239 240 |
# File 'lib/rubygame/ftor.rb', line 238 def angle @angle or @angle = Math.atan2(@y,@x) end |
#angle=(a) ⇒ Object Also known as: a=
Set the angle (radians) of this Ftor from the positive X axis. Magnitude is preserved.
244 245 246 247 |
# File 'lib/rubygame/ftor.rb', line 244 def angle=(a) m = magnitude() set!( Math.cos(a)*m, Math.sin(a)*m ) end |
#angle_with(other) ⇒ Object
Return the difference in angles (radians) between this Ftor and other.
322 323 324 |
# File 'lib/rubygame/ftor.rb', line 322 def angle_with(other) Math.acos( self.udot(other) ) end |
#dot(other) ⇒ Object
The dot product of two vectors v1 and v2 is:
v1.x * v2.x + v1.y * v2.y
312 313 314 |
# File 'lib/rubygame/ftor.rb', line 312 def dot(other) @x*other[0] + @y*other[1] end |
#inspect ⇒ Object
Same as #to_s, but this Ftor’s #object_id is also displayed.
131 132 133 |
# File 'lib/rubygame/ftor.rb', line 131 def inspect "#<#{self.class}:#{object_id}: %f, %f>"%[@x,@y] end |
#inspect_am ⇒ Object
Same as #to_s_am, but this Ftor’s #object_id is also displayed.
148 149 150 |
# File 'lib/rubygame/ftor.rb', line 148 def inspect_am "#<#{self.class}:AM:#{object_id}: %f, %f>"%[angle(),magnitude()] end |
#magnitude ⇒ Object Also known as: m
This is the same as the Ftor’s magnitude in a polar coordinate system.
254 255 256 |
# File 'lib/rubygame/ftor.rb', line 254 def magnitude @magnitude or @magnitude = Math.hypot(@x,@y) end |
#magnitude=(m) ⇒ Object Also known as: m=
In other words, the Ftor will point in the same direction, but it will be a different length from tail to head.
262 263 264 265 |
# File 'lib/rubygame/ftor.rb', line 262 def magnitude=(m) new = unit() * m set!(new.x, new.y) end |
#normal ⇒ Object Also known as: n
pi/2 radians, to be specific).
272 273 274 |
# File 'lib/rubygame/ftor.rb', line 272 def normal @normal or @normal = unit().rotate(HALF_PI) end |
#normal=(other) ⇒ Object Also known as: n=
Rotate this Ftor in-place, so that it is perpendicular to other. This Ftor will be at an angle of -pi/2 to other.
278 279 280 |
# File 'lib/rubygame/ftor.rb', line 278 def normal=(other) set!( *(self.class.new(*other).unit().rotate(-HALF_PI) * magnitude()) ) end |
#pretty ⇒ Object
“Pretty print”. Same as #to_s, but components are displayed as rounded floats to 3 decimal places, for easy viewing.
143 144 145 |
# File 'lib/rubygame/ftor.rb', line 143 def pretty "#<#{self.class}: [%0.3f, %0.3f]>"%[@x,@y] end |
#pretty_am ⇒ Object
“Pretty print” with angle and magnitude. Same as #to_s_am, but components are displayed as rounded floats to 3 decimal places, for easy viewing.
162 163 164 |
# File 'lib/rubygame/ftor.rb', line 162 def pretty_am "#<#{self.class}:AM: [%0.3f, %0.3f]>"%[angle(),magnitude()] end |
#reverse! ⇒ Object
Like #-@, but reverses this Ftor in-place.
191 192 193 |
# File 'lib/rubygame/ftor.rb', line 191 def reverse! set!(-@x,-@y) end |
#rotate(radians) ⇒ Object
Like #rotate!, but returns a duplicate instead of rotating this Ftor in-place.
362 363 364 |
# File 'lib/rubygame/ftor.rb', line 362 def rotate(radians) self.dup.rotate!(radians) end |
#rotate!(angle) ⇒ Object
Rotate this Ftor in-place by angle (radians). This is the same as adding angle to this Ftor’s #angle.
– , with one important difference: This method will be much more efficient when rotating at a right angle, i.e.rotating by any multiple of PI/2 radians from -2*PI to 2*PI radians.
For convenience, and to ensure exactitude, several numerical constants have been defined for multiples of PI/2:
- Ftor::PI
-
(same as Math::PI)
- Ftor::HALF_PI
-
PI * 0.5 (or PI/2)
- Ftor::THREE_HALF_PI
-
PI * 1.5 (or 3*PI/2)
- Ftor::TWO_PI
-
PI * 2
++
IMPORTANT: Positive rotation will appear clockwise, and negative rotation will appear counterclockwise! See #angle for the reason.
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 |
# File 'lib/rubygame/ftor.rb', line 344 def rotate!(angle) # case(angle) # when HALF_PI, -THREE_HALF_PI # self.set!(@y,-@x) # when THREE_HALF_PI, -HALF_PI # self.set!(-@y,@x) # when PI, -PI # self.set!(@y,-@x) # when 0, TWO_PI, -TWO_PI # self.set!(@y,-@x) # else self.a += angle # end return self end |
#set!(x, y) ⇒ Object
Modify the x and y components of the Ftor in-place
120 121 122 123 |
# File 'lib/rubygame/ftor.rb', line 120 def set!(x,y) @x, @y = x,y _clear() end |
#set_am!(a, m) ⇒ Object
Modify the #angle (in radians) and #magnitude of the Ftor in-place
126 127 128 |
# File 'lib/rubygame/ftor.rb', line 126 def set_am!(a,m) self.angle, self.magnitude = a, m end |
#to_a ⇒ Object Also known as: to_ary
Returns an Array of this Ftor’s components, [x,y].
167 168 169 |
# File 'lib/rubygame/ftor.rb', line 167 def to_a [@x,@y] end |
#to_s ⇒ Object
Display this Ftor in the format: “#<Ftor: [x, y]>”. x and y are displayed as floats at full precision. See also #pp.
137 138 139 |
# File 'lib/rubygame/ftor.rb', line 137 def to_s "#<#{self.class}: [%f, %f]>"%[@x,@y] end |
#to_s_am ⇒ Object
Display this Ftor in the format: “#<Ftor:AM: [angle, magnitude]>”. angle and magnitude are displayed as floats at full precision. See also #to_s and #pp_am.
155 156 157 |
# File 'lib/rubygame/ftor.rb', line 155 def to_s_am "#<#{self.class}:AM: [%f, %f]>"%[angle(),magnitude()] end |
#udot(other) ⇒ Object
Return the #dot product of #unit vectors of this Ftor and other.
317 318 319 |
# File 'lib/rubygame/ftor.rb', line 317 def udot(other) unit().dot(self.class.new(*other).unit) end |
#unit ⇒ Object Also known as: u
but a #magnitude of 1. (This is sometimes called a “normalized” vector, not to be confused with a vector’s #normal.)
288 289 290 291 |
# File 'lib/rubygame/ftor.rb', line 288 def unit m = magnitude().to_f @unit or @unit = Ftor.new(@x/m, @y/m) end |
#unit=(other) ⇒ Object Also known as: u=, align!
vector of the given Ftor.
In other words, changes the #angle of this Ftor to be the same as the angle of the given Ftor, but this Ftor’s #magnitude does not change. – TODO: investigate efficiency of using ‘self.angle = other.angle` instead ++
301 302 303 |
# File 'lib/rubygame/ftor.rb', line 301 def unit=(other) set!( *(self.class.new(*other).unit() * magnitude()) ) end |