Page 1 of 1

Finding the closest position

Posted: Sat Sep 27, 2014 12:21 am
by BruceTheGoose

Code: Select all

allies = {}
enemies = {}

for _,v in ipairs(allies) do
      if v.target == 0 then
        for i = 1, #enemies do
          v.currentBest = getMagnitude(v.x,enemies[i].x + enemy:getWidth()/2,v.y,enemies[i].y + enemy:getHeight()/2)
          if getMagnitude(v.x,enemies[i].x + enemy:getWidth()/2,v.y,enemies[i].y + enemy:getHeight()/2) >= v.currentBest then
            v.target = enemies[i]
            v.angle = math.atan2((enemies[i].y-v.y),(enemies[i].x - v.x))
          end
        end
      end
end
So I'm having trouble finding the appropriate way to find the nearest position of all the enemies and setting the target to the closest enemy.
The above code works but it does not look for the closest enemy. Instead, the allies go to the newest enemy spawned. If you can help me I would really appreciate it. :nyu:

Re: Finding the closest position

Posted: Sat Sep 27, 2014 12:44 am
by kikito
Funny, I was re-reading this blogpost in which I wrote code to do the very thing that you ask. See if this helps you:

http://kiki.to/blog/2012/03/16/small-fu ... -universe/

Re: Finding the closest position

Posted: Sat Sep 27, 2014 12:47 am
by BruceTheGoose
Coincidence? Thank you so much I'll look into it :)

Re: Finding the closest position

Posted: Sat Sep 27, 2014 1:05 am
by BruceTheGoose
If you use lots of functions like this one, your code tends to become unmanageable, especially if you return to it after not touching it for several months. It’s a code that you understand while you are writing, and certainly the machine understands it, but it doesn’t have “signposts” for future visitors. They have to “explore” it to know it.
I'm gonna rewrite all my code now :)

Re: Finding the closest position

Posted: Sat Sep 27, 2014 2:14 am
by BruceTheGoose
So I re-wrote my bullets and I'm getting a stupid error. I suspect the reason for the error is that I haven't created a new bullet and I'm calling its update function. Here is the code.

Code: Select all

Bullet = {}

function Bullet:New(x,y,x1,y1,rot,type,damage,speed)
  
  local startX = x
  local startY = y
  
  local angle = math.atan2((y1+troop:getHeight()/2-startY),(x1+troop:getWidth()/2-startX))
  
  self.x = x
  self.y = y
  
  self.rot = rot
  self.type = type
  self.damage = damage
  self.speed = speed
  self.y1 = y1
  self.x1 = x1
  self.dx = self.speed * math.cos(angle)
  self.dy = self.speed * math.sin(angle)
  self.timer = 0
  
end

function Bullet:update(dt)
 -- self:collide()
  self.x = self.x + (self.dx * dt)
  self.y = self.y + (self.dy * dt)
  self.timer = self.timer + dt
  if self.timer >= 2 then
    --self:remove()
  end
end

function Bullet:draw()
  if self.type == "elixir" then
    love.graphics.draw(elx,self.x,self.y,self.rot,1,1,elx:getWidth()/2,elx:getHeight()/2)
  end
end

function Bullet:collide()
end

function Bullet:remove()
  self = nil
end
The error is: bullet.lua:28: attempt to perform arithmetic on field 'dx' (a nil value)

Also how would I remove a bullet? Would

Code: Select all

self = nil
work?

Re: Finding the closest position

Posted: Sat Sep 27, 2014 8:57 am
by Robin
Please upload a .love. I suspect you're calling Bullet:update(dt) somewhere and that'll never work.

Also, Bullet:New is... not what you want it to do.

So instead:

Code: Select all

Bullet.__index = Bullet

function Bullet.New(x,y,x1,y1,rot,type,damage,speed)
  
  local startX = x
  local startY = y
  
  local angle = math.atan2((y1+troop:getHeight()/2-startY),(x1+troop:getWidth()/2-startX))
  
  local self = {} -- kind of misleading name, but I'm too lazy to change all the other variables
  self.x = x
  self.y = y
  
  self.rot = rot
  self.type = type
  self.damage = damage
  self.speed = speed
  self.y1 = y1
  self.x1 = x1
  self.dx = self.speed * math.cos(angle)
  self.dy = self.speed * math.sin(angle)
  self.timer = 0
  return setmetatable(self, Bullet)
end
Something like that.

Recommended reading: Chapter 13 of PIL.
BruceTheGoose wrote:Also how would I remove a bullet? Would

Code: Select all

self = nil
work?
No. You need to keep a list of bullets and remove them from that list.

Re: Finding the closest position

Posted: Sat Sep 27, 2014 3:49 pm
by BruceTheGoose
Here

Re: Finding the closest position

Posted: Sun Sep 28, 2014 9:16 am
by Robin
Okay, so you do a lot of things like:

Code: Select all

for _,v in ipairs(Bullet) do Bullet.update(dt)end
That doesn't work! That function needs a "self" argument. Either do:

Code: Select all

for _,v in ipairs(Bullet) do Bullet.update(v, dt)end
or:

Code: Select all

for _,v in ipairs(Bullet) do v:update(dt)end
(This is possible because of the __index and setmetatable I suggested.)

The same goes for Tower and Troop. So what's left to do?

When creating new objects, do something like this:

Code: Select all

Tower[#Tower + 1] = Tower.new(...)
Insert this at the end of love.update:

Code: Select all

for i = #Bullet, 1, -1 do if Bullet[i].remove then table.remove(Bullet, i) end end
Then you can do for remove:

Code: Select all

function Bullet.remove(self)
  self.remove = true
end

Re: Finding the closest position

Posted: Sun Sep 28, 2014 5:57 pm
by BruceTheGoose
Thank you so much!