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

2013/9/1

Enemy Follow Player

dominicarrojado dominicarrojado

2013/9/1

#
How can I make an enemy follow a player but only up down left right? not diagonally?
Gevater_Tod4711 Gevater_Tod4711

2013/9/1

#
Therefore you need to know the position of your enemy and the position of your player. You have to get a reference to the player in your enemy object (see this greenfoot tutorial). If you have got the reference you can use this code:
public void act() {
    java.util.List<Player> playersInWorld = getWorld().getObjects(Player.class);
    if (!playersInWorld.isEmpty()) {
        Player player = playersInWorld.get(0);
        moveToPlayer(player);
    }
}

public void moveToPlayer(Player player) {
    int deltaX = getX() - player.getX();
    int deltaY = getY() - player.getY();
    if (Math.abs(deltaX) > Math.abs(deltaY)) {
        if (deltaX > 0) {
            setLocation(getX() - 1, getY());
        }
        else if (deltaX < 0) {
            setLocation(getX() + 1, getY());
        }
    }
    else {
        if (deltaY > 0) {
            setLocation(getX(), getY() - 1);
        }
        else if (deltaY < 0) {
            setLocation(getX(), getY() + 1);
        }
    }
}
danpost danpost

2013/9/1

#
With the code given by Gevator_Tod4711, your enemy will alternately move vertically and then horizontally when along one of the diagonals of the player. This will give the impression of moving diagonally, only a little slower and choppy. Another way to handle it is with the following, which will probably be more along the lines of what you want:
// instance field to hold current axis to travel along
// (initial value randomly chosen)
private boolean movingVertically = Greenfoot.getRandomNumber(2) == 0;
;
// in act method, call a method to follow the player
followPlayer();
// the method to follow the player
private void followPlayer()
{
    // do nothing if player not in world
    if (getWorld.getObjects(Player.class).isEmpty()) return;
    // get reference to Player object
    Actor actor = (Actor)getWorld().getObjects(Player.class).get(0);
    // give some randomness to follow direction by changing travel axis
    // (the '100' can be adjusted to make changes occur slower or faster)
    if (Greenfoot.getRandomNumber(100) == 0) movingVertically = Greenfoot.getRandomNumber(2) == 0;
    // change axis if no movement required along current axis
    if ((movingVertically && getY() == actor.getY()) || (!movingVertically && getX() == actor.getX())) movingVertically = !movingVertically;
    // move along current axis
    if (movingVertically) setLocation(getX(), getY()+(int)Math.signum(actor.getY()-getY()));
    else setLocation(getX()+(int)Math.signum(actor.getX()-getX()), getY());
}
dominicarrojado dominicarrojado

2013/9/1

#
Thanks that work!
dominicarrojado dominicarrojado

2013/9/1

#
Danpost in that code of yours, how can I make the enemy not pass if there's a wall?
Gevater_Tod4711 Gevater_Tod4711

2013/9/1

#
I think the easyest way for doing this would be to override the setLocation method like this:
public void setLocation(int x, int y) {
    if (getWorld().getObjectsAt(x, y, Wall.class).isEmpty()) {
        super.setLocation(x, y);
    }
}
danpost danpost

2013/9/1

#
I have not tested it; but I think the following is what you want. From line 19 above:
// determine possible movements
int dx = (int)Math.signum(actor.getX()-getX());
int dy = (int)Math.signum(actor.getY()-getY());
// do nothing if no movement
if (dx == 0 && dy == 0) return;
// check one way and if blocked check other way
int failCount = 0; // to count failures to move
while (failCount < 2)
{
    // if on axis of movement, count as failure and change axis
    if ((movingVertically && dy == 0) || (!movingVertically && dx == 0))
    {
        failCount++;
        movingVertically = !movingVertically;
    }
    // determine axial directions to check
    int x = 0, y = 0;
    if (movingVertically) y = dy; else x = dx;
    // make move along current axis
    setLocation(getX()+x, getY()+y);
    // do no more if not blocked by wall
    if (getOneIntersectingObject(Wall.class) == null) break;
    // move back, count as failure and change axis
    setLocation(getX()-x, getY()-y);
    failCount++;
    movingVertically = !movingVertically;
}
dominicarrojado dominicarrojado

2013/9/2

#
Just the way I wanted to. Nice! Thanks!
You need to login to post a reply.