java slick2d - gettileproperty returns true when it shouldn't

I’m trying to implement some collision detection to a test game i’ve been making.
I’ve used TiledMap to create the map and set a property on one of the tiles to blocked=true
This tile is then drawn on layer 0.

I then check to see if the tile exists in the direction the player is moving, using the following code

    if (input.isKeyDown(Input.KEY_DOWN)) {
                sprite = down;
                sprite.update(delta);
                int tileID = map.map.getTileId((int) x / map.map.getTileWidth(), (int) y / map.map.getTileHeight() + 1, 0);
                String value = map.map.getTileProperty(tileID, "blocked", "false");
                if (value.equals("true")) {
                    y += delta * 0.1f;
                    System.out.println("Tile ID: " + (int) (x / map.map.getTileWidth()) + ", " + (int) (y / map.map.getTileHeight() + 1) + " Try to walk down. Tile value below the player is:" + value);
                }
    
            }

this is repeated for each direction.

The problem i’m running into is its picking up the blocked property for incorrect tiles
You can understand better with this video. The yellow tiles are the collision/blocked tiles

map.map.getTileWidth()? Shouldnt that be map.getTileWidth()?

Also, depending on how your character movement works, your tileID fetcher probably isnt grabbing the correct tile and then checking the one below it. I was literally walking out the door so I can’t really get too deep into it, but here’s how I fetch the X/Y my character is standing on. You can use this, then shift it up/down/left/right by 1 to get the tile ID you want to check.

entityX/Y = player’s X/Y on the map. If depending on how you handle figuring out where your player is standing this may need changed, but it gets you the idea.


	public int getEntityTileLocationX() {return (Math.round(entityX)/map.getTileHeight());}
	public int getEntityTileLocationY() {return (Math.round(entityY)/map.getTileWidth());}

then…


	int tileID = map.getTileId(getEntityTileLocationX(), getEntityTileLocationY() + 1, 0);

I’ll try to help more when I get back if this doesnt help you. :smiley:

its map.map since my maps are drawn in a custom map class which has a variable called map which holds the tiledmap data.

Using your code, i’m still getting the same issue

ah, I see. This is a bit off-topic, but you can just extend TiledMap in your custom map class so you can access all the methods inside TiledMap without having to init the TiledMap separately. But I’m unsure of how your code design is setup, so I don’t know if that’s an option.

Back on topic though; it sounds like something isn’t quite working out with your player’s X and Y coordinates in relation to the map. Have you tried doing something like this outside if your IF statement, and seeing if the tile the character us standing on is in fact the correct TileID? This might help you figure out if the math is even working out in the first place before you bother with collision detection.

System.out.println(map.getTileId(getEntityTileLocationX(), getEntityTileLocationY(), 0));

My best guess is the values you’re feeding it aren’t actually the player’s X/Y in relation to the map so you’re randomly bumping into objects elsewhere. IE: Your player may be at say 256,256on the screen so it’s looking at 256,256 on the map when it should be looking at something like say 512,512 because it’s not factoring in the fact the map is rendering starting at something like -256,-256. Kinda hard to explain; I hope you get what I am saying here.

To check if I’m right, you could forcefully render the map at 0,0 and then comment out all your map/camera movement code, then just move the player around and see if collision is working correctly.

The map is already rendered at 0,0.

It does seem as though I’m getting the screen and world positions mixed up, since when i used the System.out.println it is giving incorrect tile ids, some places its showing 0, when it should be 95 (even though tiled says its 94), other places its 95 when it should be 0

After further investigation , the bottom right corner x and y according to tiledmap is 16,16 but ingame its being registered as 15,15

Did you take into account the map starts at tile 0,0, not 1,1? :smiley:

Yes. Tiledmap starts at 0,0 as well, though for some reason when its being put on screen, its being started at -1,-1

I managed to get the following image. The red areas are where the collisions should be happening. That’s also where drawing the player at 0,0 puts it, though because of the camera it becomes 80,0. the coloured tiles along the top edge mark each tile across

EDIT: I’ve narrowed it down my draw map method, specifically where it draws the map. If i manually set it to draw the map at 16,16 i don’t get the error, though the map doesn’t scroll, it jumps instead, though i do if it specify 0,0

Hmmm… Can you show us the map and player (and camera if you have it) rendering code? Sounds like something is goofed up in the math somewhere.

Sure, here is the player

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package pokemon.statebased;

import org.newdawn.slick.Animation;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Image;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.tests.xml.Entity;

/**
 *
 * @author Ceri
 */
public class Player extends Entity {

