Trouble with instance_nearest

X

x365

Guest
I'm at an absolute loss. Long story short, I have an obj_Player (naturally), obj_Enemy and obj_Friendly. I wan't obj_Friendly to flee when obj_Enemy is within var=attentionRange.

They both wander randomly in their normal state, however obj_Enemy has a follow state, to chase down the player. Regardless of obj_Enemys state, I want the obj_Friendly to flee when obj_Enemy is close enough.

I should mention I am relatively new to GM:S, but have been able to figure most out so far up until this point.

I want to check if the nearest obj_Enemy is within attentionRange with instance_nearest, but my attempts through the past 8 hours have all been failures. I have googled extensively and found basically every thread imaginable on how instance_nearest works. I have resorted to a simpler example to get the code to work for now, yet this fails me as well. I can't see that I have a syntax issue, but I sure hope that is it.

My simpler test is as follow:

Code:
var eTarget=instance_nearest(x,y,obj_Enemy)

if (distance_to_object(eTarget) < 100) {
    draw_set_colour(c_maroon);
    draw_text(view_xview[0]+15, view_yview[0]+80, "PROXIMITY ALERT")
}
I have tried substituting obj_Enemy with a parent object called obj_Parent_Enemy to no avail.
All my obj_Enemy's are spawned with a spawner (thus not placed in the room editor!), and I can only expect that to have something to say (basic instance_create of obj_Enemy at a random place in the room basically).

So in short; what am I doing wrong? How can I not set the eTarget variable to be the closest enemy with instance_nearest?

Thanks!
 
X

x365

Guest
Thanks!

I should probably have mentioned that!

I have tried multiple places - primarily I want to execute it in a script, but the above example is in the obj_Players step event.
 
B

Ben Hubble

Guest
Thanks!

I should probably have mentioned that!

I have tried multiple places - primarily I want to execute it in a script, but the above example is in the obj_Players step event.
The reason that piece of code won't work is because you're trying to draw text in the step event, not draw event.
 
X

x365

Guest
The reason that piece of code won't work is because you're trying to draw text in the step event, not draw event.
Ugh, well that is straight forward. Of course it needs to go there.
It works when I put it in obj_Players draw event, however this removes the obj_Players sprite.

Would I just draw_sprite for obj_Players x,y in the draw event as well and then re-link the code I have for sprite facing?

Now I have it confirmed to work, I'll hop back to looking into adding the instance_nearest to the actual code I need and probably be back for more help with that tomorrow :)

EDIT //

Still can't get the proper code to work. It is run in a script as a state of obj_Friendly.

Here is the script:

Code:
/// scr_friendly_flee

var enemyTarget=instance_nearest(x,y,obj_Parent_Enemy) // Find nearest enemy
var enemyDirection = point_direction(x,y,enemyTarget.x,enemyTarget.y) // Find that enemys direction

// If there is no collision in a straight line between obj_Friendly & nearest enemy then alerted = true
if (!collision_line(x,y,enemyTarget.x,enemyTarget.y,obj_Wall,1,1)) alerted = true

// If alerted = true AND nearest enemy is within attentionrange
if (alerted = true) && (enemyTarget <= attentionRange) {
        direction = enemyDirection + 180 // Set direction to opposite of nearest enemy
        speed = friendlySpeed * 2 // Set normal speed to double
    }
    else
    {
        alerted = false
        state = states.friendlyStatic
    }
Which is triggered by this in the step event of obj_Friendly:

Code:
// Variables

var nearestEnemy = instance_nearest(x,y,obj_Parent_Enemy)

// States

switch(state)
{
    case states.friendlyStatic: scr_friendly_static(); break;
    case states.friendlyAttack: scr_friendly_attack(); break;
    case states.friendlyFollow: scr_friendly_follow(); break;
    case states.friendlyFlee: scr_friendly_flee(); break;
}

// Switch state if enemy is close

if point_distance(x,y,nearestEnemy.x,nearestEnemy.y) <= attentionRange { state = states.friendlyFlee }
 
Last edited by a moderator:
B

Ben Hubble

Guest
I think I see the issue, instance_nearest returns the id of the instance closest to you, and in this bit of the script:
Code:
if (alerted = true) && (enemyTarget <= attentionRange) {
       direction = enemyDirection + 180 // Set direction to opposite of nearest enemy
        speed = friendlySpeed * 2 // Set normal speed to double
    }
You're checking for (enemyTarget <= attentionRange), this won't work because remember, instance_nearest returns the id, not the x and y coordinates. So what you'd want to do is this:
Code:
if (alerted = true) && (enemyTarget.x <= attentionRange) && (enemyTarget.y <= attentionRange) {
       direction = enemyDirection + 180 // Set direction to opposite of nearest enemy
        speed = friendlySpeed * 2 // Set normal speed to double
    }
You get the id of the closest enemy, then get the enemy's x and y coordinates and compare them, not the id.
Tell me if this works!

EDIT: Also, if you've drawn anything in an object that DOES have a sprite, it will remove the sprite, so what you do is put this - draw_self(); - in the draw event, and the sprite will stay and all the text you drew will also stay.
 
Last edited by a moderator:

Nocturne

Friendly Tyrant
Forum Staff
Admin
@Ben Hubble : Your code won't work either, as that still doesn't get the range. It should be:

Code:
if (alerted = true){
        var dist = point_distance(x, y, enemyTarget.x, enemyTarget.y);
        if dist <= attentionRange {
               direction = enemyDirection + 180 // Set direction to opposite of nearest enemy
               speed = friendlySpeed * 2 // Set normal speed to double
        }
    }
Too be honest, since you call the distance function in the step event, just modify the code slightly to pass the results into the script and so save yourself calling it twice. Also note that anywhere you are using the point method (instance.var) to access variables, you should have an "if instance_exists" check somewhere before to make sure that the instance is valid otherwise you risk crashes.
 
Top