Slick2D与tilemap冲突

时间:2016-06-22 10:42:28

标签: java slick2d

我知道Slick2D已被废弃但我觉得这个库的类型代码很舒服。

也许你已经看到了与Slick2d相同的事情,碰撞。现在,我有一个我无法解决的问题,我有这个问题已经有两个星期了。在我的游戏中,有一个TileMap,在那里我找到了所有属于" solid"图层和我在同一位置绘制矩形以使用物理。问题是我的角色(是一些动画)没有检测到属于我的tilemap的实体层的矩形。

如果我使用for循环,则角色不会检测矩形。但是,如果我通过ifs语句查看所有rects,那么碰撞就会起作用。

有谁知道为什么会这样?

抱歉我的英文>。<

任何帮助都会被贬低。

谢谢!

编辑:这是关于我的碰撞的代码。

包含tilemap的Level类:

public class Level extends TiledMap{

private int tileId;
private int layerIndex;
private boolean solids[][];
private Shape rects[][];

public Level(String path) throws SlickException {
    super(path);
    solids = new boolean [super.getWidth()][super.getHeight()];
    rects = new Rectangle[super.getWidth()][super.getHeight()];
    tileId=0;
    layerIndex=0;
}

public int getTileId() {
    return tileId;
}

public int getLayerIndex() {
    return layerIndex;
}

public boolean[][] getSolids() {
    return solids;
}

public Shape[][] getRects() {
    return rects;
}
public Shape getSingleRect(int i, int j){
    return rects[i][j];
}

public void setTileId(int tileId) {
    this.tileId = tileId;
}

public void setLayerIndex(String layerName) {
    this.layerIndex = super.getLayerIndex(layerName);
}

public void setSolid(int i, int j, boolean solid) {
    this.solids[j][i] = solid;
}

public void setRect(int i, int j, Shape rect) {
    this.rects[j][i] = rect;
}

//other methods
public void printSolidMatrix(){
    System.out.println("SOLID MATRIX");
    for(int i=0;i<super.getWidth();i++){
        for(int j=0;j<super.getHeight();j++){
            System.out.print(solids[j][i]+" ");
        }
        System.out.println();
    }
}

public void drawDebugRects(Graphics g){
    layerIndex = this.getLayerIndex();
    tileId = 0;
    for(int i=0;i<this.getWidth();i++){
        for(int j=0;j<this.getHeight();j++){
            tileId = this.getTileId(j, i, layerIndex);
            g.draw(rects[j][i]);
        }
    }
}
public boolean collidesWith(Shape s){
    for(int i=0;i<this.getWidth();i++){
      for(int j=0;j<this.getHeight;j++){
          if(s.intersects(rects[j][i]) && solids[j][i]){
          }
      }
    }
    return false;
}

}

我的播放器类包含有关物理的属性:

public class Player{

private Level map;
private float x;
private float y;
private boolean falling;

private Shape bounds;

public Player(Level map) throws SlickException{ 

    falling = true;
    x=0;
    y=500;
    this.map = map;
    this.setBounds(this.x, this.y, this.x*32, this.y*32);
}
public float getX() {
    return x;
}
public void increaseX(float x) {
    this.x += x;
}
public float getY() {
    return y;
}
public void increaseY(float y) {
    this.y += y;
}
public Shape getBounds() {
    return bounds;
}
public void setBounds(float x, float y, float width, float height) {
    bounds = new Rectangle(x, y, this.currentAnimation.getWidth(), this.currentAnimation.getHeight());
}
public boolean isFalling() {
    return falling;
}
public void setFalling(boolean falling) {
    this.falling = falling;
}

public void render(GameContainer gc, Graphics g) throws SlickException {
    this.getCurrentAnimation().draw(this.getX(), this.getY());
    this.setBounds(this.getX(), this.getY(), this.getCurrentAnimation().getWidth(),this.getCurrentAnimation().getHeight());
    g.draw(this.getBounds());
}
public void update(GameContainer gc, int delta) throws SlickException {
    this.getCurrentAnimation().update(delta);
    //character movement
            if(gc.getInput().isKeyDown(Input.KEY_D)){
                this.setRight(true);
                this.setCurrentAnimation(this.getWalkAnimation());
                this.increaseX(2.5f);
            }

            else if(gc.getInput().isKeyDown(Input.KEY_A)){
                this.setRight(false);
                this.setCurrentAnimation(this.getWalkAnimationReverse());

                if(this.getX()<0){

                }else{
                    this.increaseX(-2.5f);
                }
            }
            else{
                if(!this.isRight()){
                    this.setCurrentAnimation(this.getStandAnimationReverse());
                }else{
                    this.setCurrentAnimation(this.getDefaultAnimation());
                }
            }       
}

}