    private Animation sprite, up, down, left, right;
    private float x = 0, y = 0;
    private final MapClass map;
    private final Camera cam;

    public Player(MapClass m, Camera ca) throws SlickException {
        map = m;
        cam = ca;

        Image[] movementUp = {new Image("Images/Player/u1.png"), new Image("Images/Player/u2.png"), new Image("Images/Player/u3.png"), new Image("Images/Player/u4.png")};
        Image[] movementDown = {new Image("Images/Player/d1.png"), new Image("Images/Player/d2.png"), new Image("Images/Player/d3.png"), new Image("Images/Player/d4.png")};
        Image[] movementLeft = {new Image("Images/Player/l1.png"), new Image("Images/Player/l2.png"), new Image("Images/Player/l3.png"), new Image("Images/Player/l4.png")};
        Image[] movementRight = {new Image("Images/Player/r1.png"), new Image("Images/Player/r2.png"), new Image("Images/Player/r3.png"), new Image("Images/Player/r4.png")};
        int[] duration = {100, 100, 100, 100};

        up = new Animation(movementUp, duration, false);
        down = new Animation(movementDown, duration, false);
        left = new Animation(movementLeft, duration, false);
        right = new Animation(movementRight, duration, false);

        // Original orientation of the sprite. It will look right.
        sprite = right;
    }

    public int getEntityTileLocationX() {   
        System.out.println("X: " + Math.round(this.getX()) / map.map.getTileHeight());
        return (Math.round(this.getX()) / map.map.getTileHeight());
    }

    public int getEntityTileLocationY() {
        System.out.println("Y: " + Math.round(this.getY()) / map.map.getTileWidth());
        return (Math.round(this.getY()) / map.map.getTileWidth());
    }

    public void update(GameContainer container, int delta) throws SlickException {
        Input input = container.getInput();
        if (input.isKeyDown(Input.KEY_UP)) {
            sprite = up;
            y -= delta * 0.1f;
            sprite.update(delta);
        } else if (input.isKeyDown(Input.KEY_DOWN)) {
            sprite = down;
            y += delta * 0.1f;
            sprite.update(delta);
        } else if (input.isKeyDown(Input.KEY_LEFT)) {
            sprite = left;
            x -= delta * 0.1f;
            sprite.update(delta);
        } else if (input.isKeyDown(Input.KEY_RIGHT)) {
            sprite = right;
            x += delta * 0.1f;
            sprite.update(delta);
            int tileID = map.map.getTileId(getEntityTileLocationX(), getEntityTileLocationY(), 0);
            String value = map.map.getTileProperty(tileID, "blocked", "false");
            System.out.println("Tile X: " + getEntityTileLocationX() + " Tile Y: " + getEntityTileLocationY() + " Tile ID: " + tileID + " Blocked: " + value);
        }
    }

    public void draw() {
        System.out.println("X: " + (x - cam.cameraX) + " Y: " + (y - cam.cameraY));
        sprite.draw(x - cam.cameraX, y - cam.cameraY);
    }

    public float getX() {
        return x;
    }

    public float getY() {
        return y;
    }
}

Here is the camera

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package pokemon.statebased;

/**
 *
 * @author Ceri
 */
import java.awt.geom.Point2D;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.geom.Shape;
import org.newdawn.slick.tiled.TiledMap;

public class Camera {

    /**
     * the map used for our scene
     */
    protected TiledMap map;

    /**
     * the number of tiles in x-direction (width)
     */
    protected int numTilesX;

    /**
     * the number of tiles in y-direction (height)
     */
    protected int numTilesY;

    /**
     * the height of the map in pixel
     */
    protected int mapHeight;

    /**
     * the width of the map in pixel
     */
    protected int mapWidth;

    /**
     * the width of one tile of the map in pixel
     */
    protected int tileWidth;

    /**
     * the height of one tile of the map in pixel
     */
    protected int tileHeight;

    /**
     * the GameContainer, used for getting the size of the GameCanvas
     */
    protected GameContainer gc;

    /**
     * the x-position of our "camera" in pixel
     */
    public float cameraX;

    /**
     * the y-position of our "camera" in pixel
     */
    public float cameraY;

    protected Point2D.Float currentCenterPoint = new Point2D.Float(0, 0);

    int tileOffsetX = 0;
    int tileOffsetY = 0;

    //calculate the index of the leftmost tile that is being displayed
    int tileIndexX = 0;
    int tileIndexY = 0;
    
    int offSetX, offSetY;

