[Java] Detecting collision between rectangles between classes

Started by
2 comments, last by rip-off 12 years, 4 months ago
The title probably doesn't make much sense, but I'm having trouble detecting the collision between my player from my Main class and the monster from the Entity class.

Problem: The collision isn't where the 'monster' rectangle(s) are drawn, the collision is at 0,0 but the 'monsters' are clearly at different coordinates.

Since I've been having so much trouble and I'm not completely sure what's causing it, I'm just going to cope/paste both of my classes here.

Main class:
package src;

import org.lwjgl.input.Keyboard;
import org.newdawn.slick.AppGameContainer;
import org.newdawn.slick.BasicGame;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.geom.Rectangle;


public class Main extends BasicGame{
int px = 100, py = 100;
Entity eo = new Entity("", 0, 0, 0);
Rectangle player = new Rectangle(px, py, 16, 16);

public Main() {
super("Test");
}

public static void main(String[] args) throws SlickException{
AppGameContainer app = new AppGameContainer(new Main());
app.start();
}

@Override
public void render(GameContainer gc, Graphics g) throws SlickException {
Entity m1 = new Entity("Monster1", 100, 400, 200); m1.render(gc, g);
Entity m2 = new Entity("Monster2", 100, 550, 200); m2.render(gc, g);
Entity m3 = new Entity("Monster3", 100, 500, 300); m3.render(gc, g);
g.drawString("X:" + player.getX() + "\nY: " + player.getY(), 10, 40);
//Draw player
g.drawRect(px, py, 16 ,16);
}

@Override
public void init(GameContainer gc) throws SlickException {
}

@Override
public void update(GameContainer gc, int arg) throws SlickException {
//Movement
if(Keyboard.isKeyDown(Keyboard.KEY_W)) py -= 0.1;
else if(Keyboard.isKeyDown(Keyboard.KEY_S)) py ++;
else if(Keyboard.isKeyDown(Keyboard.KEY_D)) px ++;
else if(Keyboard.isKeyDown(Keyboard.KEY_A)) px -= 0.1;

player.setX(px);
player.setY(py);

// Collision
if(player.intersects(eo.r)){
System.out.println("Collision");
}else{System.out.println("No collision");}

}
}


And my Entity class: package src;
import org.newdawn.slick.BasicGame;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.geom.Rectangle;


public class Entity extends BasicGame{
public String name;
public int health, x, y;
public Rectangle r = new Rectangle(x, y, 32, 32);


public Entity(String n, int h, int posx, int posy){
super("Test");
name = n;
health = h;
x = posx;
y = posy;
}

@Override
public void render(GameContainer gc, Graphics g) throws SlickException {
g.drawString(name, x-20, y-32);
g.drawString("Health: " + health, x-20, y-16);
g.drawRect(x, y, 32, 32);
g.drawRect(x, y, 16, 16);
}

@Override
public void init(GameContainer gc) throws SlickException {

}

@Override
public void update(GameContainer gc, int i) throws SlickException {
}

}


This draws the 'collision boxes' to where they need to be, I've made them bigger for testing purposes.
But the actually point of collision is at 0,0 (top-left.)

The code is messy, and I'm sure there are plenty of things wrong with it, but I've just been trying for the past two hours and can't get it to work, so it's far from what it needs to be.

Any and all help is appreciated, thanks for taking the time to read this.
Advertisement
You are instantiating new Entities in the render method. These entities are not tested for collision, because they do not exist in the scope of that method. Instead, you are using the Entity "eo", which isn't drawn.

Consider instantiating the Entities in the constructor or init() function, and placing them in a container e.g. ArrayList<Entity>. In the render method, loop through all the Entities and draw them. In the update method, loop through all the entities and test for collision.

You are instantiating new Entities in the render method. These entities are not tested for collision, because they do not exist in the scope of that method. Instead, you are using the Entity "eo", which isn't drawn.

Consider instantiating the Entities in the constructor or init() function, and placing them in a container e.g. ArrayList<Entity>. In the render method, loop through all the Entities and draw them. In the update method, loop through all the entities and test for collision.


Edit: Never mind, I finally got it, thank you!
Something like this:

public class Main extends BasicGame{

int px = 100, py = 100;

private List<Entity> entities = new ArrayList<Entity>();

Rectangle player = new Rectangle(px, py, 16, 16);

public Main() {
super("Test");
}

public static void main(String[] args) throws SlickException{
AppGameContainer app = new AppGameContainer(new Main());
app.start();
}

@Override
public void render(GameContainer gc, Graphics g) throws SlickException {
for(Entity entity : entities) {
entity.render(gc, g);
}

g.drawString("X:" + player.getX() + "\nY: " + player.getY(), 10, 40);
//Draw player
g.drawRect(px, py, 16 ,16);
}

@Override
public void init(GameContainer gc) throws SlickException {
Entity m1 = new Entity("Monster1", 100, 400, 200);
entities.add(m1);

Entity m2 = new Entity("Monster2", 100, 550, 200);
entities.add(m2);

Entity m3 = new Entity("Monster3", 100, 500, 300);
entities.add(m3);
}

@Override
public void update(GameContainer gc, int arg) throws SlickException {
// Movement
if(Keyboard.isKeyDown(Keyboard.KEY_W)) py -= 0.1;
else if(Keyboard.isKeyDown(Keyboard.KEY_S)) py ++;
else if(Keyboard.isKeyDown(Keyboard.KEY_D)) px ++;
else if(Keyboard.isKeyDown(Keyboard.KEY_A)) px -= 0.1;

player.setX(px);
player.setY(py);

// Collision
boolean collision = false;
for(Entity entity : entities) {
if(player.intersects(entity.r)){
collision = true;
break;
}
}

if(collision) {
System.out.println("Collision");
} else {
System.out.println("No collision");
}
}
}

I would recommend you research about containers, as they are the building blocks you'll need for any complex program.

This topic is closed to new replies.

Advertisement