0

I'm developing a game in Java and i'm having issues using and implementing my A* path finding algorithm. Currently, i have entities set up so that an entity can't exist outside of a level(each entity has access to the current level). for this reason, i stored the algorithm method 'findPath' in the base Level class. Below is the algorithm code, and the movement code for the entity, which as you can see calls the find path method in level. My issue is that when I run the code, I move the player towards the entity and the entity does nothing. I've put in some debug print lines (i'll leave those in so you can see), and the list path that is returned constantly returns just []. I've been through everything and can;'t figure it out. Hope someone can help!

Thanks

code: in Level.java class:

private Comparator<Node> nodeSorter = new Comparator<Node>() {
    public int compare(Node n0, Node n1) {
        if (n1.fCost < n0.fCost) return +1;
        if (n1.fCost > n0.fCost) return -1;
        return 0;
    }
};

public List<Node> findPath(Vector2i start, Vector2i goal) {
    List<Node> openList = new ArrayList<Node>();
    List<Node> closedList = new ArrayList<Node>();
    Node current = new Node(start, null, 0, getDistance(start, goal));
    openList.add(current);
    while (openList.size() > 0) {
        Collections.sort(openList, nodeSorter);
        current = openList.get(0);
        if (current.tile.equals(goal)) {
            List<Node> path = new ArrayList<Node>();
            while (current.parent != null) {
                path.add(current);
                current = current.parent;
            }
            openList.clear();
            closedList.clear();
            return path;
        }
        openList.remove(current);
        closedList.add(current);
        for (int i = 0; i < 9; i ++){
            if (i == 4) continue;
            int x = current.tile.getX();
            int y = current.tile.getY();
            int xi = (i % 3) - 1;
            int yi = (i / 3) - 1;
            Tile at = getTile(x + xi, y + yi);
            if (at == null) continue;
            if (at.solid()) continue;
            Vector2i a = new Vector2i(x + xi, y + yi);
            double gCost = current.gCost + getDistance(current.tile, a);
            double hCost = getDistance(a, goal);
            Node node = new Node(a, current, gCost, hCost);
            if (vecInList(closedList, a) && gCost >= node.gCost) continue;
            if (!vecInList(openList, a) || gCost < node.gCost) openList.add(node);

        }
    }
    closedList.clear();
    return null;
}

And in my "Wizard.java", which extends Mob, and in turn entity:

private List<Node> path = null;

public Wizard(int x, int y) {
    this.x = x << 4;
    this.y = y << 4;
    sprite = animSprite.getSprite();
}

private void move() {
    xa = 0;
    ya = 0;
    int px = (int)level.getPlayerAt(0).getX();
    int py = (int)level.getPlayerAt(0).getY();
    Vector2i start = new Vector2i((int)getX() >> 4, (int)getY() >> 4);
    Vector2i destination = new Vector2i(px >> 4, py >> 4);
    if (time % 60 == 0) path = level.findPath(start, destination);
    if (path != null){
        if (path.size() > 0){
            Vector2i vec = path.get(path.size() -1).tile;
            if (x < vec.getX() << 4) xa += speed;
            if (x > vec.getX() << 4) xa -= speed;
            if (y < vec.getY() << 4) ya += speed;
            if (y > vec.getY() << 4) ya -= speed;

        }
    }
    if (xa != 0 || ya != 0) {
        move(xa, ya);
        walking = true;
    } else
        walking = false;
}

public void update() {
    time++;
    if (!collision(xa, ya)){
        move();
    }
    move();
    if (walking) animSprite.update();
    else
        animSprite.setFrameRate(0);
    if (ya < 0) {
        animSprite = up;
        dir = Direction.UP;
    } else if (ya > 0) {
        animSprite = down;
        dir = Direction.DOWN;
    }
    if (xa < 0) {
        animSprite = left;
        dir = Direction.LEFT;
    } else if (xa > 0) {
        animSprite = right;
        dir = Direction.RIGHT;
    }
}

public void render(Screen screen) {
    sprite = animSprite.getSprite();
    if (level.getTile((int)x, (int)y).solid()){
        x += 16;
        y += 16;
    }
    screen.renderMob((int)(x - 16), (int)(y - 16), this);
}

Node equals code:

public boolean equals(Object object){
    if(!(object instanceof Vector2i)) return false;
    Vector2i vec = (Vector2i) object;
    if (vec.getX() == this.getX() && vec.getY() == this.getY()) return true;
    else return false;
}
Kris Rice
  • 559
  • 1
  • 5
  • 23
  • 1
    It is difficult to understand what is the problem given your variable names are bad, and you should isolate the problem and post only relevant code. – We are Borg Sep 17 '15 at 09:05
  • try stepping through in a debugger... – Mitch Wheat Sep 17 '15 at 09:06
  • @MitchWheat I'm afraid i can't. I'm using codenvy IDE and can't debug. I did try it on eclipse before leaving my house, and everything seemed okay, but obviously it isn't. – Kris Rice Sep 17 '15 at 09:12
  • One can always debug, if not with IDE then by directly using JDB on console/terminal/command-line – We are Borg Sep 17 '15 at 09:17
  • @WeareBorg have you ever used codenvy? it builds a .jar for you to download. It doesn't allow for debugging when compiling, unless i added a console output frame into my project. Which for the purpose of the project is useless, as i mostly use eclipse, however im not able to access eclipse right now – Kris Rice Sep 17 '15 at 09:21
  • Two things: 1) If you use a TreeSet instead of a List, then you don't have to manually sort it, and it will also prevent duplicates. 2) Are you super super super sure that you have correctly implemented BOTH equals and hashcode methods in your Node class(No, the comparator alone is not enough)? 90% of the times that's the issue when dealing with collections and pathfinding, as it messes up the add/remove. – Diego Martinoia Sep 17 '15 at 09:27
  • @DiegoMartinoia Positive i've implemented equals correctly. What is HashCode method you mentioned? – Kris Rice Sep 17 '15 at 09:30
  • You can't implement only equals in Java. That's an error. Every time you implement equals you need to implement also hashcode(). That's an Object method that returns an int (quickly) and is used by most collections as an optimization. The rule is if equals(a, b) -> hash(a) = hash(b) but not necessarily the opposite. So if two hashcodes are different the items are different and can be added/return contains, etc. See for example http://stackoverflow.com/questions/27581/what-issues-should-be-considered-when-overriding-equals-and-hashcode-in-java – Diego Martinoia Sep 17 '15 at 09:32
  • By default I think hashcode returns the memory ID of the instance, i.e. all items are different, even if equals returns true! – Diego Martinoia Sep 17 '15 at 09:33
  • @DiegoMartinoia okay i kind of understand. So my question would be how would i implement this? – Kris Rice Sep 17 '15 at 09:35
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/89895/discussion-between-admin-hydra-and-diego-martinoia). – Kris Rice Sep 17 '15 at 09:38

0 Answers0