How to detect which object is closest to player?

I have an attack button in my game and when I press it my character attacks. Cool right. Yeah I know.

Anyway I want to find a way of detecting which of the enemies is closest to my player so my attack animation/sprite sheet will trigger for that enemy. Anyone have any ideas? I’m thinking that I make the collision box on my player very location specific so it obvious which enemy will be attacked and have a variable triggered that way.

What do you guys think? [import]uid: 26289 topic_id: 14387 reply_id: 314387[/import]

@CELL,
when you say closest, How do you *define* closest?

Do you place all your characters and monsters on a x,y grid, on the screen grid, how are they placed, the closest will be determined based on that.

the way to do that is simple

you have the Players, x and y
and if you have a lost of all the monsters, and you can iterate through them, then you would use a function like

[lua]local monsters = {} --this has all the monsters/enemies
local function getClosestTo(playerX, playerY)
local closestX, closestY, dx, dy = -1,-1, 0,0
local theOne = -1
local i
for i=1,#monsters do
dx = playerX - monsters[i].x
dy = playerY - monsters[i].y
if closestX == -1 and closestY == -1then
closestX = dx
closestY = dy
theOne = i
end
if dx< closestX and dy< closestY then
closestX = dx
closestY = dy
theOne = i
end
end

return theOne
end[/lua]

this shall get you the closest one to your player, this can be used on most of the ways, provided you have it in the manner required.

cheers,

?:slight_smile: [import]uid: 3826 topic_id: 14387 reply_id: 53165[/import]

There are a couple of ways to do this, and it also depends on further sub-categorization of your question like jayantv notes.

If you want to know the monsters in a certain area, you can use a sensor physics body.

For checking which object is closest of all out of a set, I would do a couple of modifications to jayantv’s code:

-- Player has x, y. Monsters is a table of monsters, again with x, y as members.  
local function getClosestTo(player, monsters)  
 if #monsters == 0 then  
 return  
 end  
  
 local function sqrDist(a, b)  
 local dx = a.x - b.x  
 local dy = a.y - b.y  
 return dx \* dx + dy \* dy  
 end  
  
 local theOne = 1  
 local theDist = sqrDist(player, monsters[theOne])  
  
 for i=2,#monsters do --consider changing to pairs function  
 local dist = sqrDist(player, monsters[i])  
 if dist \< theDist then  
 theDist = dist  
 theOne = i  
 end  
 end  
   
 return theOne  
end  

What this does is to check Pythagorean distance. I suppose you also might inline the sqrDist function, not sure if the Lua interpreter/compiler does this.

Beware that this has linear run time performance (it always checks vs all objects that exist, so if you have a huge number of objects it may be a problem). In that case a sensor body to preclude enemies might be more efficient as it uses spatial partitioning of Box2d.

Edit: Whoops forgot to make dx/dy locals. [import]uid: 58849 topic_id: 14387 reply_id: 53172[/import]

There is an overhead because there is a check for every monster on the screen, but then optimisation for that is another exercise. There are ways and means to manage that, just like there is a sensor, there can be similar ones that can set a flag on the monster of being in a threshold distance everytime the monsters move, so the check will be against only the ones that are in the threshold distance.

The addition of checking it in a radius is a good idea, but generally for beginners, I avoid providing them with that, I believe in giving them little steps. Give a recruit a bazooka, they can blow their own foot. so, easy little steps.

cheers,

?:slight_smile: [import]uid: 3826 topic_id: 14387 reply_id: 53178[/import]

I would have done it me7’s way. My question is why are you starting at index position 2? isn’t monster[1] important?
[import]uid: 19626 topic_id: 14387 reply_id: 53200[/import]

@rob,

me7 has placed 1 as the default monster closest to the player, so that is set as the closest one, there would be no point in checking for that one, what is checked is from #2 onwards.

I missed that in my code, but again, to write a sample code for to help someone understand is different from writing optimised code in a commercial app.

cheers,

?:slight_smile: [import]uid: 3826 topic_id: 14387 reply_id: 53202[/import]

Thanks guys. It’s cool that I got a layman’s and polished version, because now I can compare both the examples and hopefully learn even more.

My enemies aren’t in an array at present. I’m using the sensor function and have an attack button that works on logic more than math and that is something I need to work on, I think. The button is pushed and it runs through a bunch of logic variables to work out who to attack but it is very limited because I will need to keep adding every enemy to the mix.

I might create another topic to address this problem. Will come back to this one, once attack button issue has been resolved.

Cheers

EDIT: Actually if I am already using the sensor function is there a way of working out which enemy is closer by using this. The problem arises when two enemies are in the collision box with the player. When I press the attack button it chooses the enemy who entered the box first not the current closest. [import]uid: 26289 topic_id: 14387 reply_id: 53468[/import]