Pathfinding javascript with obstacles

Viewed 189

I'm working on a custom Pacman game using Javascript canvas. I have different classes, one for the player, another one for the enemies and another one for the walls in the board. Inside my wall class I have the following code:

class Wall {
constructor(x, y, width, height, color, gate){
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
    this.color = color;
    this.gate = gate;
};
draw(){
    ctx.lineWidth = 3;
    ctx.strokeStyle = this.color;
    ctx.strokeRect(this.x, this.y, this.width, this.height);
};

Inside my enemy class I have the following code:

class Enemy {
constructor(img, x, y){
    this.img = img;
    this.x = x;
    this.y = y;
    this.width = 36;
    this.height = 36;
    this.speedX = 0.5;
    this.speedY = 0.5;
    this.dx = 0;
    this.dy = 0;
    this.distance = 0;
    this.angle = 0;
};
draw(){
    ctx.drawImage(this.img, this.x, this.y, this.width, this.height);
};
checkcollision(object) {
    return (
      this.x < object.x + object.width &&
      this.x + this.width > object.x &&
      this.y < object.y + object.height &&
      this.y + this.height > object.y
    );
};
moveRight(objects) {
    this.x += this.speedX;
    objects.forEach(object => {
        if (this.checkcollision(object)) {
            this.x -= this.speedX;
        } else if (this.x >= 976){
            this.x = 0;
        };
    });
  };
moveLeft(objects) {
    this.x -= this.speedX;
    objects.forEach(object => {
        if (this.checkcollision(object)) {
            this.x += this.speedX;
        } else if (this.x <= 0){
            this.x = 975;
        };
    });
};
moveUp(objects) {
    this.y -= this.speedY;
    objects.forEach(object => {
        if (this.checkcollision(object)) {
            this.y += this.speedY;
        };
    });
};
moveDown(objects) {
    this.y += this.speedY;
    objects.forEach(object => {
        if (this.checkcollision(object)) {
            this.y -= this.speedY;
        };
    });
};
updateAngleX(player, objects){
    this.dx = player.x - this.x;
    this.dy = player.y - this.y;
    this.distance = Math.sqrt((this.dx*this.dx) + (this.dy*this.dy));
    this.angle = Math.atan2(this.dy,this.dx);
    this.x += Math.cos(this.angle) * this.speedX;
    objects.forEach(object => {
        if (this.dead === false || object.gate === false){
            if (this.checkcollision(object)) {
                if (this.dy > 0){
                    this.y += this.speedY;
                    this.x -= Math.cos(this.angle) * this.speedX;
                    if (this.checkcollision(object)){
                        this.y -= this.speedY;
                    };
                } else if (this.dy < 0){
                    this.y -= this.speedY;
                    this.x -= Math.cos(this.angle) * this.speedX;
                    if (this.checkcollision(object)){
                        this.y += this.speedY;
                    };
                };
            };
        };
    });
};
updateAngleY(player, objects){
    this.dx = player.x - this.x;
    this.dy = player.y - this.y;
    this.distance = Math.sqrt((this.dx*this.dx) + (this.dy*this.dy));
    this.angle = Math.atan2(this.dy,this.dx);
    this.y += Math.sin(this.angle) * this.speedY;
    objects.forEach(object => {
        if (this.dead === false || object.gate === false){
            if (this.checkcollision(object)) {
                if (this.dx > 0){
                    this.x += this.speedX;
                    this.y -= Math.sin(this.angle) * this.speedY;
                    if (this.checkcollision(object)){
                        this.x -= this.speedX;
                    };
                } else if (this.dx < 0){
                    this.x -= this.speedX;
                    this.y -= Math.sin(this.angle) * this.speedY;
                    if (this.checkcollision(object)){
                        this.x += this.speedX;
                    };
                };
            };
        };
    });
};

};

But I have some problems because the enemies are stuck when they find a corner like in the following image:

enter image description here

Like the enemy should follow the top or right path to continue the persecution but it gets stuck in the corner. How can I change my functions so they find the correct path to the player? Thank you.

Added the whole code to codepen to check it here: https://codepen.io/SpaSniper/pen/bGooKrP

1 Answers

Stop what you're currently doing. Keep it super simple. You know where you can go and you know how big you are.

Let's say your enemy character is 36x36. A nice square. Now flood the map (the parts that you can actually go) with squares 36x36 or 40x40. You end up having a lot of squares one beside the other all over the map.

Now you can run something like Dijkstra to find the path between the enemy and the player (actually between the closest square to the enemy and the closest square to the player). You get back a list of squares (their centres actually) so you minimise the distance between the enemy and the next closest square in the list.

Do not run this every frame, just every 2 or 3 seconds or so.

Dijkstra on such a small amount of positions will be blazing fast but it is not necessary to keep on running it otherwise you risk your enemy to jitter too much.

This is not the only or the best solution, but you'll learn some nice techniques.

Related