Module: Sc2::Position

Included in:
Api::Point, Api::Point2D, Api::PointI, 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.



23
24
25
26
27
28
29
# File 'lib/sc2ai/protocol/extensions/position.rb', line 23

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.



34
35
36
37
38
39
40
# File 'lib/sc2ai/protocol/extensions/position.rb', line 34

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.



135
136
137
# File 'lib/sc2ai/protocol/extensions/position.rb', line 135

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



214
215
216
# File 'lib/sc2ai/protocol/extensions/position.rb', line 214

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

#cross_product(other) ⇒ Float

The cross product of this vector and the other vector.



128
129
130
# File 'lib/sc2ai/protocol/extensions/position.rb', line 128

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.



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

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



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

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.



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

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



182
183
184
# File 'lib/sc2ai/protocol/extensions/position.rb', line 182

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.

Raises:

  • (ZeroDivisionError)

    if the scalar is zero.



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

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.



121
122
123
# File 'lib/sc2ai/protocol/extensions/position.rb', line 121

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.



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

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



114
115
116
# File 'lib/sc2ai/protocol/extensions/position.rb', line 114

def magnitude
  Math.hypot(x, y)
end

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

Returns this point multiplied by the scalar



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

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

#normalizeApi::Point2D

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



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

def normalize
  divide(magnitude)
end

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

Creates a new point with x and y which is offset



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

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



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

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

#posSc2::Position

Returns self. If you’re ever unsure if you have a Unit or Position in hand, this method allows safely calling unknown_target.pos to return a position.

Examples:

target.pos


14
# File 'lib/sc2ai/protocol/extensions/position.rb', line 14

def pos = self

#random_offset(offset) ⇒ Sc2::Position

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



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

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

#random_offset!(offset) ⇒ Sc2::Position

Randomly change this point’s x and y by the supplied offset. i.e. offset=2 can adjust x and y by any number in range -2..2



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

def random_offset!(offset)
  offset = offset.to_f.abs
  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.



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

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

#to_atileArray<Integer, Integer>

Returns [x,y] array tuple where floats are cast to ints Useful when trying to find the tile which something is on



229
230
231
# File 'lib/sc2ai/protocol/extensions/position.rb', line 229

def to_atile
  [x.to_i, y.to_i]
end

#to_axyArray<Float, Float>

Returns [x,y] array tuple



222
223
224
# File 'lib/sc2ai/protocol/extensions/position.rb', line 222

def to_axy
  [x, y]
end

#to_sString



235
236
237
# File 'lib/sc2ai/protocol/extensions/position.rb', line 235

def to_s
  "#<#{self.class} x=#{x} y=#{y}>"
end

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

Moves in direction towards other point by distance



205
206
207
208
# File 'lib/sc2ai/protocol/extensions/position.rb', line 205

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