javaobjectlogiccollisionpacman

Pacman Collisions in Java


I am making a pacman arcade game on Java but my collisions have problems. If you see my image here my pacman sprite stands still (no x or y movement) when visiting a corner or when trying to turn back the direction it came (ie goes left but does not go right again). I understand this is because I set my xMovement to 0 and yMovement to 0 if a collision is detected (see second code block under collide()).

How would I allow the pacman sprite to move the other way (ie it comes from the left and I want it to go right) or traverse a corner if my collision() does not allow this?

Below is my draw method in the App.java class which draws the player based on the user's input. The keys wasd correspond with up, left, down, right respectively. this.direction is only used so the player does not waste a move nor go through a wall when a collision happens. *Note, I put (this.player.x_ord + 2) % 16 == 0 because my pacman image is not a 16x16 image unlike my walls which are.

public void draw() { // This is an infinite loop
    mapDraw(); // this draws my map constantly so I do not have multiple pacman sprites drawn 
    this.player.tick(); // see second code below for details
    if (keyPressed){ // Used wasd rather than arrow keys
        if (key == 's' && this.direction != 's' && (this.player.x_ord + 2) % 16 == 0 && 
        (this.player.y_ord + 4) % 16 == 0){ // We dont want Player to turn ever on a non 16 divisible area
            this.player.p = this.loadImage("src/main/resources/playerDown.png");
            this.player.yMovement = this.player.speed;
            this.player.xMovement = 0;
            this.direction = 's';
        }
        else if (key == 'w' && this.direction != 'w' && (this.player.x_ord + 2) % 16 == 0 && 
        (this.player.y_ord + 4) % 16 == 0){
            this.player.p = this.loadImage("src/main/resources/playerUp.png");
            this.player.yMovement = -this.player.speed;
            this.player.xMovement = 0; // I do not want my pacman to move diagonally so thats why
            this.direction = 'w';

        }
        else if (key == 'd' && this.direction != 'd' && (this.player.x_ord + 2) % 16 == 0 && 
        (this.player.y_ord + 4) % 16 == 0){
            this.player.p = this.loadImage("src/main/resources/playerRight.png");
            this.player.xMovement = this.player.speed;
            this.player.yMovement = 0;
            this.direction = 'd';
        }
        else if (key == 'a' && this.direction != 'a' && (this.player.x_ord + 2) % 16 == 0 && 
        (this.player.y_ord + 4) % 16 == 0){
            this.player.p = this.loadImage("src/main/resources/playerLeft.png");
            this.player.xMovement = -this.player.speed;
            this.player.yMovement = 0;
            this.direction = 'a';
        }
    }
    this.player.draw(this); //see second code below for details
}

Below is my player.java class *Note again that this.x_ord + 2 == w.x_pos + 16 && this.y_ord + 4 == w.y_pos is offset because of my pacman sprite is larger than my 16x16 walls.

   public void tick(){
    // //logic   
    this.detectCollision();
    if (this.isLiving){
        this.y_ord += this.yMovement;
        this.x_ord += this.xMovement;
    }
}

public void draw(PApplet a){ //just draw the sprite
    if (this.isLiving){
        a.image(this.p, this.x_ord, this.y_ord);
    }
    
}

public void collide(boolean isX){ // Is it an x or y collision
    if (isX == true){ // If it moves left or right into a wall
        this.xMovement = 0;
    }
    else if (isX == false){ // If it moves up or down into a wall
        this.xMovement = 0;
    }
}

public void detectCollision(){
    for (Walls w: this.wallLocations){ // A list of wall locations from a .txt file
        if (this.x_ord + 2 == w.x_pos + 16 && this.y_ord + 4 == w.y_pos){ // Detect left movement into right wall piece
            collide(true);
        }

        if (this.x_ord + 2 + 16 == w.x_pos && this.y_ord + 4 == w.y_pos){ // Detect right movement into left wall piece
            collide(true);
        }

        if (this.y_ord + 4 == w.y_pos + 16 && this.x_ord + 2 == w.x_pos){ // Detect up movement into bottom wall piece
            collide(false);
        }

        if (this.y_ord + 4 + 16 == w.y_pos && this.x_ord + 2 == w.x_pos){ // Detect down movement into top wall piece
            collide(false);
        }
    }

Any help to my problem is much appreciated.


Solution

  • I didn't analyze your code deeply but it seems to me that your main problem is that collide method considers only 2 cases, vertical movement or horizontal movement. If you want to have movement in 4 different directions that method need to have 4 different states.

    To achieve that you could create an enum representing direction. Then in detectCollision pass appropriate Direction into collide. Finally, in the collide consider 4 different directions. For example, if there is barrier on the right, xMovement need to be non-positive. The collide method could look like so:

    public void collide(Direction direction){ 
        if (direction == Direction.RIGHT){ 
            this.xMovement = Math.min(0, this.xMovement);
        }
        if (direction == Direction.LEFT){ 
            this.xMovement = Math.max(0, this.xMovement);
        }
        if (direction == Direction.UP){ 
            this.yMovement = Math.min(0, this.yMovement);
        }
        if (direction == Direction.DOWN){ 
            this.yMovement = Math.max(0, this.yMovement);
        }
    }