1. Hey! Guest! The 35th GMC Jam will take place between November 28th, 12:00 UTC - December 2nd, 12:00 UTC. Why not join in! Click here to find out more!
    Dismiss Notice

GM:S 1.4 [Solved] Making an AI that avoids the edges of the room using Objects

Discussion in 'Programming' started by Irishes, Jun 29, 2017.

  1. Irishes

    Irishes Member

    Joined:
    Jun 27, 2016
    Posts:
    30
    I'm attempting to write an AI that moves until it gets close to the edge of the room. I added obj_boundary objects around the edge of the room. Every Ship creates a collision line 100 px in front of the ship. For some reason, when approaching the border from the right, the algorithm seems to work, but when approaching from the left, the ship takes longer to switch states.
     

    Attached Files:

  2. NightFrost

    NightFrost Member

    Joined:
    Jun 24, 2016
    Posts:
    1,977
    Without seeing any code, and using the scientific instrument of "just eyeballing it," the behavior looks as if the collision is always sensed from the right end of your collision line. So, a ship approaching the left boundary won't detect it before on top of it.

    EDIT: are you running some vector math scripts? Because it could be your code is confused about which end of the vector your ship is at.
     
    Last edited: Jun 29, 2017
    Irishes likes this.
  3. newtinn

    newtinn Member

    Joined:
    Dec 27, 2016
    Posts:
    52
    So Irishes if you want it just to go side to side you can just do this code:
    Code:
    // Collision with the right side
    if (place_meeting,x+1,y,obj_boundary) {
        hspeed = -10;
    }
    // Collision with the left side
    if (place_meeting,x-1,y,obj_boundary) {
        hspeed = 10;
    }
     
    Irishes likes this.
  4. Murzy

    Murzy Member

    Joined:
    Jul 28, 2016
    Posts:
    24
    It's hard to tell what is wrong with your code without seeing it first. Could you post it here so we could take a look?
     
    Irishes likes this.
  5. Irishes

    Irishes Member

    Joined:
    Jun 27, 2016
    Posts:
    30
    forwardCollisionLine = collision_line(x, y, direction+300, y, obj_boundary, false, false);

    if(forwardCollisionLine != noone){

    state = scr_ship_turn_left;
    }

    if(forwardCollisionLine == noone){

    state = scr_ship_fly;
    }

    I switched to this instead and it seems to work. Previously I had the ships change speed to their Minimum Speed before changing state. Ships still sometimes fly off the map if they cant make the turn.
     
  6. Murzy

    Murzy Member

    Joined:
    Jul 28, 2016
    Posts:
    24
    Ah, I see. The problem here is that the collision_line -function takes the following arguments:

    Code:
     collision_line( x1, y1, x2, y2, obj, prec, notme ); 
    However your x2, y2 aren't exactly what they are supposed to be. To make a line to 300px in front of the ship (i.e. pointing at the direction of the ship) you should do something like this:

    Code:
    var forward_look_distance = 300;
    var forward_x = x + lengthdir_x(forward_look_distance, direction);
    var forward_y = y + lengthdir_y(forward_look_distance, direction);
    
    forwardCollisionLine = collision_line(x, y, forward_x, forward_y, obj_boundary, false, false);
    
    if(forwardCollisionLine != noone){
        state = scr_ship_turn_left;
    }
    
    else if(forwardCollisionLine == noone){
        state = scr_ship_fly;
    }
    
    The lengthdir_x/y -functions are pretty well explained in the manual, I suggest that you look them up. They are very useful in a lot of things.

    Also, when debugging something like this, it usually is a good idea to visualize the problem. If you would have drawn a line using the values you put into your original collision_line(x1, y1, x2, y2) call, and had a similar draw_line(x1, y1, x2, y2) call in the draw event, you would have spotted that the line isn't where it is supposed to be.
     
    Irishes likes this.
  7. Irishes

    Irishes Member

    Joined:
    Jun 27, 2016
    Posts:
    30
    Ohhhhhh, that makes sense. What is direction+300 returning?
     
  8. Murzy

    Murzy Member

    Joined:
    Jul 28, 2016
    Posts:
    24
    The direction variable contains the heading of the ship (the angle) 0-360 in degrees. So adding the length of 300px to that doesn't really make any sense as even the units aren't the same! The collision_line function needs 2 positions to do the comparison against, so we need a way to convert the heading of the ship to an actual x,y position in front of it. That's what the solution above does.

    The point of the lengthdir -functions is to convert a given length, at a given angle, to a distance using the axis provided (x or y). I recommend checking out the manual page for this. There is a more detailed explanation in there.
     
    Irishes likes this.
  9. the_dude_abides

    the_dude_abides Member

    Joined:
    Jun 23, 2016
    Posts:
    672
    Murzy is offering useful advice - though I think if you're ship is only travelling left or right, then it can be simplified. The lengthdir commands are good for objects that move in any direction, as it takes that direction and figures a point at whatever distance ahead.

    But with only two directions its perhaps somewhat unnecessary to use it. I think you could do:
    Code:
    var side=sign(hspeed);
    switch (side)
    {
    case -1:
       forward_x = x - forward_look_distance;
       break;
    case 1:
      forward_x = x + forward_look_distance;
      break
    ;}
    forwardCollisionLine = collision_line(x, y, forward_x, forward_y, obj_boundary, false, false);
    followed by the rest of your code etc.

    Because you're only moving left or right (if I've understood correctly) you only need to find out which direction the ship is heading in. The variable 'hspeed' gets a minus when going left, and is a positive number when going right - using sign before a variable gets whether its positive, or negative, and so is a simple way to know whether 'forward_look_distance' should be added or subtracted from x. There is a switch statement which will set 'forward_x' to the appropriate amount.

    'Forward_x' will be either 0 degress or 180 degrees from the objects origin. I may be wrong, but I think doing it this way would be faster to process than using lengthdir commands in your situation.
     
    Irishes likes this.

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice