Module: Sc2::Position

Included in:
Api::Point, Api::Point2D, Api::PointI, Api::PowerSourceExtension, Api::Size2DI
Defined in:
lib/sc2ai/protocol/extensions/position.rb

Overview

A unified construct that tames Api::* messages which contain location data Items which are of type Sc2::Position will have #x and #y property at the least.

Constant Summary collapse

TOLERANCE =

Tolerance for floating-point comparisons.

1e-9

Instance Method Summary collapse

Instance Method Details

#==(other) ⇒ Boolean

Loose equality matches on floats x and y. We never check z-axis, because the map is single-level. TODO: We should almost certainly introduce TOLERANCE here, but verify it’s cost first.

Parameters:

Returns:

  • (Boolean)


15
16
17
18
19
20
21
# File 'lib/sc2ai/protocol/extensions/position.rb', line 15

def ==(other)
  if other.is_a? Position
    x == other.x && y == other.y
  else
    false
  end
end

#add(other) ⇒ Api::Point2D Also known as: +

A new point representing the sum of this point and the other point.

Parameters:

  • other (Api::Point2D, Numeric)

    The other point/number to add.

Returns:



26
27
28
29
30
31
32
# File 'lib/sc2ai/protocol/extensions/position.rb', line 26

def add(other)
  if other.is_a? Numeric
    Api::Point2D[x + other, y + other]
  else
    Api::Point2D[x + other.x, y + other.y]
  end
end

#angle_to(other) ⇒ Float

The angle between this vector and the other vector, in radians.

Parameters:

  • other (Api::Point2D)

    The other vector to calculate the angle to.

Returns:

  • (Float)


125
126
127
# File 'lib/sc2ai/protocol/extensions/position.rb', line 125

def angle_to(other)
  Math.acos(dot(other) / (magnitude * other.magnitude))
end

#away_from(other, distance) ⇒ Api::Point2D

Moves in direction away from the other point by distance

Parameters:

  • other (Api::Point2D)

    The target point to move away from

  • distance (Float)

    The distance to move.

Returns:



203
204
205
# File 'lib/sc2ai/protocol/extensions/position.rb', line 203

def away_from(other, distance)
  towards(other, -distance)
end

#cross_product(other) ⇒ Float

The cross product of this vector and the other vector.

Parameters:

  • other (Api::Point2D)

    The other vector to calculate the cross product with.

Returns:

  • (Float)


118
119
120
# File 'lib/sc2ai/protocol/extensions/position.rb', line 118

def cross_product(other)
  x * other.y - y * other.x
end

#distance_squared_to(other) ⇒ Float

The squared distance between this point and the other point.

Parameters:

  • other (Api::Point2D)

    The other point to calculate the squared distance to.

Returns:

  • (Float)


160
161
162
163
164
165
# File 'lib/sc2ai/protocol/extensions/position.rb', line 160

def distance_squared_to(other)
  if other.nil? || other == self
    return 0.0
  end
  (x - other.x) * (y - other.y)
end

#distance_to(other) ⇒ Float

Calculates the distance between self and other

Parameters:

Returns:

  • (Float)


150
151
152
153
154
155
# File 'lib/sc2ai/protocol/extensions/position.rb', line 150

def distance_to(other)
  if other.nil? || other == self
    return 0.0
  end
  Math.hypot(self.x - other.x, self.y - other.y)
end

#distance_to_circle(center, radius) ⇒ Float

The distance from this point to the circle.

Parameters:

  • center (Api::Point2D)

    The center of the circle.

  • radius (Float)

    The radius of the circle.

Returns:

  • (Float)


179
180
181
182
183
184
185
186
# File 'lib/sc2ai/protocol/extensions/position.rb', line 179

def distance_to_circle(center, radius)
  distance_to_center = distance_to(center)
  if distance_to_center <= radius
    0.0 # Point is inside the circle
  else
    distance_to_center - radius
  end
end

#distance_to_coordinate(x:, y:) ⇒ Float

Distance between this point and coordinate of x and y

Parameters:

  • x (Float, Integer)
  • y (Float, Integer)

Returns:

  • (Float)


171
172
173
# File 'lib/sc2ai/protocol/extensions/position.rb', line 171

def distance_to_coordinate(x:, y:)
  Math.hypot(self.x - x, self.y - y)
end

#divide(scalar) ⇒ Api::Point2D Also known as: /

Returns A new point representing this point divided by the scalar.

Parameters:

  • scalar (Float)

    The scalar to divide by.

