Self.distanceTo(enemy) or self.distanceTo(enemy.pos)?


#1

Hi,
I have a very basic question:
Is there any difference between self.distanceTo(enemy) and self.distanceTo(enemy.pos) ?

Thanks


#2

I think (I’ve been saying that a lot today) that “distanceTo” is built to look for the “.pos” of the item passed to it. So, the magic gnomes see “self.distanceTo(enemy.pos)” as the distance to “enemy.pos.pos” which doesn’t make any sense to them.


#3

Actually, it should be the same. distanceTo will look for a Vector (which is what enemy.pos is), but if you don’t give it a Vector, it’ll see if the thing you gave it has a pos Vector in it and then use that. Are you seeing any differences between distanceTo(enemy) and distanceTo(enemy.pos)?

Just for kicks, here’s the code that does this:

Vector = require 'lib/world/vector'
Rectangle = require 'lib/world/rectangle'
Ellipse = require 'lib/world/ellipse'
{ArgumentError} = require 'lib/world/errors'

class Physical extends Component
  @className: 'Physical'
  hasRotated: false
  constructor: (config) ->
    super config
    @depth ||= @_calculateDepth()
    @pos = new Vector(@pos?.x or 0, @pos?.y or 0, @pos?.z or @depth / 2) unless @pos?.isVector
    @volume = @_calculateVolume()
    @dragArea = @_calculateDragArea()

  attach: (thang) ->
    super thang
    thang.addTrackedProperties ['rotation', 'number']

  rectangle: ->
    new Rectangle @pos.x, @pos.y, @width, @height, @rotation
    
  ellipse: ->
    new Ellipse @pos.x, @pos.y, @width, @height, @rotation
    
  getShape: ->
    if @shape is 'ellipsoid' or @shape is 'disc' then @ellipse() else @rectangle()
    
  isGrounded: ->
    @pos.z <= @depth / 2

  isAirborne: ->
    @pos.z > @depth / 2

  contains: (thang) ->
    # Determines whether thang's center is within our bounds.
    @getShape().containsPoint thang.pos

  distance: (thang, fromEdges=false) ->
    unless thang and (thang.isVector or thang.isThang or (not _.isNaN (thang.x + thang.y)))
      console.log 'distance from', @id, 'to', thang?.id, 'did not work: isVector', thang?.isVector, 'isThang', thang?.isThang, 'x', thang?.x, 'y', thang?.y, 'keys', _.keys thang
      throw new ArgumentError "Find the distance to a target unit.", "distance", "target", "object", thang
    # Determines the distance between the closest edges of @ and thang (0 if touching), or just centers if fromEdges is false.
    Math.sqrt @distanceSquared thang, fromEdges

  distanceSquared: (thang, fromEdges=false) ->
    if fromEdges
      shape = @getShape()
      return shape.distanceSquaredToPoint thang unless thang.pos
      otherShape = thang.getShape()
      return shape.distanceSquaredToShape otherShape
    else
      return @pos.distanceSquared thang.pos if thang.pos
      return @pos.distanceSquared thang  # a Vector

  # Alias distance as distanceTo, since it's more obvious at first that it's a method, for use in user-facing code.
  distanceTo: (thang) ->
    if thang and _.isString thang
      thang = @world.getThangByID thang
    else if thang and not thang.isThang and _.isString(thang.id) and targetThang = @world.getThangByID thang.id
      # Temporary workaround for Python API protection bug that makes them not Thangs
      thang = targetThang
    unless thang and (thang.isVector or thang.isThang or (not _.isNaN (thang.x + thang.y)))
      throw new ArgumentError "Find the distance to a target unit.", "distanceTo", "target", "object", thang
    @distance thang
  distanceToValidateReturn: (ret) ->
    unless _.isNumber ret
      throw new ArgumentError '', "distanceTo", "return", "number", ret

  intersects: (thang, t1=null) ->
    t1 ?= @
    t2 = thang
    return true if t1.contains t2
    s1 = t1.getShape?() ? t1  # pass Thangs or Shapes
    s2 = t2.getShape?() ? s2  # pass Thangs or Shapes
    s1.intersectsShape s2

  _calculateDepth: ->
    switch @shape
      when "box", "ellipsoid" then @height  # as deep as tall if unspecified
      when "sheet", "disc" then @height / 20

  _calculateVolume: ->
    switch @shape
      when "box", "sheet" then @width * @height * @depth
      when "ellipsoid", "disc" then 4 / 3 * Math.PI * @width * @height * @depth

  _calculateDragArea: ->
    # Assume it's facing to the right/left (height * depth face).
    # For a missile, we'd calculate just based on the head (height) sphere/cube, so it
    # can be an ellipsoid or box as long as the height dimension is the head diameter.
    switch @shape
      when "box", "sheet" then @height * @depth
      when "ellipsoid", "disc" then Math.PI / 4 * @height * @depth

And there’s also some here: https://github.com/codecombat/codecombat/blob/master/app/lib/world/vector.coffee#L43


#4

Thanks for answers,

I didn’t see any differences, in fact I was mainly interested to better understand the coding structure.
Looking at nick’s reply I am still a long way to master python…