    /**
     * Create a new camera
     *
     * @param gc the GameContainer, used for getting the size of the GameCanvas
     * @param map the TiledMap used for the current scene
     */
    public Camera(GameContainer gc, TiledMap map) {
        this.map = map;

        this.numTilesX = map.getWidth();
        this.numTilesY = map.getHeight();

        this.tileWidth = map.getTileWidth();
        this.tileHeight = map.getTileHeight();

        this.mapWidth = this.numTilesX * this.tileWidth;
        this.mapHeight = this.numTilesY * this.tileHeight;

        this.gc = gc;
    }

    /**
     * "locks" the camera on the given coordinates. The camera tries to keep the
     * location in it's center.
     *
     * @param x the real x-coordinate (in pixel) which should be centered on the
     * screen
     * @param y the real y-coordinate (in pixel) which should be centered on the
     * screen
     * @return
     */
    public Point2D.Float centerOn(float x, float y) {
        //try to set the given position as center of the camera by default
        cameraX = x - gc.getWidth() / 2;
        cameraY = y - gc.getHeight() / 2;

        //if the camera is at the right or left edge lock it to prevent a black bar
        if (cameraX < 0) {
            cameraX = 0;
        }
        if (cameraX + gc.getWidth() > mapWidth) {
            cameraX = mapWidth - gc.getWidth();
        }

        //if the camera is at the top or bottom edge lock it to prevent a black bar
        if (cameraY < 0) {
            cameraY = 0;
        }
        if (cameraY + gc.getHeight() > mapHeight) {
            cameraY = mapHeight - gc.getHeight();
        }

        currentCenterPoint.setLocation(cameraX, cameraY);
        return currentCenterPoint;
    }

    /**
     * "locks" the camera on the center of the given Rectangle. The camera tries
     * to keep the location in it's center.
     *
     * @param x the x-coordinate (in pixel) of the top-left corner of the
     * rectangle
     * @param y the y-coordinate (in pixel) of the top-left corner of the
     * rectangle
     * @param height the height (in pixel) of the rectangle
     * @param width the width (in pixel) of the rectangle
     */
    public void centerOn(float x, float y, float height, float width) {
        this.centerOn(x + width / 2, y + height / 2);
    }

    /**
     * "locks the camera on the center of the given Shape. The camera tries to
     * keep the location in it's center.
     *
     * @param shape the Shape which should be centered on the screen
     */
    public void centerOn(Shape shape) {
        this.centerOn(shape.getCenterX(), shape.getCenterY());
    }

    /**
     * draws the part of the map which is currently focussed by the camera on
     * the screen
     *
     * @param layer the layer number
     */
    public void drawMap(int layer) {
        this.drawMap(0, 0, layer);
    }

    /**
     * draws the part of the map which is currently focussed by the camera on
     * the screen.

     * You need to draw something over the offset, to prevent the edge of the
     * map to be displayed below it

     * Has to be called before Camera.translateGraphics() !
     *
     * @param offsetX the x-coordinate (in pixel) where the camera should start
     * drawing the map at
     * @param offsetY the y-coordinate (in pixel) where the camera should start
     * drawing the map at the layer
     * @param layer
     */
    public void drawMap(int offsetX, int offsetY, int layer) {
        //calculate the offset to the next tile (needed by TiledMap.render())
        tileOffsetX = (int) -(cameraX % tileWidth);
        tileOffsetY = (int) -(cameraY % tileHeight);

        //calculate the index of the leftmost tile that is being displayed
        tileIndexX = (int) (cameraX / tileWidth);
        tileIndexY = (int) (cameraY / tileHeight);
        
        offSetX = offsetX;
        offSetY = offsetY;
    }

    /**
     * Translates the Graphics-context to the coordinates of the map - now
     * everything can be drawn with it's NATURAL coordinates.
     */
    public void translateGraphics() {
        gc.getGraphics().translate(-cameraX, -cameraY);
    }

    /**
     * Reverses the Graphics-translation of Camera.translatesGraphics(). Call
     * this before drawing HUD-elements or the like
     */
    public void untranslateGraphics() {
        gc.getGraphics().translate(cameraX, cameraY);
    }

}

and here is the mapclass

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package pokemon.statebased;

import java.util.HashMap;
import org.newdawn.slick.Animation;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.tiled.TiledMap;

/**
 *
 * @author Ceri
 */
public class MapClass {

    public TiledMap map;
    private static Camera camera;
    private final GameContainer gc;
    private HashMap<String, Animation> autos = new HashMap<>();