Returns:

  • (Api::Point2D)

    A new point representing this point divided by the scalar.

Raises:

  • (ZeroDivisionError)

    if the scalar is zero.



59
60
61
62
# File 'lib/sc2ai/protocol/extensions/position.rb', line 59

def divide(scalar)
  raise ZeroDivisionError if scalar.zero?
  Api::Point2D[x / scalar, y / scalar]
end

#dot(other) ⇒ Float

The dot product of this vector and the other vector.

Parameters:

  • other (Api::Point2D)

    The other vector to calculate the dot product with.

Returns:

  • (Float)


111
112
113
# File 'lib/sc2ai/protocol/extensions/position.rb', line 111

def dot(other)
  x * other.x + y * other.y
end

#lerp(other, scale) ⇒ Api::Point2D

Linear interpolation between this point and another for scale Finds a point on a line between two points at % along the way. 0.0 returns self, 1.0 returns other, 0.5 is halfway.

Parameters:

  • scale (Float)

    a value between 0.0..1.0

Returns:



141
142
143
# File 'lib/sc2ai/protocol/extensions/position.rb', line 141

def lerp(other, scale)
  Api::Point2D[x + (other.x - x) * scale, y + (other.y - y) * scale]
end

#magnitudeFloat

For vector returns the magnitude, synonymous with Math.hypot

Returns:

  • (Float)


104
105
106
# File 'lib/sc2ai/protocol/extensions/position.rb', line 104

def magnitude
  Math.hypot(x, y)
end

#multiply(scalar) ⇒ Api::Point2D Also known as: *

Returns this point multiplied by the scalar

Parameters:

  • scalar (Float)

    The scalar to multiply by.

Returns:



50
51
52
# File 'lib/sc2ai/protocol/extensions/position.rb', line 50

def multiply(scalar)
  Api::Point2D[x * scalar, y * scalar]
end

#normalizeApi::Point2D

A new point representing the normalized version of this vector (unit length).

Returns:



131
132
133
# File 'lib/sc2ai/protocol/extensions/position.rb', line 131

def normalize
  divide(magnitude)
end

#offset(x = 0, y = 0) ⇒ Sc2::Position

Creates a new point with x and y which is offset

Parameters:

  • x (Float, Integer) (defaults to: 0)
  • y (Float, Integer) (defaults to: 0)

Returns:



86
87
88
# File 'lib/sc2ai/protocol/extensions/position.rb', line 86

def offset(x = 0, y = 0)
  dup.offset!(x, y)
end

#offset!(x = 0, y = 0) ⇒ Sc2::Position

Changes this point’s x and y by the supplied offset

Parameters:

  • x (Float, Integer) (defaults to: 0)
  • y (Float, Integer) (defaults to: 0)

Returns:



94
95
96
97
98
# File 'lib/sc2ai/protocol/extensions/position.rb', line 94

def offset!(x = 0, y = 0)
  self.x += x
  self.y += y
  self
end

#random_offset(offset) ⇒ Sc2::Position

Randomly adjusts both x and y by a range of: -offset..offset

Parameters:

  • offset (Float)

Returns:



69
70
71
# File 'lib/sc2ai/protocol/extensions/position.rb', line 69

def random_offset(offset)
  dup.random_offset!(offset)
end

#random_offset!(offset) ⇒ Sc2::Position

Changes this point’s x and y by the supplied offset

Returns:



75
76
77
78
79
80
# File 'lib/sc2ai/protocol/extensions/position.rb', line 75

def random_offset!(offset)
  offset = offset.to_f
  range = -offset..offset
  offset!(rand(range), rand(range))
  self
end

#subtract(other) ⇒ Api::Point2D Also known as: -

Returns a new point representing the difference between this point and the other point/number.

Parameters:

Returns:



38
39
40
41
42
43
44
# File 'lib/sc2ai/protocol/extensions/position.rb', line 38

def subtract(other)
  if other.is_a? Numeric
    Api::Point2D[x - other, y - other]
  else
    Api::Point2D[x - other.x, y - other.y]
  end
end

#towards(other, distance) ⇒ Api::Point2D

Moves in direction towards other point by distance

Parameters:

  • other (Api::Point2D)

    The target point to move to.

  • distance (Float)

    The distance to move.

Returns:



194
195
196
197
# File 'lib/sc2ai/protocol/extensions/position.rb', line 194

def towards(other, distance)
  direction = other.subtract(self).normalize
  add(direction.multiply(distance))
end