Drag And Drop Random Enemy Movement For A Maze Game

Discussion in 'Programming' started by giraffeman210, Aug 24, 2019.

  1. giraffeman210

    giraffeman210 Member

    Joined:
    Sep 23, 2018
    Posts:
    72
    I am trying to make random enemy movement work for my maze game but can't find any tutorials on how to do it. I am trying to make it work so the enemies move in random directions but can not choose backwards or where there is a wall. Below is a response I had gotten but I don't know how to add the actual movement into this. I know its checking a bunch of stuff but how do I add movement to it? I am using DnD and GMS2. Thank you!

    "because there is not a do until loop in drag in drop your best bet is each time you wish to move to do the following

    set a variable called dchoosen to false
    repeat 20 times
    start block
    test variable dchoosen false
    check collision 64 0 wall relative not
    test chance 4
    start block
    set variable x 64 relative
    set variable dchosen true
    end block
    test variable dchoosen false
    check collision -64 0 wall relative not
    test chance 4
    start block
    set variable x -64 relative
    set variable dchosen true
    end block
    test variable dchoosen=false
    check collision 0 64 wall relative not
    test chance 4
    start block
    set variable y 64 relative
    set variable dchosen=true
    end block
    test variable dchoosen=false
    check collision 0 -64 wall relative not
    test chance 4
    start block
    set variable y -64 relative
    set variable dchosen=true
    end block
    endblock

    this is actually much easer and fasteer to do in code than block but that should work"
     
  2. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,889
    So a Pac-Man clone?

    Where the code "set x" or "set y" is where the movement is. That's more in line with an old roguelike, like Angband. You are better off setting hspeed or vspeed instead of manually adjusting x and y.

    How big are the walls in your game? Your walls are essentially aligned to a grid, right? How big is that grid?
     
    Last edited: Aug 25, 2019
  3. giraffeman210

    giraffeman210 Member

    Joined:
    Sep 23, 2018
    Posts:
    72
    Yeah that's the foundation I am going for. Like I said someone sent me the above system to put into my enemy AI but I don't know how to use that check system with movement. Once it checks all that stuff how do I determine movement?
     
  4. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,889
    I was editing my post. Go back and answer the last question. Lol
     
  5. giraffeman210

    giraffeman210 Member

    Joined:
    Sep 23, 2018
    Posts:
    72
    my grid is 64, 64
     
  6. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,889
    At least you can create temporary variables in GMS2's DnD. lol

    The following code assumes your enemy's sprite origin is CENTERED. I will also assume the size of your enemy sprite is 64x64 like the walls. It...shouldn't matter too much if it's not, though. This code also uses the built-in movement variables "direction". Set speed to how fast you want the enemy to move. Try to keep it at 0.5, 1, 1.5, 2, 4, or 8. If you want fractional speeds, you'll need to find my post on using fractional speeds with grid-aligned movement.

    When a line is indented, it means it belongs to the right of the action above it, since Studio2's DnD supposedly doesn't use "blocks" per se.

    In your step event:
    [​IMG] If Expression ( ( x - 32 ) + ( y - 32) ) mod 64 is equal to 0
    This will check if the enemy is in the middle of a grid cell
    Put the rest of this code inside the chain of actions for the
    true condition (default is to the right)

    [​IMG] Declare Temporary Variable paths[3] with value !position_meeting(x, y+64, wall) and direction != 90
    click the + sign 5 times to add 5 more variables
    + paths[2] with value !position_meeting(x - 64, y, wall) and direction != 0
    + paths[1]
    with value !position_meeting(x, y-64, wall) and direction != 270
    + paths[0]
    with value !position_meeting(x + 64, y, wall) and direction != 180
    The ! means we set each of these variables to 1 if position_meeting() is FALSE (meaning no walls blocking) and the enemy is not going the opposite way
    + targetH with value player.x - x replace "player" with your player object's name
    +
    targetV with value player.y - y
    If Expression abs(targetH) < abs(targetY) check if the player is closer horizontally than vertically
    [​IMG] If Variable paths[ 1 - sign(targetH) ] is equal to 1
    [​IMG] Assign Variable direction with value 90 - 90 * sign(targetH)
    [​IMG] Note: This goes BELOW the "If Variable" action
    If Variable paths[ 2 + sign(targetV) ] is equal to 1
    Assign Variable direction with value 180 + 90 * sign(targetV)
    [​IMG]
    Declare Temporary Variable rand with value irandom(3)
    [​IMG] While paths[ rand ] is equal to 0
    Assign Variable rand with value (rand + 1) mod 4
    This is a loop which will look through all paths and find an available one
    Note: Next line goes BELOW While since it is not a part of the loop
    Assign Variable direction with value rand * 90
    [​IMG] Note: This goes BELOW the "If Expression" action
    If Variable paths[ 2 + sign(targetV) ] is equal to 1
    Assign Variable direction with value 180 + 90 * sign(targetV)
    [​IMG]
    If Variable paths[ 1 - sign(targetH) ] is equal to 1
    Assign Variable direction with value 90 - 90 * sign(targetH)
    [​IMG]
    Declare Temporary Variable rand with value irandom(3)
    While paths[ rand ] is equal to 0
    Assign Variable rand with value (rand + 1) mod 4
    Assign Variable direction with value rand * 90
     
    TheSly and giraffeman210 like this.
  7. giraffeman210

    giraffeman210 Member

    Joined:
    Sep 23, 2018
    Posts:
    72
    Thank you so much for writing all of this out! I finally had time to put this code in (I had to work extra all week until now) I had some errors appear though when I finished.
    Object: object_enemy3 Event: Step at line 27 : unexpected symbol ")" in expression
    Object: object_enemy3 Event: Step at line 27 : malformed assignment
    Object: object_enemy3 Event: Step at line 24 : Cannot set a constant ("@@NewGMLArray@@") to a value
    Object: object_enemy3 Event: Step at line 25 : Cannot set a constant ("@@NewGMLArray@@") to a value
    Object: object_enemy3 Event: Step at line 26 : Cannot set a constant ("@@NewGMLArray@@") to a value
    Object: object_enemy3 Event: Step at line 27 : Cannot set a constant ("@@NewGMLArray@@") to a value
    Pretty sure these are all from the declaring temps at the beginning. Any ideas? Thanks again for helping with this and sorry for the late reply!
     
  8. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,889
    There is an option somewhere supposedly the turn dragon drop into gml, find that and copy the code. It could be a bug, a typo on your part, maybe type on my part. lol but the error is for the translated code.
     
  9. giraffeman210

    giraffeman210 Member

    Joined:
    Sep 23, 2018
    Posts:
    72
    Once you convert dnd to code though you cant convert it back. You can preview the dnd in code though. would that help find the problem?
     
  10. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,889
    Maybe. Probably.
     
  11. giraffeman210

    giraffeman210 Member

    Joined:
    Sep 23, 2018
    Posts:
    72
    These are the errors:
    Object: object_enemy3 Event: Step at line 27 : unexpected symbol ")" in expression
    Object: object_enemy3 Event: Step at line 27 : malformed assignment
    Object: object_enemy3 Event: Step at line 24 : Cannot set a constant ("@@NewGMLArray@@") to a value
    Object: object_enemy3 Event: Step at line 25 : Cannot set a constant ("@@NewGMLArray@@") to a value
    Object: object_enemy3 Event: Step at line 26 : Cannot set a constant ("@@NewGMLArray@@") to a value
    Object: object_enemy3 Event: Step at line 27 : Cannot set a constant ("@@NewGMLArray@@") to a value

    This is the code (read only):
    // GameMaker Language Preview (Read-Only)
    // If Expression
    if([(x - 32) + (y -32)] mod 64 = 0)
    {
    // Declare Temp
    var paths[3] = !position_meeting(x, y + 64, wall) and direction!= 90;
    var paths[2] = !position_meeting(x + 64, y, wall) and direction!= 0;
    var paths[1] = !position_meeting(x, y - 64, wall) and direction!= 270;
    var paths[0] = !position_meeting(x + 64, y, wall) and direction!= 180 );
    var targetH = object_player2.x - x;
    var targetV = object_player.y - y;
    // If Expression
    if(abs(targetH) < abs(targetV))
    {
    // If Variable
    if(paths[1 - sign(targetH)] == 1)
    {
    // Assign Variable
    direction = 90 - 90 * sign(targetH);
    }

    // Else
    else
    {
    // If Variable
    if(paths[2 + sign(targetV)] == 1)
    {
    // Assign Variable
    direction = 180 + 90 * sign(targetV);
    }

    // Else
    else
    {
    // Declare Temp
    var rand = irandom(3);

    // While Loop
    while ((path[rand] == 0)) {
    // Assign Variable
    rand = (rand + 1)mod 4;
    }

    // Assign Variable
    direction = rand * 90;
    }
    }
    }
    // Else
    else
    {
    // If Variable
    if(paths[2 + sign(targetV)] == 1)
    {
    // Assign Variable
    direction = 180 + 90 * sign(targetV);
    }

    // Else
    else
    {
    // If Variable
    if(paths[1 - sign(targetH)] == 1)
    {
    // Assign Variable
    direction = 90 - 90 * sign(targetH);
    }

    // Else
    else
    {
    // Declare Temp
    var rand = irandom(3);

    // While Loop
    while ((paths[rand] == 0)) {
    // Assign Variable
    rand = (rand + 1) mod 4;
    }

    // Assign Variable
    direction = rand * 90;
    }
    }
    }
    }
     
  12. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,889
    Did you put [ ] there orvdid Game Maker? It should be

    if ((x-32)+(y-32)) mod 64 = 0
     
  13. giraffeman210

    giraffeman210 Member

    Joined:
    Sep 23, 2018
    Posts:
    72
    I forgot I had put that in to try it and see if it worked and never changed it back. Now it says:
    Object: object_enemy3 Event: Step at line 27 : unexpected symbol ")" in expression
    plus the other ones
     
  14. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,889
    Try changing paths to PATHS.
     
  15. giraffeman210

    giraffeman210 Member

    Joined:
    Sep 23, 2018
    Posts:
    72
    nope same errors
     
  16. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,889
    Wow GMS2 dnd must suck compared to 1.4's...

    You changed ALL "paths" to "PATHS"? lol

    .....Change "direction" to "image_angle". I know it's a stupid suggestion, but curious if that changes the error.
     
  17. giraffeman210

    giraffeman210 Member

    Joined:
    Sep 23, 2018
    Posts:
    72
    Yeah they are all PATHS. And the errors are still
    Object: object_enemy3 Event: Step at line 24 : Cannot set a constant ("@@NewGMLArray@@") to a value
    after I changed direction to image_angle
     
  18. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,889
    That shouldn't be happening... Especially since the error says the array is a legit array... But it's a constant. It can't be a constant and an array! I say file a bug report. Cuz that [ ] i pointed out earlier was the only error i saw.
     
  19. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,889
    Hey man, did you get this working yet? YoyoGames renewed my license temporarily, so I may be able to try to work on this on my end.
     
  20. giraffeman210

    giraffeman210 Member

    Joined:
    Sep 23, 2018
    Posts:
    72
    No not yet. Would it be easier if the enemies didn't have to follow the player? I think that's probably what I will need anyway. Just roaming enemies that pick random paths that are free of walls and won't go backwards.
     
  21. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,889
    Edit: I think I confused myself in that original code, too. All the times where I had something like
    if paths[1 - 90 * sign(targetH)] == 1
    it should have been 0, not 1. A value of 1 meant the path was blocked, while 0 meant it's open. And we're trying to find an open path. lol

    Edit 2: I confused myself twice. I forgot I used ! before position_meeting(), so my original code was fine. So now I removed ! from all my code. ... I'm so confused. I should just go to work now.


    Anyway, I found the issue. I think it's a bug, personally, but there is a workaround. Unfortunately, you're going to have to retype stuff (if you want to keep it in DnD).

    (minor edit: It's not really a bug, since it's in GML also. You can't declare a temporary array, but you can declare a temporary variable and then convert it to an array. That's what the below code does.)

    The workaround is you need to declare paths (or PATHS by now, lol) as a temporary variable set to 0. Once paths (or PATHS) has been created, then you can convert it to an array.

    [​IMG] Declare Temporary Variable paths with value 0
    click the + sign 2 times to add 2 more variables
    + targetH with value player.x - x replace "player" with your player object's name
    +
    targetV with value player.y - y

    [​IMG]
    Assign Variable paths[3] with value position_meeting(x, y+64, wall) and direction != 90
    + paths[2]
    with value position_meeting(x - 64, y, wall) and direction != 0
    + paths[1]
    with value position_meeting(x, y-64, wall) and direction != 270
    + paths[0]
    with value position_meeting(x + 64, y, wall) and direction != 180
    The ! means we set each of these variables to 1 if position_meeting() is FALSE (meaning no walls blocking) and the enemy is not going the opposite way
     
    Last edited: Sep 11, 2019
    giraffeman210 likes this.
  22. giraffeman210

    giraffeman210 Member

    Joined:
    Sep 23, 2018
    Posts:
    72
  23. giraffeman210

    giraffeman210 Member

    Joined:
    Sep 23, 2018
    Posts:
    72
    Sorry for the late response! This week(or month) has been insane! I will try this out when I get a chance but I am also going out of town next week. Thanks for all of your help through all of this! Especially explaining everything has helped a lot and I feel like I have learned a lot. Sorry I have been so late with responses. I started this project and and then happened!
     
  24. giraffeman210

    giraffeman210 Member

    Joined:
    Sep 23, 2018
    Posts:
    72
    Finally got back and put this all in and the game boots up again without errors!! Yay!! The problem though is that the enemies don't move still. Any ideas?
     
  25. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,889
    Did you set speed yet?
     
  26. giraffeman210

    giraffeman210 Member

    Joined:
    Sep 23, 2018
    Posts:
    72
    Nope I hadn't but now I did and the enemies move but they ignore walls and eventually the game freezes
     
  27. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,889
    Before I say upload the project to a free file host, a couple things to check.

    First of all, it freezes because "While paths[ rand ] is equal to 0" is stuck in an endless loop because every index of paths is set to 0. This would mean either the enemy is completely enclosed by walls... or standing out in the open, depending on how the paths array was set.

    In the first post, I had used:
    [​IMG] Declare Temporary Variable paths[3] with value !position_meeting(x, y+64, wall) and direction != 90
    click the + sign 5 times to add 5 more variables
    + paths[2] with value !position_meeting(x - 64, y, wall) and direction != 0
    + paths[1]
    with value !position_meeting(x, y-64, wall) and direction != 270
    + paths[0]
    with value !position_meeting(x + 64, y, wall) and direction != 180

    If this freezes, the enemy is completely enclosed by walls.

    But in the last post, I used:
    [​IMG] Assign Variable paths[3] with value position_meeting(x, y+64, wall) and direction != 90
    + paths[2]
    with value position_meeting(x - 64, y, wall) and direction != 0
    + paths[1]
    with value position_meeting(x, y-64, wall) and direction != 270
    + paths[0]
    with value position_meeting(x + 64, y, wall) and direction != 180

    If this freezes, the enemy is out in the open.

    Notice how in the original post I had ! in front of each position_meeting(), but I didn't in the other post? That was a typo of sorts. You probably still have the rest of the old code, so you need the ! before position_meeting() in this case.

    [​IMG] Assign Variable paths[3] with value !position_meeting(x, y+64, wall) and direction != 90
    + paths[2]
    with value !position_meeting(x - 64, y, wall) and direction != 0
    + paths[1]
    with value !position_meeting(x, y-64, wall) and direction != 270
    + paths[0]
    with value !position_meeting(x + 64, y, wall) and direction != 180

    Actually, there is still one more possibility. I did use two conditions for each of those, the second condition being if direction is not a certain value. I did this to prevent back-tracking. However, if your maze has dead-ends, then you'll need to remove all of the "and direction !=" parts.

    It's also possible, but unlikely, that direction is not getting changed and it stays at 0, causing paths[2] to always be false. That's something I'd look for after exhausting the other possibilities.
     
  28. giraffeman210

    giraffeman210 Member

    Joined:
    Sep 23, 2018
    Posts:
    72
    I have no idea whats going on. I checked all of the code and put the "!" back in but as soon as the enemies spawn they move into a wall block and freeze the game. Could it be that I am putting in wall wrong? I tried it as "object_block" the name of the wall objects and as "wall" but "wall" shows an error before the game even boots up.
     
  29. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,889
    Use the name of your wall/block object.
    If you have multiples, assign one of them as the parent of all the others and reference that one.

    Copy the GML preview again so I can see what it's coming up as now.

    Inside this main block:
    [​IMG] If Expression ( ( x - 32 ) + ( y - 32) ) mod 64 is equal to 0

    ...at the end of it, put a

    Show Message string(paths[0])+" "+string(paths[1])+" "+string(paths[2])+" "+string(paths[3]))

    If the main IF block works, the message will at least pop up.

    ....I just had an idea. What are the coordinates of your enemy when he's put in the room? Maybe you don't need the -32's in the main conditional. Honestly, it could be lots of things.
     
  30. giraffeman210

    giraffeman210 Member

    Joined:
    Sep 23, 2018
    Posts:
    72
    // If Expression
    if(((x - 32) + (y -32)) mod 64 = 0)
    {
    // Set Speed
    speed = 2;
    // Declare Temp
    var PATHS = 0;
    var targetH = object_player2.x - x;
    var targetV = object_player2.y - y;
    // Assign Variable
    PATHS[3] = !position_meeting(x, y + 64, object_block) and direction !=90;
    PATHS[2] = !position_meeting(x - 64, y, object_block) and direction !=0;
    PATHS[1] = !position_meeting(x, y - 64, object_block) and direction !=270;
    PATHS[0] = !position_meeting(x + 64, y, object_block) and direction !=180;
    // If Expression
    if(abs(targetH) < abs(targetV))
    {
    // If Variable
    if(PATHS[1 - sign(targetH)] == 1)
    {
    // Assign Variable
    image_angle = 90 - 90 * sign(targetH);
    }

    // Else
    else
    {
    // If Variable
    if(PATHS[2 + sign(targetV)] == 1)
    {
    // Assign Variable
    image_angle = 180 + 90 * sign(targetV);
    }

    // Else
    else
    {
    // Declare Temp
    var rand = irandom(3);

    // While Loop
    while ((PATHS[rand] == 0)) {
    // Assign Variable
    rand = (rand + 1)mod 4;
    }

    // Assign Variable
    image_angle = rand * 90;
    }
    }
    }
    // Else
    else
    {
    // If Variable
    if(PATHS[2 + sign(targetV)] == 1)
    {
    // Assign Variable
    image_angle = 180 + 90 * sign(targetV);
    }

    // Else
    else
    {
    // If Variable
    if(PATHS[1 - sign(targetH)] == 1)
    {
    // Assign Variable
    image_angle = 90 - 90 * sign(targetH);
    }

    // Else
    else
    {
    // Declare Temp
    var rand = irandom(3);

    // While Loop
    while ((PATHS[rand] == 0)) {
    // Assign Variable
    rand = (rand + 1) mod 4;
    }

    // Assign Variable
    image_angle = rand * 90;
    }
    }
    }
    }
     
  31. giraffeman210

    giraffeman210 Member

    Joined:
    Sep 23, 2018
    Posts:
    72
    The enemies spawn in the room randomly and if they spawn over a wall or a block they respawn somewhere else. Once they spawn they snap to the grid.
     
  32. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,889
    Your code is setting image_angle, it's not setting direction that I see. You need to update the value of direction.

    Image angle just affects the direction that the Sprite is facing. direction actually affects the the direction of motion when you use the speed variable.
     

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