How to do collision detection with many walls (maze)?

ぃ、小莉子 提交于 2019-12-24 18:13:14

问题


In my game, the player navigates a maze. I can't figure out how to do proper collision detection with the walls. It is easy to do collision detection for staying in a certain area:

if (x > rightWallX - playerWidth) x = rightWallX - playerWidth;
if (x < leftWallX) x = leftWallX;
//...

But how would I do collision detection for many walls?

I can do plain collision detection without correction (like if (intersecting) return true;), but I can't correct this correctly. If I just store the old x and y and reset them, then

  1. The object never actually touches the wall
  2. If the object can go up but is blocked to the right, it won't go up, it will just not move.

How is collision detection in a maze done?


回答1:


The easiest way, once you have solved collision detection, to fix the collision is to move the actor to the closest valid position to where the actor would be were it not for the object it collides with. This assumes no inertia, but it is sufficient for maze-like games or top-down map-crawling games.

If you want to simplify your calculations further, you can limit yourself to detecting if changing the actor's x or y coordinate would be better. If your actor has an axis-aligned rectangular hit-box and all obstacles are axis-aligned rectangular as well (the simplest case), this assumption is indeed correct. However, the results might not be satisfactory in some other cases (potential artifact: speed boost from gliding diagonal walls - not the case in most maze games).

Keep in mind multiple collisions could happen concurrently (pushing against two walls). If there are no sharp angles between two walls that an actor could both intersect (say, if all your obstacles are axis aligned and sufficiently spaced), fixing each collision in turn will suffice - just don't stop after the first collision.




回答2:


You can use Rectangle.intersects() method:

    public Rectangle Player(){
         return new Rectangle(PlayerX,PlayerY,PlayerWidth,PlayerHeight);
         //we do this for getting players x and y values every tick
    }

    if(Player().intersects(new Rectangle(0,0,100,50)))//if(player touching wall)

new Rectangle(0,0,100,50) is just an example you can change it.




回答3:


Ok so i'm currently making a 2D top down view game and I'm not sure how you created your maze. However, in my game my Level is created from a Tile[][] tiles = new Tile[levelWidth][levelHeight]; array. The way i handled collision detection was by checking the surrounding tiles to see if they were solid.

This is my getTile method.

public Tile[][] getTile(int x, int y) {
    if (x < 0 || x >= getWidth() || y < 0 || y >= getHeight()) {
    return new VoidTile();
} else {
    return tiles[x][y];
}
}

In my Tile.java class i have a isSolid() method which returns whether the tile is solid or not. All of my tiles extend my Tile.java so they inherit this method and I override it in their constructor. As i said previously, I am not sure whether or not you use the same style of level implementation as i do. However, It is good practice to do it this way :)

Personally, I am not a big fan of using the .intersects() and .contains() methods for Sprite collision detection. I mainly use them for buttons and alike.

Ok so, In my player.java class i have a checkBlockedDirection(int x, int y) method and it looks like this.

    public void checkBlockedDirection(int x, int y) {
    boolean u = map.getTile(x, y - 1).isSolid();
    boolean d = map.getTile(x, y + 1).isSolid();
    boolean l = map.getTile(x - 1, y).isSolid();
    boolean r = map.getTile(x + 1, y).isSolid();

    if (u) {
        uBlocked = true;
        System.out.println("up tile blocked");
    } else {
        uBlocked = false;
    }
    if (d) {
        dBlocked = true;
        System.out.println("down tile blocked");
    } else {
        dBlocked = false;
    }
    if (l) {
        lBlocked = true;
        System.out.println("left tile blocked");
    } else {
        lBlocked = false;
    }
    if (r) {
        rBlocked = true;
        System.out.println("right tile blocked");
    } else {
        rBlocked = false;
    }
}

Then in my player update method i have this

public void tick() {
    float dx = 0;
    float dy = 0;

    if (input.up.isPressed()) {
        direction = 0;
    } else if (input.down.isPressed()) {
        direction = 2;
    } else if (input.left.isPressed()) {
        direction = 3;
    } else if (input.right.isPressed()) {
        direction = 1;
    } else {
        direction = 4; // standing
    }

    checkBlockedDirection((int)x, (int)y);


    if (input.up.isPressed() && y > 0 && !uBlocked) {
            dy += -speed;
    } else if (input.down.isPressed() && y < map.getHeight() - 1 && !dBlocked) {
            dy += speed;
    } else if (input.left.isPressed() && x > 0 && !lBlocked) {
            dx += -speed;
    } else if (input.right.isPressed() && x < map.getWidth() - 1 && !rBlocked) {
            dx += speed;
    }
    x += dx;
    y += dy;

}

Basically it just checks whether or not the blocks up, down, left, or right are solid. If they are solid then it wont move and if they arent solid then you can move in the desired direction.

Not sure if this helps or not but it's just my take on this kind of grid collision detection :)

Hope this helps :)

Enjoy



来源:https://stackoverflow.com/questions/14132645/how-to-do-collision-detection-with-many-walls-maze

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!