-1
\$\begingroup\$

I have tilemaps represented by values from 0 to 4. How can I make the player collide with tiles represented by 3 and stop the player from passing through it ? Here is my code for the player and tilemap:

public class tilemap {

private int x;
    private int y;

private int tilesize;
private int[][] map;
private int mapwidth;
private int mapheight;
public static Image img;
public static int camx,camy;

public String sl;

public tilemap(String s,int tilesize){
    this.tilesize = tilesize;

    try{

        BufferedReader br = new BufferedReader(new FileReader(s));

        mapwidth = Integer.parseInt(br.readLine());
        mapheight = Integer.parseInt(br.readLine());

        map = new int[mapheight][mapwidth];

        String del = " ";
        for(int row = 0; row < mapheight; row++){
            String line = br.readLine();
            String[] tokens = line.split(del);
            for(int col = 0; col < mapwidth; col++){
                map[row][col] = Integer.parseInt(tokens[col]);
            }
        }

    }catch(Exception e){}
}


public void update(){


}



public void draw(Graphics g){
    for(int row = 0; row < mapheight; row++){
        for(int col = 0; col < mapwidth; col++){

             int rc = map[row][col];

             if(rc == 0){
                 g.setColor(Color.green);
             }

             if(rc == 1){
                 g.setColor(Color.yellow);
             }
             if(rc == 2){
                 g.setColor(Color.GRAY);
             }
             if(rc == 3){
                 g.setColor(new Color(127,51,0));
             }
             if(rc == 4){
                 g.setColor(Color.BLUE);
             }



             g.fillRect(x + col * tilesize - camx, y + row * tilesize - camy,tilesize,tilesize);


        }
    }
}
}


public class player {

public static boolean camo = false, walkb = false, walkl = false,
        walkr = false, walkw = false;
public static int x = 431, y = 335, anim = 0;
public static String name = "Jack";
public static Image img;
public static int cx, cy;
public static int an = 0, mxan = 2;
public static int an1 = 0, mxan1 = 2;
public static int an2 = 0, mxan2 = 2;
public static int an3 = 0, mxan3 = 2;

public static void tick() {
    if (walkb) {
        // y+=2;
        tilemap.camy += 2;
        if (an <= mxan) {
            an++;
        }
    } else if (walkw) {
        // y-=2;
        tilemap.camy -= 2;
        if (an3 <= mxan3) {
            an3++;
        }
    } else if (walkr) {
        // x+=2;
        tilemap.camx += 2;
        if (an1 <= mxan1) {
            an1++;
        }
    } else if (walkl) {
        // x-=2;
        tilemap.camx -= 2;
        if (an2 <= mxan2) {
            an2++;
        }
    }

    if (an >= mxan) {
        an = 0;
    }
    if (an1 >= mxan1) {
        an1 = 0;
    }
    if (an2 >= mxan2) {
        an2 = 0;
    }
    if (an3 >= mxan3) {
        an3 = 0;
    }

}

public static void render(Graphics g) {
    g.setColor(Color.black);
    g.setFont(new Font("italic", Font.BOLD, 12));
    g.drawString("" + name, x + 10, y - 10);

    /** player **/

    if (anim == 0) {
        if (an1 == 0) {
            ImageIcon i3 = new ImageIcon("res/player.png");
            img = i3.getImage();
            g.drawImage(img, x, y, null);
        } else if (an1 == 1) {
            ImageIcon i3 = new ImageIcon("res/player.1.png");
            img = i3.getImage();
            g.drawImage(img, x, y, null);
        }
    } else if (anim == 1) {
        if (an2 == 0) {
            ImageIcon i3 = new ImageIcon("res/player2.png");
            img = i3.getImage();
            g.drawImage(img, x, y, null);
        } else if (an2 == 1) {
            ImageIcon i3 = new ImageIcon("res/player2.1.png");
            img = i3.getImage();
            g.drawImage(img, x, y, null);
        }
    } else if (anim == 2) {
        if (an3 == 0) {

            ImageIcon i3 = new ImageIcon("res/player3.png");
            img = i3.getImage();
            g.drawImage(img, x, y, null);
        } else if (an3 == 1) {
            ImageIcon i3 = new ImageIcon("res/player3.1.png");
            img = i3.getImage();
            g.drawImage(img, x, y, null);
        }
    } else if (anim == 3) {
        if (an == 0) {
            ImageIcon i3 = new ImageIcon("res/player4.png");
            img = i3.getImage();
            g.drawImage(img, x, y, null);
        } else if (an == 1) {
            ImageIcon i3 = new ImageIcon("res/player4.1.png");
            img = i3.getImage();
            g.drawImage(img, x, y, null);

        }
    }

}
}
\$\endgroup\$
2
\$\begingroup\$

AABBs

There are a couple of ways to handle collision, but the simplest way is to use AABBs (Axis-Aligned-Bounding-Box). AABBs are made up of four coponents: left, right, top, and bottom (in my code, I just call refer to them as min and max X/Y). You can check for collision be checking if the boxes are aligned with each other on all axis.

AABB Example

To implement this, you would create a class called "AABB". This class would contain four variables of a numerical type: left, right, top, and bottom. You would then have a method called something like collidesWith. This method would return a boolean and it would accept another AABB as an argument (we will name this argument other for now). This method would return true if all of the following conditions are met:

this.right  >=  other.left
this.left   <=  other.right
this.top    >=  other.bottom
this.bottom <=  other.top

An example implementation might look like this:

boolean collidesWith(AABB other)
{
    return other != null & // first make sure that the other AABB isn't null so we don't get an error
           this.right >= other.left &
           this.left <= other.right &
           this.top >= other.bottom &
           this.bottom <= other.top;
}

Once you have written this class you would then write a method inside of the tilemap class to return the AABB for the tile at the given X/Y coordinates. This method would return a new AABB instance with the left, right, top, and bottom variables set appropriately. Here is an example implementation:

public AABB getAABB_at(int x, int y)
{
    if(map[x][y] != 3) return null; // we made a null check inside of our collidesWith method, so this won't raise an error
    return new AABB(x * TILE_WIDTH, y * TILE_HIEGHT,
                    x * TILE_WIDTH + TILE_WIDTH, y * TILE_HEIGHT + TILE_HEIGHT);
}

Now that these methods have been written, you must also add an AABB variable to the player.

On each update, you move the player on the X axis, and then you check for collision between the player and the tiles that are surrounding the player. If the player collides with any of the tiles that you checked, you get the amount that the player is inside of the tile by. Keep in mind that this amount should be checked differently depending on which way the player is moving. Once you have this number, you then offset the player's X by this amount to ensure that they aren't colliding with the tile vertically.

You then repeat this step again, except on the Y axis. And don't forget to update the AABB after each movement.

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Simply predict next player position. If it passes through a 3 block don't move.

Do this by creating a checkCollide() function before updating the tilemap.camx-y.

Take into account current position, x,y, ImageIcon height and width and compare to map values on the direction of player sprite.

PS : You should definitely use better named variables.

  • walkr => walkRight
  • an1-3 => ancorWest, East, ...
  • mxan1-3 => maxAncorWest,...

Because it's otherwise hard for us to help you correctly, plus in one month you won't remember and understand anything of what you've done.

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

Easier way: Make a new Rectangle(x, y, width, height) for each of the objects, and check if rect.intersects(otherRect)

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.