GMS 2 Self-Made (Very sketchy) Basic Pathfinding Troubles.

As the title states, I'm currently having trouble getting my enemy to move towards my character. I've built a very sketchy, but somewhat usable pathfinding system. (Which is just a simple bigger or smaller check, swapping between checking x and y) I've done this because in my game characters dash 64 pixels at a time, because I want it to be sorta rythmy-like. Anyways, to the point, I've checked this code over and over and I'm still unsure whats wrong. (Alarm 1 is just a simple speed = 0). The enemy sometimes dashes for 32, and sometimes, it looks like its having difficulties going sideways. Can someone tell me where I went wrong?

Code:
if(x = Player.x){
    xyorder = 1;
}
else{if(y = Player.y){
    xyorder = 0;
}
else{
    if(xyorder = 1){
        xyorder = 0;
    }
    if(xyorder = 0){
        xyorder = 1;
    }
}
}
if(xyorder = 1){
    if(Player.x > x){
        if(not place_meeting(x + 64,y,Enemy)){
        direction = 0
        speed = 8;
        alarm[1] = 8;
        }
    }
    if(Player.x < x){
        if(not place_meeting(x - 64,y,Enemy)){
            direction = 180;
            speed = 8;
            alarm[1] = 8;
        }
    }
}
if(xyorder = 0){
    if(Player.y > y){
        if(not place_meeting(x,y + 64,Enemy)){
        direction = 270
        speed = 8;
        alarm[1] = 8;
        }
    }
    if(Player.y < y){
        if(not place_meeting(x,y - 64,Enemy)){
            direction = 90;
            speed = 8;
            alarm[1] = 8;
        }
    }
}
alarm[0] = 60;
 

Roldy

Member
An alarm event, and from the enemy themselves.

So each enemy calls alarm[0] every 60 frames...

The first part reformatted and commented so it is readable:

GML:
if(x = Player.x){

    xyorder = 1;    // If enemy x == Player.x then move on x
 
} else{

    if(y = Player.y){
 
        xyorder = 0;  // if enemy y == Player.y then move on y
     
    } else {
 
        if(xyorder = 1) {   // Other wise flip xyorder
            xyorder = 0;
        }
     
        if(xyorder = 0){    // Even though we possibly just set xyorder = 0
            xyorder = 1;    // Lets just flip it back to 1 for no reason
        }
     
    }
}
Does the above sound like what you want to do?

The second part:

GML:
if(xyorder = 1){                          // Do we want to check if player is left or right
    if(Player.x > x){                    // Player is to the right
        if(not place_meeting(x + 64,y,Enemy)){  // If there is NOT an Enemy in 8 steps in front of me
            direction = 0                       // Then move towards right
            speed = 8;                             // I guess it doesn't matter if There was an enemy closer
            alarm[1] = 8;                        // Nor does it matter that the enemy might also be moving towards the player and wont actually be in my way in 8 frames.
                                                // I refuse to move
                              
        }
    }
    if(Player.x < x){                            // Lets do the same as above if player is to the left
        if(not place_meeting(x - 64,y,Enemy)){
            direction = 180;
            speed = 8;
            alarm[1] = 8;
        }
    }
}

if(xyorder = 0){        // Do we want to check if player is up or down on y axis?
    if(Player.y > y){   // If player is down
        if(not place_meeting(x,y + 64,Enemy)){ // Then check if an enemy is 8 frames away from me
            direction = 270                    // Lets again ignore if the enemy is closer or moving away
            speed = 8;                           // None of that matters I guess
            alarm[1] = 8;                    
        }
    }
    if(Player.y < y){    // If player is up
        if(not place_meeting(x,y - 64,Enemy)){ // Do the same check except going up
            direction = 90;
            speed = 8;
            alarm[1] = 8;
        }
    }
}
Does this sound right to you? Or do you think you might want things to work differently.

When you write code, make it look nice, read it back, comment and annotate it and see if it matches your expectations and makes sense.
 
So each enemy calls alarm[0] every 60 frames...

The first part reformatted and commented so it is readable:

GML:
if(x = Player.x){

    xyorder = 1;    // If enemy x == Player.x then move on x

} else{

    if(y = Player.y){

        xyorder = 0;  // if enemy y == Player.y then move on y
  
    } else {

        if(xyorder = 1) {   // Other wise flip xyorder
            xyorder = 0;
        }
  
        if(xyorder = 0){    // Even though we possibly just set xyorder = 0
            xyorder = 1;    // Lets just flip it back to 1 for no reason
        }
  
    }
}
Does the above sound like what you want to do?

The second part:

