GameMaker [Solved] Enemy swoop down behaviour

basementApe

Member
I need some help figuring this out. I have this ghost that I want to patrol in a circle until it spots you, then swoop down at you and circle around to make another swoop after either hitting or missing.

I have some code up and running already as you can see in this gif. The first pass works correctly more or less, the second pass not so much.



It only works right when the ghost comes in from a slight angle. There's some other weird behaviour going on as well. I think I might need to use a different approach altogether.


This is the behaviour I'm trying to make:


The ghost patrols back and forth in an oval circle while weaving up and down slightly.



When it spots you it'll start to descend (or ascend depending on its position relative to you) and home in on your position until it's almost within range.



When it's almost within range it'll stop homing in on you and just keep going. If you stand still you'll get hit, but if you jump or crouch you'll be able
to avoid it just in time.



After hitting or missing it'll decelerate and circle around for another swoop moving in a figure-eight sort of pattern.


I have a feeling it might be easy to achieve this with the right equations. I'm not much good with math though. Anyone able to help me out with this?

Here's the code I got so far:

GML:
with(obj_chr) { with(other)
{
    if other.type == c.type_PLAYER
    {
        if other.x > x - 120 and other.x < x + 120 and other.y > y - 190 and other.y < y + 140
        {
            if currentAnim != anim_Transform and currentAnim != anim_Float_Aggro and currentAnim != anim_Turn
            {
                // do we need to turn? check that first
                if (other.x < x and facing == 1) or (other.x > x and facing == -1)
                { facing = -facing; currentAnim = anim_Turn; frame = 0; }
                else
                // otherwise become aggro
                { currentAnim = anim_Transform; frame = 0; }
            }
            aggro = true;
            accel = 0.2;
            maxSpeed = 3;
            destY = 14;
        }
        else
        {
            if currentAnim != anim_Transform and currentAnim != anim_Float and currentAnim != anim_Turn
            { currentAnim = anim_Transform; frame = 3; }
        }

        player = other;
    }
} }



if aggro == false
{
    // roam back and forth
    // set initial destination if 0
    if destX == 0
    { destX = x + (var_destX*facing); destY = y; speedX = var_speedX; accel = 1; maxSpeed = 0.25; }


    if (facing == 1 and x < destX - speedX) or (facing == -1 and x > destX + speedX)
    {
        if (facing == 1 and x < destX - 30) or (facing == -1 and x > destX + 30)
        {
            if speedX < maxSpeed
            { speedX += ((0.001*accel)*ts)*dt; }
            else
            { speedX = maxSpeed; }
        }
        else
        {
            if speedX > 0.01
            { speedX -= ((0.001025*accel)*ts)*dt; }
        }
    }
    else
    {
        x = destX;
        facing = -facing;
        if currentAnim != anim_Turn { currentAnim = anim_Turn; frame = 0; }
        { destX = x + (82*facing); destY = y; speedX = 0; accel = 1; maxSpeed = 0.25; }      
    }

    if speedY > ((0.1*accel)*ts)*dt
    { speedY -= ((0.1*accel)*ts)*dt; }
    else if speedY < -(((0.1*accel)*ts)*dt)
    { speedY += ((0.1*accel)*ts)*dt; }
    else
    { speedY = 0; }

    if (facing == 1 and x < destX - ((speedX*ts)*dt)) or (facing == -1 and x > destX + ((speedX*ts)*dt))
    { x += ((speedX*ts)*dt)*facing; }
}

else
{
    if postSweep == false
    {
        if speedX < maxSpeed
        { speedX += ((0.1*accel)*ts)*dt; }
        else
        { speedX = maxSpeed; }

        if speedY > ((0.1*accel)*ts)*dt
        { speedY -= ((0.1*accel)*ts)*dt; }
        else if speedY < -(((0.1*accel)*ts)*dt)
        { speedY += ((0.1*accel)*ts)*dt; }
        else
        { speedY = 0; }


        if distance_to_point(player.x, player.y-28+destY) > speedX//(speedX*ts)*dt
        {
            if speedY != 0 then y += speedY;
            { move_towards_point(player.x, player.y-28+destY, (speedX*ts)*dt); }
           
            // put current x/y into lastX/Y so we can use them to calculate movement speed after our wraith
            // has reached its destination and needs to swoop back up
            lastX = x;
            lastY = y;
        }
        else
        { speed = 0; postSweep = true; speedX = abs(lastX - x); if lastY < y { speedY = abs(lastY - y); } else { speedY = -abs(lastY - y); } if speedX > maxSpeed { speedX = maxSpeed; } if speedY > maxSpeed { speedY = maxSpeed; } if speedY < -maxSpeed { speedY = -maxSpeed; } x += ((speedX*ts)*dt)*facing; y += ((speedY*ts)*dt); }
    }
    // we successfully attacked the player or the player managed to dodge us. Now what?
    else
    {
//        if speedX > 0 or speedY > -1.5
        if speedY > -1.5
        {
            if speedX > 0
            {
                if postSweepTurn == false
                { speedX -= ((0.2*accel)*ts)*dt; x += ((speedX*ts)*dt)*facing; }
                else
                {
                    if speedX + ((0.2*accel)*ts)*dt < maxSpeed
                    { speedX += ((0.2*accel)*ts)*dt; x += ((speedX*ts)*dt)*facing; }
                }
            }
            else
            { speedX = 0; }

            if speedY > -1.5
            {
                if speedX <= 0
                { speedY = -1.5; }
                else
                { speedY -= ((0.1*accel)*ts)*dt; y += (speedY*ts)*dt; }
            }
            else
            { speedY = -1.5; }


            // turn around if speedX <= 0
            if ((player.x < x and facing == 1) or (player.x > x and facing == -1)) and speedX <= 0 and postSweepTurn == false
            { facing = -facing; currentAnim = anim_Turn; frame = 0; postSweepTurn = true; speedX = 0.001; }
        }
        else
        {
            // turn around if speedX <= 0
            if ((player.x < x and facing == 1) or (player.x > x and facing == -1)) and speedX <= 0 and postSweepTurn == false
            { facing = -facing; currentAnim = anim_Turn; frame = 0; postSweepTurn = true; }

            if speedX > 0
            { speedX -= ((0.2*accel)*ts)*dt; x += ((speedX*ts)*dt)*facing; }
            else
            { speedX = 0; }

            if speedY > -1.5
            { speedY -= ((0.1*accel)*ts)*dt; y += (speedY*ts)*dt; }
            else
            { postSweep = false; postSweepTurn = false; speedX = (speedX + abs(speedY))/2; move_towards_point(player.x, player.y-28+destY, (speedX*ts)*dt); }
        }
    }
}

//////// animate ///////////////
 
Last edited:
Top