    public MapClass(String file, GameContainer g) throws SlickException {
        map = new TiledMap(file);
        gc = g;
        //SpriteSheet flower = new SpriteSheet("Images/Animations/Flower.png", 16, 16);
        Animation flowerAnimation = new Animation();
        flowerAnimation.setAutoUpdate(true);
        /*flowerAnimation.addFrame(flower.getSprite(0, 0), 300);
        flowerAnimation.addFrame(flower.getSprite(1, 0), 300);
        flowerAnimation.addFrame(flower.getSprite(2, 0), 300);
        autos.put("Flower", flowerAnimation);*/
    }

    public void drawAnimations() {
        Animation a = autos.get("Flower");
        a.drawFlash(210f, 222f, 16f, 16f);
    }

    public void setCamera(Camera c) {
        camera = c;
    }

    public void drawMap(int layer) {
        map.render(
                camera.tileOffsetX + camera.offSetX,
                camera.tileOffsetY + camera.offSetY,
                camera.tileIndexX,
                camera.tileIndexY,
                (gc.getWidth() - camera.tileOffsetX) / camera.tileWidth + 1,
                (gc.getHeight() - camera.tileOffsetY) / camera.tileHeight + 1, layer, false);
        //drawAnimations();
    }
}

Try replacing draw() with this:


    public void drawMap(int layer) {
        map.render(
                camera.tileOffsetX + camera.offSetX,
                camera.tileOffsetY + camera.offSetY,
                camera.tileIndexX,
                camera.tileIndexY,
                (gc.getWidth() - camera.tileOffsetX) / camera.tileWidth,
                (gc.getHeight() - camera.tileOffsetY) / camera.tileHeight, layer, false);
        //drawAnimations();
    }

I think whats going on is it is shifting the visible location of the map down/right by 1, but when it calculates the player’s location with getEntityTileLocationY()/X() it’s not factoring that in so the player’s tile is always 1,1 off.

(gc.getWidth() - camera.tileOffsetX) / camera.tileWidth + 1,
(gc.getHeight() - camera.tileOffsetY) / camera.tileHeight + 1, layer, false);

Doesn’t make any difference. I have found though that

(camera.tileOffsetX + camera.offSetX) + 16,
(camera.tileOffsetY + camera.offSetY) + 16,

seems to work

How do i make it so that when the tile is over .5 (like 9.5, 7.5) its still picked up as being 9, 7 etc but still allow movement to 9.99
At the moment when the tile is .5 or over its classing it as the next tile up, so 7.5 becomes 8. I’ve tried using math.floor but it stops the movement at the whole number

Well, +16/+16 is just correcting the error elsewhere though. You’re rendering something else offshifted by 16/16 and recorrecting it when you render the map (I think)

The code I use to get the player’s exact location at all times (based on his feet position) is this, but I also allow the player to walk in front of objects, only stopping when his feet hit them.


	public int getEntityTileLocationX() {return (Math.round(entityX+16)/32);}
	public int getEntityTileLocationY() {return (Math.round(entityY+28)/32);}

But, I’m thinking this is more what you want for your needs, it should register what tile you’re standing on regardless of where you’re standing on it. I’m assuming based on your code that your character is 16x16. If not, change +8 to +16 (or half the width/height of the sprite)


	public int getEntityTileLocationX() {return (Math.floor(entityX+8)/map.map.getTileHeight());}
	public int getEntityTileLocationY() {return (Math.floor(entityY+8)/map.map.getTileWidth());}

Math.floor(x) is basically the same as Math.round, except instead of rounding to the nearest whole number, it’ll round down no matter what. IE 1.9 == 1, where as Math.round(x) 1.9 == 2.

There’s also Math.ceil(x), that always rounds up. IE: 1.1 == 2

those three classes are the only classes that do any rendering on the map.

My character sprite is 32x32, all tiles are 16x16

At the moment i’m trying to make it so that the player can’t step on the collision tile at all, though can still appear on top of it. I can make more advanced ones at a later stage

Basically allow the player to move in the posistions in the image. The Red F blocks are where the player can’t move at all, but can still appear over the top of them like in the one facing up

Then you’d want to use something like my first one that track’s the feet position where entityX+16 and entityY+28 is the coordinates of your characters feet. My guess is for you, that’s somewhere around the same place mine is anyway, give or take a few pixels.But the fact you’re using a 32x32 character in a 16x16 could complicates things a bit. But I’m pretty sure you can still just offshift the X/Y coordinates to where the character’s feet are, and divide by tileHeight/Width (or just /16).

 
   public int getEntityTileLocationX() {return (Math.round(entityX+16)/16);}
   public int getEntityTileLocationY() {return (Math.round(entityY+28)/16);}

That should give you the tile somewhere around the center of his feet, as seen here:

http://sixtygig.com/junk/coordscheck1.png

thanks, i’ll have a go in the morning and let you know how i get on

