GML Shooting at nearest enemie in sight

T

T. Brugel

Guest
Hey everyone!

I am currently making a tower-defense survival game.
But I have a minor problem.
I am working on new levels for the game, and the levels get more complicated along the campaign of the game.
So there is a level, with a wall.
And I want my shooting towers not to be focusing enemies on the other side of the wall, because of the fact that tthere is a wall in between.
Instead, the tower should focus on the nearest enemie in sight.
Right now I store the nearest enemie in a variable:

var obj = instance_nearest(x, y, obj_enemy);

And when it is about to shoot it checks if the distance to the nearest enemie is smaller than or equal to the range of the tower.

I have no idea how I can make it so the tower focuses the nearest enemie in sight.
I guess something with collision lines?

Thanks in advance!

Cheers
 
P

PandaPenguin

Guest
is your game based on any sort of grid or cell layout?


EDIT: nvm, check out collision_line(), that should work regardless of grid or not
 
Last edited by a moderator:
T

T. Brugel

Guest
is your game based on any sort of grid or cell layout?


EDIT: nvm, check out collision_line(), that should work regardless of grid or not
Hi!

Thanks for the reply, but I already know about collision lines (and how to use them).
The thing is, I do not know how to check for the nearest enemie who is in sight using the collision line.
My game is not grid-based btw.

Thanks again!
 
P

PandaPenguin

Guest
hmm but then you should have all you need :D
unless...how is your game world set up? are the walls just sprites or actual objects?
 
T

T. Brugel

Guest
I am using tiles for walls, and invisible hitbox objects covering them.
This is the code in the alarm[0] event of my canon tower object.
Every time the alarm runs it shoots if possible.

Code:
// Define some variables
if (instance_exists(obj_enemy)) {
    var nearest = instance_nearest(x, y, obj_enemy);
   
    // Make the canon shoot
    if (instance_exists(obj_night)) {
        if (distance_to_object(nearest) <= range && !collision_line(x, y, nearest.x, nearest.y, obj_solid, false, true)) {
            image_speed = .5;
            var obj = instance_create(x, y, obj_trap_canon_bullet);
            obj.direction = image_angle;
            hp -= 1;
        }
    }
}

// Reset the alarm
alarm[0] = spd;
The problem is that I do not know how to check for the nearest enemy without a wall in between...
Right now it always focuses on the nearest enemie object, but it does not shoot when there is a wall in between.
I want it to change target to a new enemy which is in range and without a wall obstructing it.
 
P

PandaPenguin

Guest
ok^^ got it

so the thing is that you only check once for a nearby enemy in range

what you need is to loop all enemies in range and check each if it is in direct line of sight and fire at the first one found
I use a FOR loop to cycle through each existing instance of an object like this:

Code:
var target = noone;
for(var i = 0; i < instance_number(obj_enemy); i += 1){
 var nearest = instance_nearest(x, y, instance_find(obj_enemy, i));
 if (distance_to_object(nearest) <= range && !collision_line(x, y, nearest.x, nearest.y, obj_solid, false, true))
 {
  //found nearest target with clear line of sight, exit for
  target = nearest;
  exit;
 }
}

//if any valid target found, target != noone
if(target)
{
 //your shooting code
}
EDIT:
this is just a quick whacked togehter example
you should refine it for better performance
like... cycle through all enemy instances and only check if they are in range and collect all that are in range in an array and after that cycle that array again with the collision_line code
this way you only collision checking the enemy instances that are actually in range
 
Last edited by a moderator:
T

T. Brugel

Guest
ok^^ got it

so the thing is that you only check once for a nearby enemy in range

what you need is to loop all enemies in range and check each if it is in direct line of sight and fire at the first one found
I use a FOR loop to cycle through each existing instance of an object like this:

Code:
var target = noone;
for(var i = 0; i < instance_number(obj_enemy); i += 1){
 var nearest = instance_nearest(x, y, instance_find(obj_enemy, i));
 if (distance_to_object(nearest) <= range && !collision_line(x, y, nearest.x, nearest.y, obj_solid, false, true))
 {
  //found nearest target with clear line of sight, exit for
  target = nearest;
  exit;
 }
}

//if any valid target found, target != noone
if(target)
{
 //your shooting code
}
EDIT:
this is just a quick whacked togehter example
you should refine it for better performance
like... cycle through all enemy instances and only check if they are in range and collect all that are in range in an array and after that cycle that array again with the collision_line code
this way you only collision checking the enemy instances that are actually in range
Thank you so much!
I really appreciate it!
 
Z

zendraw

Guest
i use this code for this

range=100;
with (enemy)
{
if (distance<other.range)
{
if (!collision_line)
{
other.range=distance
other.target=id
}
}
}

so basically it goes throu all enemy instances and if the distance is lower then the range, it lowers the range and sets the target which on the other hand resaults in false statement for enemies with larger distance then the range

but you must reset the range aways before proceeding with the code
 
T

T. Brugel

Guest
i use this code for this

range=100;
with (enemy)
{
if (distance<other.range)
{
if (!collision_line)
{
other.range=distance
other.target=id
}
}
}

so basically it goes throu all enemy instances and if the distance is lower then the range, it lowers the range and sets the target which on the other hand resaults in false statement for enemies with larger distance then the range

but you must reset the range aways before proceeding with the code
Hi!
Thanks a lot for the help.
Your code seems just a little bit simpler.
Thanks again!
Cheers!
 
Top