Code only works on first enemy created

Hi everyone, I've got a bit stuck on an issue. I have my music change when in a certain radius of an enemy. However it only seems to work on the first instance of the enemy that was created. Any idea why it only works on one enemy?
Big thankyou in advance for any help.

EDIT: Also worth pointing out if I kill the first enemy created the code does work on the second created.

Here's my code...

if (instance_exists(oEnemyArcher))
{
if (point_in_circle(oEnemyArcher.x,oEnemyArcher.y,x,y,300))
{
message += "I see you";
with (oMusic)
{
audio_sound_gain(mBattle,1,2000)
audio_sound_gain(mNormal,0,2000)
}
}
if (!point_in_circle(oEnemyArcher.x,oEnemyArcher.y,x,y,300))
{
message += "I dont see you";
with (oMusic)
{
audio_sound_gain(mBattle,0,2000)
audio_sound_gain(mNormal,1,2000)
}
}
}
 
Last edited:

FrostyCat

Member
Straight from the article you were told to read:
Collision-checking functions: instance_place() and instance_position() are the instance-ID-oriented analogues of place_meeting() and position_meeting(). Functions that start with collision_ but don't end in _list all return instance IDs. Save that instance ID into a variable, then use that as the subject to work with. DO remember to check that it is not noone before acting on it. DO NOT refer to this instance as other.
GML:
var inst_enemy = instance_place(x, y, obj_enemy);
if (inst_enemy != noone) {
    inst_enemy.hp -= 10;
}
 

Rob

Member
Thank you, I apologise, I did read it but I didn't fully understand.
You make different objects in gamemaker but in a room, you only have instances of objects. If you have 1 object and 10 instances of the same object, how do you tell them apart? By the instance_id, which is basically a long number.


How do you get an instance_id? There are a few ways - one of them is through using a function that returns an instance_id or noone. You can check the manual to see what a function returns (middle mouse click if you have a function typed out and you will be taken to the correct page).


GML:
//This function returns either an instance_id or noone. Either this instance is colliding with another, or it's not.
enemy = collision_point( x, y, obj_enemy, false, true );

//The next thing we'd do is:

if (enemy != noone){
   //there IS a collision, now we can do
   enemy.hp -= 5; //remove 5 from the enemy's hp variable.
   //OR
   with enemy instance_destroy(); //destroy the enemy instance
}
 
Just wanted to post up a solution that works in case anyone else learning is having trouble with the same issue with manually placed instances.
So I made this code and it may not be the most efficient ever but it works perfectly.

Thanks to all that helped

GML:
if (instance_exists(oEnemy))
{
    var closeToEnemy = false;
    
    var i;
    
    for (i=0; i<instance_number(oEnemy);i++)
    {
        var enemy = instance_find(oEnemy,i);
        if (point_in_circle(enemy.x,enemy.y,x,y,300))
        {
            closeToEnemy = true;
        }
    }
    
    if (closeToEnemy == true)
    {
        message += "I see you";
        with (oMusic)
        {   
            audio_sound_gain(mBattle,1,2000)
            audio_sound_gain(mNormal,0,2000)
        }
    }
    else
    {
        message += "I dont see you";
        with (oMusic)
        {   
            audio_sound_gain(mBattle,0,2000)
            audio_sound_gain(mNormal,1,2000)
        }
    }
}
 

Nidoking

Member
This is certainly not very efficient. You might want to look into functions like instance_nearest (and see whether that distance is less than 300) or collision_circle to find instances within a particular distance.
 
You don't want to loop through all instances. To adapt your original code:
GML:
// Don't hardcode your values into functions
// Put them as variables at the top for quick access and readability
var radius = 300;
var enemyToDetect = oEnemyArcher;
var preciseCollision = true // or false, up to you
var enemyDetected

// This will either return special object "noone" or return the instance ID
enemyDetected = collision_circle( x, y, radius, enemy, preciseCollision, true );

if enemyDetected != noone
{
    message += "I see you";
    with (oMusic)
    {
        audio_sound_gain(mBattle,1,2000)
        audio_sound_gain(mNormal,0,2000)
    }
}
else
{
    with (enemyDetected)
    {
        // Now you can do things to the specific enemy that you found
    }
    
    message += "I dont see you";
    with (oMusic)
    {
        audio_sound_gain(mBattle,0,2000)
        audio_sound_gain(mNormal,1,2000)
    }
}
 
Last edited:
You don't want to loop through all instances. To adapt your original code:
GML:
// Don't hardcode your values into functions
// Put them as variables at the top for quick access and readability
var radius = 300;
var enemyToDetect = oEnemyArcher;
var preciseCollision = true // or false, up to you
var enemyDetected

// This will either return special object "noone" or return the instance ID
enemyDetected = collision_circle( x, y, radius, enemy, preciseCollision, true );

if enemyDetected != noone
{
    message += "I see you";
    with (oMusic)
    {
        audio_sound_gain(mBattle,1,2000)
        audio_sound_gain(mNormal,0,2000)
    }
}
else
{
    with (enemyDetected)
    {
        // Now you can do things to the specific enemy that you found
    }
   
    message += "I dont see you";
    with (oMusic)
    {
        audio_sound_gain(mBattle,0,2000)
        audio_sound_gain(mNormal,1,2000)
    }
}
Thankyou so much for the help Shadowogre, I really appreciate it!
 
Top