ok, i have up and down working without an issue mostly, though i had to change it to

public int getEntityTileLocationY() {
        if (sprite == down) {
            return (Math.round(this.getY() + 32) / 16);
        }

        return (Math.round(this.getY() + 20) / 16);
    }

With left and right, i can way to halfway outside the walls (though it happens no matter what the values in (this.getX() + 16) are set to) and then get stuck, can’t move in either direction.

this is what i mean, the green box around the player is the sprites background. i coloured so i could easily see where the sprites bounds were.

mhmm, are you sure you’re checking the tile to your left/right and not directly at your feet? Looking at the image, it seems to be just checking your feet position at Y:32/X:16 in relation to the sprite (center of his feet) and not checking the tile to his left or right.

You need something like this (based off your current code). Although I’d recommend taking the IF statements out of getTileLocation. But if you want it to be in there, it should be something like this:


public int getEntityTileLocationX() {
        if (sprite == left) { //if he's moving left
            return (Math.round(this.getX() - 16) / 16);
        }
        if (sprite == right) { //If he's moving right
            return (Math.round(this.getX() + 16) / 16);
        }

        return (Math.round(this.getX() + 16) / 16); //I assume this is to check at his feet if he's not moving
        }

Keep in mind though, that if “up”, “down”, “left”, and “right” are always running even if you’re not actually moving it could really confuse the system. It would be better to put it in your movement code. Here’s my actual-working code from my game, as-is, just to give you an idea of where I am coming from. Pay close attention to the collision detection stuff. (Even though I use a totally different system than you for actual collision detection, it shouldn’t matter though)

I comment’ed it all up to show you whats going on.


	public void moveEntityNorth() throws SlickException{
		position = "movingNorth"; //position is the animation to play
		setPosition(position); //This is unneeded for you, this just makes sure all my sprite's layers are ALL moving the same way.
		if (collisionCtrl.checkCollision(getEntityExactLocationX()+7, getEntityExactLocationY()+27, collisionImage, true, false)){ //Collision check that returns true/false if I can move. Mine actually DOES check feet position at all times because of how my system works. Yours should add +-16 in whatever axis you need to check (IE: for north you'd add -16 on X)
			canMoveNorth=false; //Can't move!
		}else{
			canMoveNorth=true; //Can move!
		}
		if(canMoveNorth()){ //If the above check allows me to move
			canMoveReset(); //Ignore this
			entityY -= entitySpeed; //Move me!
		}
		idleDetection = 0; //Ignore this, part of my animation reset code.
	}

Ok, i have all directions mostly working. I say mostly because i’ve ran into a problem when the player is between two tiles, they can still way over (or appear to) collision tiles

This screenshot show the player walking over the tv, which is set as a collision tile. The player shouldn’t be able to walk over the bottom half of the tv, just under the top half

Edit: Forgot the latest version of the code

public int getEntityTileLocationX() {
        if (sprite == left)
            return (Math.round(this.getX() + 22) / 16);
        else
            return (Math.round(this.getX() + 8) / 16);
    }

    public int getEntityTileLocationY() {
        if(sprite == up)
            return (Math.round(this.getY() + 32) / 16);
        else
            return (Math.round(this.getY()+15) / 16);
    }

    public int getTileID(int x, int y) {
        return map.map.getTileId(getEntityTileLocationX() + x, getEntityTileLocationY() + y, 0);
    }

    public String getTileValue(int tileID) {
        return map.map.getTileProperty(tileID, "blocked", "false");
    }

and

public void update(GameContainer container, int delta) throws SlickException {
        Input input = container.getInput();
        if (input.isKeyDown(Input.KEY_UP)) {
            sprite = up;
            sprite.update(delta);
            String value = getTileValue(getTileID(0, -1));
            if (!"true".equals(value)) {
                y -= delta * 0.1f;
            }
        } else if (input.isKeyDown(Input.KEY_DOWN)) {
            sprite = down;
            sprite.update(delta);
            String value = getTileValue(getTileID(0, 1));
            if (!"true".equals(value)) {
                y += delta * 0.1f;
            }
        } else if (input.isKeyDown(Input.KEY_LEFT)) {
            sprite = left;
            sprite.update(delta);
            String value = getTileValue(getTileID(-1, 0));
            if (!"true".equals(value)) {
                x -= delta * 0.1f;
            }
        } else if (input.isKeyDown(Input.KEY_RIGHT)) {
            sprite = right;
            sprite.update(delta);
            String value = getTileValue(getTileID(1, 0));
            if (!"true".equals(value)) {
                x += delta * 0.1f;
            }
        }
    }

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