I want to make an slick2d java game and encountered an problem I could not solve in the last couple of hours. I've looked into many other posts but non of that fits my problem.
The collission detection works fine in 9/10 cases. Everytime it intersects with another rectangle it moves back according to the code below and shown in picture1. But sometimes if I get as near as possble to the edge the edges seem to overlap shown here picture2. If I go up he detects the intersection and moves down. If I go down everything is fine. If I go left or right nothing happens. This only happens if the corners of the rectangles intersects. If I go up and left or right at the same time he goes in the wrong direction sometimes. It seems that if I go up and sideways at the same time he detects the collision and moves in the opposite direction until he reaches a point where he intersects with the corners and stops again. The point is after detecting and collision he never moves more back then he he has moves foreward before. Further shouldn't he detect the intersection of the rectangles AND move back again but why doesn't he detect the intersection at the edge as shown in picture2? I really hope someone has some ideas why this is happening. This problem occures on every side. Here is the code.
public class Player extends Creature {
int posX = 0;
int posY = 0;
Rectangle hitbox;
Input input;
public Player(Handler handler) {
super(handler);
// TODO Auto-generated constructor stub
}
@Override
public void init() {
hitbox = new Rectangle(posX + 320, posY + 240, 32, 32);
}
@Override
public void render(Graphics g) {
g.setColor(Color.red);
g.draw(hitbox);
g.setColor(Color.cyan);
for (int i = 0; i < handler.getWorldCollision().size(); i++) {
g.draw(handler.getWorldCollision().get(i));
}
}
@Override
public void update(GameContainer gc, int delta) {
input = gc.getInput();
if (input.isKeyDown(Input.KEY_W)) {
// move
posY -= 100 * delta / 1000f;
// if collision move back
for (int i = 0; i < handler.getWorldCollision().size(); i++) {
if (hitbox.intersects(handler.getWorldCollision().get(i))) {
posY += 100 * delta / 1000f;
break;
}
}
hitbox.setY(posY + 240);
}
if (input.isKeyDown(Input.KEY_S)) {
// move
posY += 100 * delta / 1000f;
// if collision move back
for (int i = 0; i < handler.getWorldCollision().size(); i++) {
if (hitbox.intersects(handler.getWorldCollision().get(i))) {
posY -= 100 * delta / 1000f;
break;
}
}
hitbox.setY(posY + 240);
}
if (input.isKeyDown(Input.KEY_A)) {
// move
posX -= 100 * delta / 1000f;
// if collision move back
for (int i = 0; i < handler.getWorldCollision().size(); i++) {
if (hitbox.intersects(handler.getWorldCollision().get(i))) {
posX += 100 * delta / 1000f;
break;
}
}
hitbox.setX(posX + 320);
}
if (input.isKeyDown(Input.KEY_D)) {
// move
posX += 100 * delta / 1000f;
// if collision move back
for (int i = 0; i < handler.getWorldCollision().size(); i++) {
if (hitbox.intersects(handler.getWorldCollision().get(i))) {
posX -= 100 * delta / 1000f;
break;
}
}
hitbox.setX(posX + 320);
}
handler.setPlayerX(posX);
handler.setPlayerY(posY);
}
}
handler.getWorldCollision() is an array containing all the rectangles as drawn in cyan in the pictures.
public class TestWorld extends World {
int[][] map = new int[87][35];
ArrayList<Rectangle> worldCollision;
MapLoader maploader;
public TestWorld(Handler handler) {
super(handler);
}
@Override
public void init() throws IOException {
maploader = new MapLoader(handler);
map = maploader.readMapFile("gameResources/map/testmap.map");
worldCollision = new ArrayList<Rectangle>();
}
@Override
public void render(Graphics g) throws SlickException {
// Render all Tiles given by the map of this world.
for (int i = 0; i < 87; i++) {
for (int j = 0; j < 35; j++) {
g.drawImage(handler.getTileList()[map[j][i]].getImage(), i * 16 - handler.getPlayerX(), j * 16 - handler.getPlayerY());
}
}
}
@Override
public void update(GameContainer gc, int delta) {
worldCollision.clear();
for (int i = 0; i < 87; i++) {
for (int j = 0; j < 35; j++) {
if(handler.getTileList()[map[j][i]].hasCollision()){
worldCollision.add(new Rectangle(i * 16 - handler.getPlayerX(), j * 16 - handler.getPlayerY(), 16, 16));
}
}
}
handler.setWorldCollision(worldCollision);
}
}
Thank you for advices!
I'm not sure I totally got why this overlapping occurs. You say " if I get as near as possble to the edge the edges seem to overlap", so overlapping occurs when going UP, but then is not corrected when moving towards left or right?
By the way, if it's not detected when moving left or right, it's because you are checking the Y colisions only when going up or down; although this should be sufficient, this is a reason why this isn't corrected/detected when going left and right and already overlaping the edge!