【问题标题】:Collision Detection with Java, Slick2D and Tiled Map Editor使用 Java、Slick2D 和平铺地图编辑器进行碰撞检测
【发布时间】:2016-03-02 05:49:05
【问题描述】:

长期以来,我一直在关注碰撞检测以及如何处理它。我需要帮助了解如何使用平铺地图编辑器进行碰撞检测。我使用播放器、相机和键盘移动来解析和显示 TMX 文件。我不确定如何处理碰撞。我的地图有 2 层,一层是你可以在上面行走的草和瓷砖,另一层是 objectLayer。我见过有人说我应该遍历对象层中的所有图块并为它们分配矩形。我不知道该怎么做,我正在寻找一些见解。

我的主要问题是:如何循环遍历我的图层并获取所有图块并为它们分配矩形。

游戏类:

    public class Game extends BasicGameState {

Player player;
Camera cam;
Map map = new Map();

public void init(GameContainer container, StateBasedGame sbg) throws SlickException {
    map.init();
    cam = new Camera(0, 0);
    player = new Player(new Image("res/textures/player.png"), container.getWidth() / 2, container.getHeight() / 2, 32, 32);
}

public void update(GameContainer container, StateBasedGame sbg, int delta) throws SlickException {
    cam.tick(player);
    player.update(container, delta, map);
}

public void render(GameContainer container, StateBasedGame sbg, Graphics g) throws SlickException {
    g.translate(-cam.getX(), -cam.getY());
        map.render();
        player.render(g);
    g.translate(cam.getX(), cam.getY());
}

public int getID() {
    return 1;
}

}

玩家等级:

    public class Player {

float x, y;

int width, height;
double velX = 0.4;
double velY = 0.4;

Image img;

public Player(Image img, float x, float y, int width, int height) {
    this.img = img;
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
}

public void init() throws SlickException {

}

public void update(GameContainer container, int delta, Map map) {
    Input input = container.getInput();

    if (input.isKeyDown(Input.KEY_D)) x += velX;
    if (input.isKeyDown(Input.KEY_A)) x -= velX;
    if (input.isKeyDown(Input.KEY_W)) y -= velY;
    if (input.isKeyDown(Input.KEY_S)) y += velY;

}

public void render(Graphics g) {
    //g.scale(-2, -2);
    g.drawImage(img, x, y);
}

public float getX() {
    return x;
}

public float getY() {
    return y;
}

}

地图类:

    public class Map {

TiledMap map;

public void init() throws SlickException {
    map = new TiledMap("res/map/zenith.tmx");
}

public void render() throws SlickException {
    map.render(0, 0);
}

}

【问题讨论】:

    标签: java loops collision-detection slick2d tiled


    【解决方案1】:

    我不太熟悉获取磁贴的方法,但它肯定在 Javadoc 中。 http://slick.ninjacave.com/javadoc/

    为了检查与玩家的碰撞,你需要改变你的移动来检查玩家的新位置是否会发生碰撞,否则你会卡在他们身上。

    public void update(GameContainer container, int delta, Map map) {
        Input input = container.getInput();
        float dx = 0, dy = 0;
        // add to dx and dy instead of moving the player straight away.
        if (input.isKeyDown(Input.KEY_D)) dx += velX;
        if (input.isKeyDown(Input.KEY_A)) dx -= velX;
        if (input.isKeyDown(Input.KEY_W)) dy -= velY;
        if (input.isKeyDown(Input.KEY_S)) dy += velY;
        // here we check the collisions, you can fiddle with this if statement and it'll behave differently.
        if(dx != 0 || dy != 0){
            if(map.checkCollision(x+dx,y+y){
               x+=dx;
               y+=dy;
            }
        }
    }
    

    至于检查碰撞本身,您需要在地图类中创建一个新方法,为玩家创建一个矩形,并检查地图类中保存碰撞的二维数组。您可以在地图初始化时填充此数组,方法是在您需要的图层中循环通过您的平铺地图并检查平铺是否与 getTile(x,y) 发生冲突。如果瓷砖具有正确的碰撞属性,您可以在 2D 数组中的该位置创建一个矩形,如下所示:

    collisionArray[x][y] = new Rectangle(x,y,TILEWIDTH,TILEHEIGHT);
    

    您现在可以检查内部的碰撞

    map.checkCollision(x,y)
    

    并使用

    为玩家创建一个矩形
    Rectangle player = new Rectangle(x,y,PLAYERWIDTH,PLAYERHEIGHT);
    

    将它们放在一起,您可以使用前面提到的 .intersect(r) 检查与碰撞数组中的任何图块是否相交,并且 map.collision 可以向应该停止玩家移动的玩家返回 true。

    我希望这不是太复杂,javadoc 非常有用,Kevin Glass 写了一篇关于仅使用 2D 数组检查碰撞的文章,碰撞框大小不同。 http://www.cokeandcode.com/main/tutorials/tile-maps/

    【讨论】:

    • 哇,这是一个非常详细的答案,而且说得很好。我现在就去试一试,看看有没有用。现在更有意义了,非常感谢。
    • 我在 objectLayer 上循环遍历我的地图,如果它的 tileid 为 1,那么它会向数组添加一个矩形,但它给了我某种错误。矩形[][] 碰撞数组; public void init() throws SlickException { map = new TiledMapPlus("res/map/zenith.tmx"); int objectLayer = map.getLayerIndex("objectLayer"); for (int x = 0; x
    • 您可能需要用空矩形初始化碰撞数组以循环遍历它。什么错误?
    • 它会抛出一个漂亮的异常,所以我不确定。我将如何为它分配空矩形。
    • 天哪,我想我明白了。而不是 Rectanlge[][] 碰撞数组;我做了 Rectangle[][] collisionArray = new Rectangle[60][30]; 60 是我在 X 轴上的瓷砖数量,30 是我在 Y 轴上拥有的瓷砖数量。所以它现在正在运行,我想我已经为它们分配了矩形
    【解决方案2】:

    好的,现在我的 checkCollision() 中出现空指针异常

    public void assignRectangles() {
        int objectLayer = map.getLayerIndex("objectLayer");
        for (int x = 0; x < map.getWidth(); x++) {
            for (int y = 0; y < map.getHeight(); y++) {
                if (map.getTileId(x, y, objectLayer) == 1){
                    collisionArray[x][y] = new Rectangle(x * 32, y * 32, 32, 32);
                }
            }
        }
    }
    
    public boolean checkCollision(float x, float y) {
        for (int j = 0; j < collisionArray.length; j++) {
            for (int i = 0; i < collisionArray[j].length; i++) {
                if (collisionArray[j][i].getX() == x || collisionArray[j][i].getY() == y) {
                    return false;
                }
            }
        }
        return true;
    }
    

    我把它放在说 if (collisionArray[j][i].getX() == x || collisionArray[j][i].getY() == y) 的那一行

    不知道为什么我得到它虽然

    【讨论】:

    • 在地图初始化时将collisionArray中的每个值设置为大小为0,0的新矩形,或者检查您得到的collisionArray值是否不等于null。
    • 我遍历了collisionArray,里面的所有值都返回了null。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 2013-04-21
    相关资源
    最近更新 更多