I am in the early stages of creating a Java 2d platformer / sidescroller game where the Entity class requires (at this point) basic Rectangle bounds collision detection.
In my code I check to see if the static Rectangle bounds of the Player object intersects with the Rectangle bounds of Entity Object in the array "entities[]" in the Screen class. My method of implementation is rendering a rectangle on the top, bottom, left, and right sides of each Entity.
My code is almost fully working since it does provide collision detection, however this is only true for the last Entity Object in the Array. Every Entity object besides the last one has NO collision detection, even though the Rectangle objects are properly positioned and rendered.
For example if I call the method "addEntities(3)" in my Screen class Constructor, only the 3rd and final Entity will actually utilize the collision detection.
I know the collision detection works because I have adjusted the "checkCollision()" method to check a specific index of the Entity array that isn't the last one. The Rectangle bounds are also rendered to the screen over each Entity sprite properly, so I know the Rectangle object of each Entity is there.
Here is some of my code for the Screen class, which is the intermediary between the Entitiy and the Game class:
public Screen (int width, int height) {
this.width = width;
this.height = height;
addEntities(2); // amount of entities to spawn
}
public void tick() {
checkCollision(); // checks collision
}
public void render(Graphics g) { // renders all entities based on size of array
for (int i = 0; i < this.entitySize; i++) {
entities[i].render(g);
}
}
//
public void addEntities(int entitySize) { // adds entities to the Screen
this.entitySize = entitySize;
entities = new Entity[entitySize];
int renderX, renderY;
for (int i = 0; i < entitySize; i++) {
renderX = (i* 64) + 300;
renderY = 300;
entities[i] = new Entity(renderX, renderY, topFloorMob, topFloorSheet, 64, 64); // adds Entities to the proper index of Array 'entities[]'
}
}
public void checkCollision() { // checks if bounds of the Player Rectangles intersect the bounds of the Entity Array Rectangles
for (int i = 0; i < entitySize; i++) {
if (Player.topBorder.intersects(entities[i].getBottomBounds())) Player.topCollision = true;
else Player.topCollision = false;
if (Player.bottomBorder.intersects(entities[i].getTopBounds())) Player.bottomCollision = true;
else Player.bottomCollision = false;
if (Player.leftBorder.intersects(entities[i].getRightBounds())) Player.leftCollision = true;
else Player.leftCollision = false;
if (Player.rightBorder.intersects(entities[i].getLeftBounds())) Player.rightCollision = true;
else Player.rightCollision = false;
}
}
}
Here is some of the Entity class code:
public class Entity {
public int renderX, renderY;
protected Sprite sprite;
protected SpriteSheet sheet;
protected Rectangle topBorder, bottomBorder, leftBorder, rightBorder;
protected int sizeX, sizeY; // sizes of entity
public Entity(int renderX, int renderY, Sprite sprite, SpriteSheet sheet, int sizeX, int sizeY) {
this.renderX = renderX;
this.renderY = renderY;
this.sprite = sprite;
this.sheet = sheet;
this.sizeX = sizeX;
this.sizeY = sizeY;
setBounds();
}
public void setBounds() {
setTopBounds();
setBottomBounds();
setLeftBounds();
setRightBounds();
}
public Rectangle setTopBounds() {
return topBorder = new Rectangle(renderX, renderY, sizeX, sizeY - (sizeY - 4));
}
public Rectangle setLeftBounds() {
return leftBorder = new Rectangle(renderX, renderY, sizeX - (sizeX - 4), sizeY);
}
public Rectangle setRightBounds() {
return rightBorder = new Rectangle(renderX + (sizeX - 3), renderY, sizeX - (sizeX - 4), sizeY);
}
public Rectangle setBottomBounds() {
return bottomBorder = new Rectangle(renderX, renderY + (sizeY - 3), sizeX, sizeY - (sizeY - 4));
}
public void render(Graphics g) {
sprite.render(g, renderX, renderY);
g.fillRect((int)topBorder.getX(), (int) topBorder.getY(), (int) topBorder.getWidth(), (int) topBorder.getHeight());
g.fillRect((int)leftBorder.getX(), (int) leftBorder.getY(), (int) leftBorder.getWidth(), (int) leftBorder.getHeight());
g.fillRect((int)rightBorder.getX(), (int) rightBorder.getY(), (int) rightBorder.getWidth(), (int) rightBorder.getHeight());
g.fillRect((int)bottomBorder.getX(), (int) bottomBorder.getY(), (int) bottomBorder.getWidth(), (int) bottomBorder.getHeight());
}
public void tick() {
}
public Rectangle getTopBounds() {
return topBorder;
}
public Rectangle getLeftBounds() {
return leftBorder;
}
public Rectangle getRightBounds() {
return rightBorder;
}
public Rectangle getBottomBounds() {
return bottomBorder;
}
And finally here is some of the code for my Player class, which is nearly identical to the Entity class (not properly formatted inheritance at this stage of the project, but it will be fixed later):
public class Player {
public static int renderX, renderY;
public static Sprite sprite;
public static SpriteSheet sheet;
public static Rectangle topBorder;
public static Rectangle bottomBorder;
public static Rectangle leftBorder;
public static Rectangle rightBorder;
public static boolean topCollision = false, bottomCollision = false, leftCollision = false, rightCollision = false;
public static int sizeX, sizeY;
public static boolean moveUp = true, moveDown = true, moveLeft = true, moveRight = true;
public Player(int renderX, int renderY, Sprite sprite, SpriteSheet sheet, int sizeX, int sizeY) {
Player.renderX = renderX;
Player.renderY = renderY;
Player.sprite = sprite;
Player.sheet = sheet;
Player.sizeX = sizeX;
Player.sizeY = sizeY;
setBounds();
}
public void setBounds() {
setTopBounds();
setBottomBounds();
setLeftBounds();
setRightBounds();
}
public void render(Graphics g) {
sprite.render(g, renderX, renderY);
g.fillRect((int)topBorder.getX(), (int) topBorder.getY(), (int) topBorder.getWidth(), (int) topBorder.getHeight());
g.fillRect((int)leftBorder.getX(), (int) leftBorder.getY(), (int) leftBorder.getWidth(), (int) leftBorder.getHeight());
g.fillRect((int)rightBorder.getX(), (int) rightBorder.getY(), (int) rightBorder.getWidth(), (int) rightBorder.getHeight());
g.fillRect((int)bottomBorder.getX(), (int) bottomBorder.getY(), (int) bottomBorder.getWidth(), (int) bottomBorder.getHeight());
}
public void tick() {
checkForCollision();
setBounds();
}
public void checkForCollision() {
if( topCollision = true) moveUp = false;
if( bottomCollision = true) moveDown = false;
if( leftCollision = true) moveLeft = false;
if( rightCollision = true) moveRight = false;
}
public static Rectangle setTopBounds() {
return topBorder = new Rectangle(renderX, renderY, sizeX, sizeY - (sizeY - 4));
}
public static Rectangle setLeftBounds() {
return leftBorder = new Rectangle(renderX, renderY, sizeX - (sizeX - 4), sizeY);
}
public static Rectangle setRightBounds() {
return rightBorder = new Rectangle(renderX + (sizeX - 3), renderY, sizeX - (sizeX - 4), sizeY);
}
public static Rectangle setBottomBounds() {
return bottomBorder = new Rectangle(renderX, renderY + (sizeY - 3), sizeX, sizeY - (sizeY - 4));
}
}
I think the problem arises from the logic used in the Screen class method "checkCollision()", but I am not entirely sure. I will post more code of the main Game class if necessary.
I would like some understanding as to how the collision detection only works for the last Entity of the array, otherwise my code fully works. If there is a better way of implementing this, feel free to leave feedback.
*[EDIT] Added a Collision ID integer associated with the index of the Entity array used by the checkCollision() method to detect whether a collision has occurred and at which index corresponding to the tiles rendered on the Screen.