我正在工作的当前水平:

public class IntroStage extends BasicGameState{


Level map;
Player p;


@Override
public void init(GameContainer gc, StateBasedGame sbg) throws SlickException {
    initMap();
    p = new Player(map); 
    //map.printSolidMatrix();
}

@Override
public void render(GameContainer gc, StateBasedGame sbg, Graphics g) throws SlickException {
    map.render(0, 0);
    map.drawDebugRects(g);
    p.render(gc, g);
}

@Override
public void update(GameContainer gc, StateBasedGame sbg, int delta) throws SlickException {
    p.update(gc, delta);

    //this if make character fall while he doesnt collides
    if(map.collidesWith(p.getBounds())){
       p.increaseY(delta);
    }
    else{
       p.increaseY(0);
    }
}

@Override
public int getID() {
    return 1;
}


public void initMap() throws SlickException{
    map = new Level("res/tiles/test.tmx");
    map.setLayerIndex("suelo");
    int id=0;
    int x=0;
    int y=0;
    for(int i=0; i<map.getWidth();i++){
        for(int j=0;j<map.getHeight();j++){
            id = map.getTileId(j, i, map.getLayerIndex());
            x=j*32;
            y=i*32;
            map.setRect(i, j, new Rectangle(x, y, map.getTileWidth(), map.getTileHeight())); 
            if(id!=0){
                map.setSolid(i, j, true);
            }
            else{
                map.setSolid(i, j, false);
            }
        }
    }
}

}

注意:Slick2D的getTileId方法效果不好,这就是为什么我使用matrix [j] [i]而不是matrix [i] [j]

1 个答案:

答案 0 :(得分:0)

因此,互联网上有很多教程解释了如何做到这一点:

我可以推荐这些以便很好地理解你可能做错了什么:

Slick2d | Entity collision detection

https://gamedev.stackexchange.com/questions/59308/how-do-i-detect-and-handle-collisions-using-a-tile-property-with-slick2d

我强烈建议您的播放器为hitbox。例如,一个32 * 32的矩形,这对于 easy &amp; 精确碰撞检测,因为您可以使用shape.intersects(Shape s)方法。

我检查了你的代码,我理解的缺少的是播放器端的碰撞检测。所以现在你要确定哪些瓷砖被“阻止”了。从您的方法中,每个被阻止的区块都是一个存储在数组中的x,y的形状。

你需要在球员身上做什么,如果你的球员想要移动的方向被阻挡,那么在移动后进行检查。

没有播放器收件箱的方法,虽然可能表现得很谦逊,但取决于你的速度。这应该最适合每个移动命令1个瓦片的速度。 E.G。

if(gc.getInput().isKeyDown(Input.KEY_D)){
   if(Level.solids[Player.x+Player.xv][Player.y] == false){ // Checking whether the tile to the right of the Player is returning false or true
   // ...Do your movement / Animation stuff.
   }

}

在我看来,如果你通过形状检查碰撞做同样的事情会更好。

if(gc.getInput().isKeyDown(Input.KEY_D)){
   for(Shape s : Level.shapes){
   if(!Player.hitbox.intersects(s)){
   // ...Do your movement / Animation stuff.
   }

请注意,您可能无法一个一个地使用它,因为它表现得不精确,您需要根据您的要求进行调整。但是它应该重新考虑你的游戏设计,并给你一个暗示问题可能存在的提示。

希望这会对你有所帮助。