Search code examples
javagame-engineslick2d

Stop player getting stuck in certain coordinates?


Right, I have been learning Slick2D for the past couple of days and want to know why and how to fix my player getting stuck in the collision coordinates if statement.

This is my code for the main Play state, the first couple of lines of the Update void are the if conditions to see if the character (middle of window) is inside to coords...if player is then move em back basically.

package com.ohdanbo.game;

import org.newdawn.slick.*;
import org.newdawn.slick.geom.Rectangle;
import org.newdawn.slick.geom.Shape;
import org.newdawn.slick.state.*;

public class Play extends BasicGameState {

    Animation dude, movingUp, movingDown, movingLeft, movingRight;
    Image map;
    boolean quit = false;
    int[] duration = { 200, 200 };
    float dudePositionX = 0;
    float dudePositionY = 0;
    float shiftX = (640 / 2) - (40 / 2);
    float shiftY = (360 / 2) - (40 / 2);
    Image pauseBG;
    Shape rectangle;
    float rectX = 0;
    float rectY = 0;

    public Play(int state) {
    }

    public void init(GameContainer gc, StateBasedGame sbg) throws SlickException {
        //rectangle = new Rectangle(100,100);
        pauseBG = new Image("res/bg.png");
        map = new Image("res/worldTemp.png");
        Image[] walkUp = { new Image("res/charBack.png"), new Image("res/charBack.png") };
        Image[] walkDown = { new Image("res/charFront.png"), new Image("res/charFront.png") };
        Image[] walkLeft = { new Image("res/charLeft.png"), new Image("res/charLeft.png") };
        Image[] walkRight = { new Image("res/charRight.png"), new Image("res/charRight.png") };

        movingUp = new Animation(walkUp, duration, false);
        movingDown = new Animation(walkDown, duration, false);
        movingLeft = new Animation(walkLeft, duration, false);
        movingRight = new Animation(walkRight, duration, false);
        dude = movingDown;
    }

    public void render(GameContainer gc, StateBasedGame sbg, Graphics g) throws SlickException {
        map.draw(dudePositionX, dudePositionY);
        dude.draw(shiftX, shiftY);
        //g.draw(rectangle);
        // g.setColor(Color.black);
        g.drawString("Dude's X: " + dudePositionX + "\nDude's Y: " + dudePositionY, 400, 20);

        if (quit == true) {
            pauseBG.draw(0, 0);
            g.drawString("Continue (C)", 250, 100);
            g.drawString("Main Menu (M)", 250, 150);
            g.drawString("Quit (Q)", 250, 200);
            if (quit == false) {
                g.clear();
            }
        }
    }

    public void update(GameContainer gc, StateBasedGame sbg, int delta) throws SlickException {
        Input input = gc.getInput();

        if ((dudePositionX > 100) && (dudePositionX < 267) && (dudePositionY > -68) && (dudePositionY < 156)) {
            if(input.isKeyDown(Input.KEY_UP)){dudePositionY -= delta * .1f;}
            if(input.isKeyDown(Input.KEY_DOWN)){dudePositionY += delta * .1f;}
            if(input.isKeyDown(Input.KEY_LEFT)){dudePositionX -= delta * .1f;}
            if(input.isKeyDown(Input.KEY_RIGHT)){dudePositionX += delta * .1f;}
        }

        if (input.isKeyDown(Input.KEY_UP)) {
            dude = movingUp;
            dudePositionY += delta * .1f; // increase the Y coordinates of bucky
                                            // (move him up)
            if (dudePositionY > 162) {
                dudePositionY -= delta * .1f; // dont let him keep going up if
                                                // he reaches the top
            }
        }
        if (input.isKeyDown(Input.KEY_DOWN)) {
            dude = movingDown;
            dudePositionY -= delta * .1f;
            if (dudePositionY < -600) {
                dudePositionY += delta * .1f;
            }
        }
        if (input.isKeyDown(Input.KEY_LEFT)) {
            dude = movingLeft;
            dudePositionX += delta * .1f;
            if (dudePositionX > 324) {
                dudePositionX -= delta * .1f;
            }
        }
        if (input.isKeyDown(Input.KEY_RIGHT)) {
            dude = movingRight;
            dudePositionX -= delta * .1f;
            if (dudePositionX < -840) {
                dudePositionX += delta * .1f;
            }
        }

        if (input.isKeyDown(Input.KEY_ESCAPE)) {
            quit = true;
        }

        if (quit == true) {
            if (input.isKeyDown(Input.KEY_C)) {
                quit = false;
            }
            if (input.isKeyDown(Input.KEY_M)) {
                sbg.enterState(0);
                quit = false;
            }
            if (input.isKeyDown(Input.KEY_Q)) {
                System.exit(0);
            }
        }
    }

    public int getID() {
        return 1;
    }

}

Solution

  • How you want to approach collision detection/collision response problems like this is to understand how collisions should typically play out in game loops.

    Basically, it's all based on order of operation to get the right outcome:

    • Take the characters initial position into account, and save it.
    • Poll the controller input from the player, and update the player coordinates.
    • If the player is "out of bounds" or colliding with anything you don't want it to, return it to the previous position (e.g. the initial position you saved in step 1)

    Try an approach like that, rather than integrating into your controller code directly as I point out in a snippet of your code below:

        if (input.isKeyDown(Input.KEY_RIGHT)) {
            dude = movingRight;
            dudePositionX -= delta * .1f;
    
            // Do these lines LATER after all the 
            //   controls of movement have been seen and the player updated
            if (dudePositionX < -840) { 
                dudePositionX += delta * .1f;
                // Instead of this line, you would have it be something like:
                // dudePositionX = previousDudePositionX;
            }
        }