• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

AI Target 'free' enemy

L

Latch

Guest
I'm messing about with AI and I have hit a bump.

My goal is to have two teams of AI shoot at each other without all shooting the same instance at the same time.

My thoughts is to always have the AI checking each target if it is currently under attack, if it isn't and is within range, attack that instance, and switch a variable in the AI called 'attacker' to equal the ID of, well, the attacker, and that is where I am at a loss.

I understand I may be able to use instance_find to cycle the enemies, and loop this until it finds one that has attacker = noone. Once this instance has been found how would I then go about setting the attacker variable to equal that of the attacker?

Unless of course I am way off and there is a better way to do this I just haven't thought of?
 

Bingdom

Googledom
Ok, this is what i have done in my game, When the war began.

The troops have 2 variables, target and team.

target - is used to check if it exists and in range.

team - is used to determine who to shoot at.

For the targeting system, i use ds_priority queues.

So for every troop, they basically do this:
Code:
///SCR_Find_Enemy
var ds;
ds = ds_priority_create();
ds_priority_add(ds,noone,100000); //Return noone if there is no enemies
with (OBJ_Troop) {
    if (team != other.team)  { //If it is an enemy
        ds_priority_add(ds,id,point_distance(x,y,other.x,other.y)); //Add to list, based on distance
    }
}
target = ds_priority_find_min(ds); //Find the closest enemy
ds_priority_destroy(ds);
You can modify the targeting system if you want to avoid them all attacking the same target, by giving them a flag called attacked and check if its false, then add to list.

Then when one of the troops die, you can check if the target exists, if it does then set the attacked to false from the target.
 
Last edited:

Mick

Member
Sounds good, this is how you set the attacker id (you would also need to check for distance etc):

Code:
enemy_attacking = noone;
with(obj_enemy)
{
  if(attacker == noone) {
    attacker = other.id;
    other.enemy_attacking = id;
    break;
  }
}
// enemy_attacking is now the enemy that should be attacked by this instance
 

TheouAegis

Member
A modification for that code:

Code:
///SCR_Find_Enemy
var ds = ds_priority_create();
var reach = argument0;    //Pass as argument0 the max distance to look
var range;
ds_priority_add(ds,noone,100000); //Return noone if there is no enemies
with (OBJ_Troop) {
   if (team != other.team)  { //If it is an enemy
        range = point_distance(x,y,other.x,other.y);
        if range < reach {
            ds_priority_add(ds,id,range + reach*attacked ); //Add to list, based on distance
        }
    }
}
target = ds_priority_find_min(ds); //Find the closest enemy
with target attacked = 1;
ds_priority_destroy(ds);

I made three changes. First, I made it so you can specify the distance of the attack so enemies that are out of range won't even be targeted (you don't want your enemies shooting from all the way across the map). Second, I allowed enemies that are already being attacked to still be attacked but placed much farther down in the priority queue. Third, I actually set the target's attacked variable.
 
Last edited:
Top