This site requires JavaScript, please enable it in your browser!
Greenfoot back
johnLearnsToCode
johnLearnsToCode wrote ...

2021/3/9

How do I make an actor navigate around obstacles?

johnLearnsToCode johnLearnsToCode

2021/3/9

#
I'm working on a project where Zombies chase the player. There is a building in the world. I'm trying to get the zombies to navigate around the building, but as soon as a zombie touches a building it stops moving entirely. I'm not sure
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

public class Zombie extends Actor
{
    private GreenfootImage zombieleft;
    private GreenfootImage zombieright;
    
    public Zombie()
    {
        System.out.println("Zombie created.");
        zombieleft = new GreenfootImage("image_zombie_left.png");
        zombieright = new GreenfootImage("image_zombie_right.png");
    }
    
    public void act() 
    {
        if (getOneIntersectingObject(Building.class) == null)
        {
            chasePlayer();
        }
        else
        {
            pathing();
        }
    }
    
    public void chasePlayer()
    {
        Player player = (Player)getWorld().getObjects(Player.class).get(0);
        
        int pX = player.getX();
        int pY = player.getY();
        
        int dx = 1;
        int dy = 1;
        
        if (getX() > pX)
        {
            dx = -1;
            setImage(zombieleft);
        }
        else
        {
            setImage(zombieright);
        }
        
        if (getY() > pY)
        {
            dy = -1;
        }

        setLocation(getX() + dx, getY() + dy);
    }
    
    public void pathing()
    {
        Player player = (Player)getWorld().getObjects(Player.class).get(0);
        Building building = (Building)getWorld().getObjects(Building.class).get(0);
        
        
        int pX = player.getX();
        int pY = player.getY();
        
        int bX = building.getX();
        int bY = building.getY();
        
        int deltaX = player.getX() - getX();
        int deltaY = player.getY() - getY();
        
        // if player is to the right or left of the zombie, the zombie will only move up or down to clear the building
        if ((getX() + 1 == bX) || (getX() - 1 == bX))
            {
                if (deltaY < 0)
                {
                    setLocation(getX(), getY() - 1);
                }
                else
                {
                    setLocation(getX(), getY() + 1);
                }
            }
        
        // if player is above or below the zombie, the zombie will only move left or right to clear the building
        if ((getY() + 1 == bY) || (getY() + 1 == bY))
           {
               if (deltaX < 0)
                {
                    setLocation(getX() + 1, getY());
                }
                else
                {
                    setLocation(getX() - 1, getY());
                }
           }
    }
}

danpost danpost

2021/3/9

#
johnLearnsToCode wrote...
I'm working on a project where Zombies chase the player. There is a building in the world. I'm trying to get the zombies to navigate around the building, but as soon as a zombie touches a building it stops moving entirely.
How do you want the zombie to react? Should it mirror the player if on other side or just choose a direction to go around (and what determines choice)?
johnLearnsToCode johnLearnsToCode

2021/3/9

#
Hey Danpost, thanks so much for looking at this! The intent with my code is for the zombie to take the shortest route to the player. This is determined using the deltaX and deltaY values. My understanding of coords in Java is that (0,0) is the top left of the screen. So, for example if the player is higher up than the zombie, deltaY will be a negative number. Since that would satisfy the “deltaY < 0” condition, the zombie would move straight up. Unfortunately, this doesn’t happen - the zombie stays stuck in place. I’m wondering it it’s because I have two independent if statements that lead to conflicting instructions for the actor. If I was to create an if else statement that chose the larger of the two deltas, then nested the existing code, would that work better? E.g. If (deltaX > detaY) { getX code block } Else { getY code block }
danpost danpost

2021/3/9

#
johnLearnsToCode wrote...
If I was to create an if else statement that chose the larger of the two deltas, then nested the existing code, would that work better?
If you do horizontal and vertical movement separately, maybe (collision checking after each). If delta value with player is zero, then use negative house coordinate delta to circumvent house.
johnLearnsToCode johnLearnsToCode

2021/3/9

#
danpost wrote...
If you do horizontal and vertical movement separately, maybe
Is there a better way to approach this problem? I’m not married to this approach, I just don’t know if there is a better way to handle it.
danpost danpost

2021/3/10

#
johnLearnsToCode wrote...
danpost wrote...
If you do horizontal and vertical movement separately
Is there a better way to approach this problem?
Not really. It is the best way to allow movement along the walls of the house. If not done separately, you would need to test each way anyway after a collision to see which axis of movement caused the collision. There is no guess work if you do them separately to begin with.
You need to login to post a reply.