GameMaker Studio Turret shoots enemy

Hi guys! I want to ask for help! How can i make that in my game that my turret shoots an enemy whet its getting in a certain range???

Im trying with this scrip but it wont work :( Can somebody help me?


The code:

if(distance_to_object(obj_enemy) <200)
{
bullet=instance_create(x,y,Basic_attack)
with (bullet) {
bullet= move_towards_point( x, y, obj_enemy,x, obj_enemy,y);

image_angle=direction
}
}

Comments

  • edited
    Welcome :)

    There are a couple of things going on here that could be causing problems and/or be confusing you. Let me break them down:

    1. The way GM handles types of objects. I'm assuming that obj_enemy is what your enemy object is called in the object name window and what it shows up as in the side menu and the dropdowns, right? That means the word in script should go a special colour. Some functions, like distance_to_object (or many collision functions) can take an object type as a parameter and will try to search through all the instances of that specific type of object, so your current code will execute if there's an instance of obj_enemy closer to the turret than 200 pixels. Rad! The issue comes in when you then try to use the object type name to access an individual object OF that type. GM will let you do this, but what it will do is give you a handle to the FIRST object of that type that was instantiated. So where you ask for obj_enemy.x and obj_enemy.y, you're actually getting the x and y position of the very first enemy created, every time. It doesn't matter which enemy is closer, you're only getting the oldest current enemy's position.

    2. You're using commas instead of periods to access variables on an object... Basically "obj_enemy,x" won't work, it'll assume that you're moving on to the next parameter in a function. You should use "obj_enemy.x" if you want the x position of a thing.

    We can solve 1 (targeting the wrong object) by first grabbing a pointer to the nearest enemy and then using that to fire the bullet so that we make sure it goes to the correct place.

    //Find the nearest enemy:
    nearest_enemy = instance_nearest(obj_enemy);
    
    //Make sure we actually have something to aim at!
    if (nearest_enemy > 0) { //This is a GM pointer trick - pointers to objects are set to -1 if they're not pointing at anything
      //Check to see how close that enemy is:
      if (point_distance(x, y, nearest_enemy.x, nearest_enemy.y) < 200) {
        //Spawn a bullet:
        bullet = instance_create(x, y, Basic_attack);
      
        //Aim it at the specific enemy from earlier:
        with (bullet) {
          move_towards_point(other.nearest_enemy.x, other.nearest_enemy.y, bulletSpeed);
          image_angle = direction;
        }
      }
    }


    The other keyword inside the with statement allows us to use variables from the object that called the with. Inside the with everything is running on the object it was told to use - so in this case the with is running "on" the bullet that was just created, that bullet doesn't have a variable called nearest_enemy on it, so we have to use other to point to the turret, which is where that variable is defined. We could do this another way:

    //Aim it at the specific enemy from earlier:
      bullet.target = nearest_enemy;
      with (bullet) {
        move_towards_point(target.x, target.y, bulletSpeed);
        image_angle = direction;
      }


    That would work too. Hopefully you can see why :)

    But there's a problem, isn't there? This spews an unending stream of bullets at the nearest enemy. So it's progress, but it might not be what you want (unless you want to make a fire turret). How would you handle a firing cooldown?

    P.S. Forgive me, I haven't used GM in a while and there seem to be new functions that I wouldn't have used before. This is mostly from memory with a few trips to https://docs.yoyogames.com for reference ;)
    Thanked by 1pieter
Sign In or Register to comment.