Java 2d Collision with rectangles

Started by
1 comment, last by !Null 11 years, 8 months ago
So ive been working on getting working collision with simple rectangle.intersects() stuff and i can get 1 rectangle to intersect but if i place more than 1 of my entities the first entity loses the collision compatablity and my player can only collide with the 2nd entity i have placed i was wondering if i could get a review of my code and maybe some help with this.

Here is my Main class featuring the collision detection in the update method

package RPG;
import java.util.ArrayList;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.state.StateBasedGame;
public class Play extends BasicGameState {
Devmode Devmode;
Player player;
public ArrayList<Entity> entites;
public boolean terrainCollision = false;

public Play(int state) {

}

@Override
public void init(GameContainer gc, StateBasedGame game) throws SlickException {
Devmode = new Devmode();

entites = new ArrayList<Entity>();
Entity e1 = new Entity("e1", 32, 32);
entites.add(e1);
Entity e2 = new Entity("e2", 64, 64);
entites.add(e2);

player = new Player(600, 400);
}
@Override
public void render(GameContainer gc, StateBasedGame game, Graphics g) throws SlickException {
Devmode.render(gc, game, g);
player.render(gc, game, g);

for (Entity entity : entites) {
entity.render(gc, game, g);
}

if (terrainCollision) {
g.drawString("asdasd", 200, 200);
}
}
@Override
public void update(GameContainer gc, StateBasedGame game, int delta) throws SlickException {
Input input = gc.getInput();

Devmode.update(gc, game, delta);

player.update(gc, game, delta);

for (Entity entity : entites) {
entity.update(gc, game, delta);
}

for (Entity entity : entites) {
if (player.HitBox.intersects(entity.HitBox)) {
terrainCollision = true;
}

if (!player.HitBox.intersects(entity.HitBox)) {
terrainCollision = false;
}
}

}
@Override
public int getID() {
return 1;
}
}


my player class

package RPG;
import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.Input;
import org.newdawn.slick.geom.Rectangle;
import org.newdawn.slick.state.StateBasedGame;
public class Player {
public float x, y;
public Rectangle HitBox;
public Entity entity;

public Player(float posx, float posy) {
this.x = posx;
this.y = posy;
HitBox = new Rectangle(posx, posy, 32, 32);
}

public void render(GameContainer gc, StateBasedGame game, Graphics g) {
g.drawString("Player", x, y - 18);
g.setColor(Color.yellow);
g.drawRect(x, y, 32, 32);
g.setColor(Color.white);
}

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

HitBox = new Rectangle(x, y, 32, 32);

if (input.isKeyDown(Input.KEY_A)) {
x -= 0.3f * delta;
}

if (input.isKeyDown(Input.KEY_W)) {
y -= 0.3f * delta;
}

if (input.isKeyDown(Input.KEY_S)) {
y += 0.3f * delta;
}

if (input.isKeyDown(Input.KEY_D)) {
x += 0.3f * delta;
}
}
}


and the entity class

package RPG;
import java.util.ArrayList;
import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.geom.Rectangle;
import org.newdawn.slick.state.StateBasedGame;
public class Entity {
public float x, y;
public Image image;
public String name;
public Rectangle HitBox;

public Entity(String n, float posx, float posy) {
this.x = posx;
this.y = posy;
this.name = n;
HitBox = new Rectangle(x, y, 32, 32);
}

public void render(GameContainer gc, StateBasedGame game, Graphics g) {
g.drawString(name, x, y - 18);
g.setColor(Color.red);
g.drawRect(x, y, 32, 32);
g.setColor(Color.white);

}

public void update(GameContainer gc, StateBasedGame game, int delta) {

}
}

thanks for any help and replies you may have =D
Advertisement
The problem is in the loop where you check for collision.

If you put a breakpoint on the first line inside that loop, you can step through and see exactly what's going on there.

An example scenario is if you have your player standing on the first entity of the list:
-- first iteration --
if (player intersects with entity[0]) is true, so set terrain collision to true
if (player DOES NOT intersect with entity[0]) is false
-- second iteration --
if (player intersects with entity[1]) is false
if (player DOES NOT intersect with entity[1]) is true, so set terrain collision to false

So the way your code currently checks for collision, it's really just telling you if the last entity added is colliding with the player.

I'm not sure what you're going to do with that collision information, so I can't recommend a good way to solve your problem.

If this is the kind of game where colliding with any terrain means you die, a solution could be to add a break; statement inside the intersection code block. That way if somebody collides with any of the entities, it will set terrainCollision to true and then break out of the for each loop. So you could check that variable later and see if the player should die.

If you need more information like which entity it is colliding with, you may need an additional variable to put some meaningful information into.
Not entierly sure if this is the best soloution for you BUT!

In Slick you can use a tilemap. which has different layers.

For my game i have a layer for collisions and a layer for the game.

So when i want to see if i've collided i do something like

if(in.isKeyDown(Input.KEY_UP))
{
if(tilemap.getTileId(player.getX() / tileWidth, player.getY() / tileHeight, 0) != 1)
{
if(tilemap.getTileId((player.getX() + tileWidth) / tileWidth, player.getY() / tileHeight, 0) != 1)
{
player.moveUp();
}
}
}

the paramaters are x,y and layer. So if the player hits a block on layer 0 whos tile id is 1 then, just dont let the player move.
Otherwise let the player moves.

This checks for the top left corner of the players image and the top right corner of the players image.


Of course to do this example you would need to change about what you are doing a bit.

Hope this was helpful, if you need me to clear up anything, let me know.
/********************************************************************************\
/**********************He Who Dares, Wins**********************************\
/********************************************************************************\

This topic is closed to new replies.

Advertisement