Since your movement isn’t tile-by-tile, you may need to check for collision boxes on 4 points instead of just one, find the 4 corners of your sprite (IE: 0,0, 32,0, 0,32 and 32,32… or the points around your feet) and check all 4 positions.
There is a completely alternative way of doing all this, but it’s much more complicated. You could just draw rectangles around all your blocked tiles, then draw one around your character’s feet and check if they intersect. But that would involve rewriting your entire collision system.
Basically it works like this:
- When your map loads, you run a for loop that checks your entire map tile by tile for the “blocked” property
- Every time it finds one, it creates a collision box rectangle over that spot
- Create a collision box rectangle at your character’s feet
- have a for loop that checks the player’s collision box against all the other collision boxes on the map.
- If any of the intersect, a collision has happened. Stop the player from moving and bounce him back 1 pixel so he isn’t stuck.
That system will work a lot better than the 4-point idea I suggested, but will take a while to implement.
Example code:
Searching for properties then creating objects to act as collision boxes:
static TiledMap map = null;
static public ArrayList <CollisionControl> collisionBoxArray = new ArrayList<CollisionControl>();
int[] tileId[amountOfMapLayersHere];
for (int x = 0; x < map.getWidth(); x++) {
for (int y = 0; y < map.getHeight(); y++) {
for (int l = 0; l < tileID.length; l++) {
tileId[l] = map.getTileId(x, y, l);
if (!(tileId[l] == 0)){ //not needed, just stops if there's no tile there to save a tiny amount of CPU usage.
if (map.getTileProperty(tileId[l], "blocked", "false")){
collisionBoxArray.add (new CollisionControl(x,y,mapX,mapY));
}
}
}
}
}
Very basic collision box object:
CollisionControl.class
package core;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.geom.Rectangle;
import org.newdawn.slick.geom.Shape;
public class CollisionControl {
int x2 = 0;
int y2 = 0;
private Shape collisionBox;
public CollisionControl(int x, int y, int mapX, int mapY) throws SlickException{
collisionBox = new Rectangle(mapX+10*16, mapY+10*16,16,16);
x2 = x;
y2 = y;
}
public void render(Graphics g, int mapX, int mapY) throws SlickException{
g.draw(collisionBox); //Draw the box
}
public void update(int mapX, int mapY) throws SlickException{
collisionBox.setX(mapX+x2*16); //Update box's location on the map
collisionBox.setY(mapY+y2*16); //Update box's location on the map
}
//Just some get methods
public Shape getCollisionBox(){return collisionBox;}
public int getCollisionBoxX(){return x2;}
public int getCollisionBoxY(){return y2;}
}
Then, stick this somewhere to render the boxes so you can see them (they dont need to be seen to work)
COLLISION BOX RENDER
for (int i = 0; i < mapParserArray.size(); i++) {
mapParserArray.get(i).render(g,mapctrl.getMapX(),mapctrl.getMapY());
}
…and here’s a basic idea on whats needed to render a collision box (well, circle) for the player:
public class Player{
public Shape playerBox;
public void init(MapController mapctrl) throws SlickException{
playerBox = new Circle(getPlayerX()+16,getPlayerY()+16,8); //Creates it
}
public void render(MapController mapctrl, Graphics g) throws SlickException{
g.draw(playerBox); //Draws the circle.
}
public void update(MapController mapctrl, GameContainer gc) throws SlickException{
playerBox.setCenterX(getPlayerX()+16); //Repositions it
playerBox.setCenterY(getPlayerY()+16); //Repositions it
}
}
Put this in an update() method somewhere, to update the locations of all those collision boxes you created:
for (int i = 0; i < mapParserArray.size(); i++) {
mapParserArray.get(i).update(getMapX(),getMapY());
}
…and finally, this is the intersect code to check if your player is overlapping a box.
for (int i = 0; i < mapParserArray.size(); i++) {
if(playerBox.intersects(mapParserArray.get(i).getCollisionBox())){
//DON'T allow movement code here.
break;
}
}
Note that this is all untested code, I just ripped it all out of a old program I made forever ago and removed anything unrelated. But at least it’ll give you an idea on where to start rewriting the entire collision system if you want to go that route.
EDIT: Fixed a small code error