GML:
if(xyorder = 1){                          // Do we want to check if player is left or right
    if(Player.x > x){                    // Player is to the right
        if(not place_meeting(x + 64,y,Enemy)){  // If there is NOT an Enemy in 8 steps in front of me
            direction = 0                       // Then move towards right
            speed = 8;                             // I guess it doesn't matter if There was an enemy closer
            alarm[1] = 8;                        // Nor does it matter that the enemy might also be moving towards the player and wont actually be in my way in 8 frames.
                                                // I refuse to move
                           
        }
    }
    if(Player.x < x){                            // Lets do the same as above if player is to the left
        if(not place_meeting(x - 64,y,Enemy)){
            direction = 180;
            speed = 8;
            alarm[1] = 8;
        }
    }
}

if(xyorder = 0){        // Do we want to check if player is up or down on y axis?
    if(Player.y > y){   // If player is down
        if(not place_meeting(x,y + 64,Enemy)){ // Then check if an enemy is 8 frames away from me
            direction = 270                    // Lets again ignore if the enemy is closer or moving away
            speed = 8;                           // None of that matters I guess
            alarm[1] = 8;                 
        }
    }
    if(Player.y < y){    // If player is up
        if(not place_meeting(x,y - 64,Enemy)){ // Do the same check except going up
            direction = 90;
            speed = 8;
            alarm[1] = 8;
        }
    }
}
Does this sound right to you? Or do you think you might want things to work differently.

When you write code, make it look nice, read it back, comment and annotate it and see if it matches your expectations and makes sense.
Thankyou for this. You've pointed out alot of errors in my code, which im grateful for. (Especially the "Doesn't seem to matter if enemy is moving towards player" bit.) I'm going to try and put this all into action immediately! However, theres one problem. Since enemies each move at exactly the same time, how will I know which way the Enemy in front is going? This could be a problem, where the enemy thinks that the enemy in front will move out of the way, but the enemy in front changes its mind and moves towards the other enemy.
 
What I have so far, (Still stumped on making the Enemy avoid ally enemies)
GML:
//Make sure that we're not trying to move towards Player when X/Y are the same as Player X/Y
if(x = Player.x){
    xyorder = 0;
}
else{if(y = Player.y){
    xyorder = 1;
}
else{
    if(xyorder = 1){
        xyorder = 0;
    }
    else{
    if(xyorder = 0){
        xyorder = 1;
    }
    }
}

//Move towards player depending on X/Y differences
//X Movement
}
if(xyorder = 1){
    if(Player.x > x){
        if(not place_meeting(x + 64,y,Enemy)){
        direction = 0
        speed = 8;
        alarm[1] = debugdelay;
        travelling = true;
        }
    }
    //If player X > My x, try to close the gap while avoiding allies
  
    if(Player.x < x){
        if(not place_meeting(x - 64,y,Enemy)){
            direction = 180;
            speed = 8;
            alarm[1] = debugdelay;
            travelling = true;
        }
    }
    //If Player X < My x, try to close the gap while avoiding allies
  
}

//Y Movement

if(xyorder = 0){
    if(Player.y > y){
        if(not place_meeting(x,y + 64,Enemy)){
        direction = 270
        speed = 8;
        alarm[1] = debugdelay;
        travelling = true;
        }
    }
    //If Player Y > My Y, try to close the gap whilst avoiding allies
  
    if(Player.y < y){
        if(not place_meeting(x,y - 64,Enemy)){
            direction = 90;
            speed = 8;
            alarm[1] = debugdelay;
            travelling = true;
        }
    }
    //If Player Y < My Y, try to close the gap whilst avoiding allies
}
}
alarm[0] = 60;
 

Roldy

Member
What I have so far, (Still stumped on making the Enemy avoid ally enemies)
That can always be a tricky thing. But you have potentially made it much harder because of how you have decided to do movement.

I would say many games might suffer from the same dilemma you are facing except it isn't as noticeable because they do smaller movement increments. If two objects are moving around each other and taking many little steps then it is easy to approximate collisions.

However, the way you are attempting to do it with alarms and settings a motion once a second, you will have to do a lot more prediction or book keeping where other objects are or will be. This can become difficult. The same problems arise even in systems where small little steps are continuously processed, if speeds get too high. Because as the speed increases the amount of movement increases and more prediction is required.

I think the way you are trying to set it up with alarms would possibly work for a tile based or turn based game. But for movement in a more continuous space I would suggest processing the objects movement in little steps each frame. You can still have them move the same speed and amount you currently are, but instead of setting one big movement and waiting 60 frames, set little movement and process it every frame. This means you don't have to look very far ahead.
 
Top