Java - LWJGL - Slick2D - 平铺地图碰撞

时间:2013-12-29 15:41:30

标签: java lwjgl tiles slick2d

我正在制作一个简单的基于平铺的游戏。谈到碰撞检测,我倾向于失败。这是第三次尝试正确地进行像素精确运动。我仍然面临着瓷砖的一些问题。(http://prntscr.com/2evl5c)例如 - > http://prntscr.com/2evl92http://prntscr.com/2evlg6http://prntscr.com/2evll1

这是我上课的。     //包     //进口     公共类LevelOne扩展BasicGameState {           // state是这个类的id,objLayer是检查碰撞的图层的id,tileX,Y = tile上的位置     public int state,objLayer,tileX,tileY;     布尔esc;     输入输入;

public int[][] obj; //store each tile's id of the object layer here

private TiledMap map;

private float x,y,vel, TILE_SIZE;//x position , y position ,velocity, tile size in pixels

private Sound jump;//nevermind

public boolean cLeft,cRight,cUp,cDown;//c(anMove)Left/Right/Down etc

public LevelOne(int state){
    this.state = state;//constructor to pass the 
}

@Override
public void init(GameContainer arg0, StateBasedGame arg1)
        throws SlickException {
      TILE_SIZE = 32;//initialization
      esc = false;
      map = new TiledMap("res/map/map.tmx");
      cUp = false;
      cDown = false;
      cLeft = false;
      cRight = false;
      x = 2 * TILE_SIZE;//see the map
      y = 1 * TILE_SIZE;
      vel = .1f;
      objLayer = map.getLayerIndex("Objects");//get the layer
      jump = new Sound("res/sound/jump.wav");

      obj = new int[10][10];//initialize the 2d array to store the blocked tiles

      for(int col = 0; col < 10;col++){
          for(int row = 0;row < 10;row++){
              obj[col][row] = map.getTileId(col, row, objLayer);
          }
      }
}

@Override
public void render(GameContainer arg0, StateBasedGame arg1, Graphics g)
        throws SlickException {
        map.render(0, 0);//render only the map and a white rectangle (player)

        g.fillRect(x, y, TILE_SIZE, TILE_SIZE);

}

@Override
public void update(GameContainer gc, StateBasedGame sbg, int delta)
        throws SlickException {
    input = gc.getInput();//get input
    if(esc){//somehting about the menu , ignore it!
        Mouse.setGrabbed(false);

    }else{
        Mouse.setGrabbed(true);
    }
        if(input.isKeyPressed(Input.KEY_ESCAPE)){
            esc = true;
        }   
    if(esc){
        Mouse.setGrabbed(false);
            if(input.isKeyPressed(Input.KEY_R)){
                esc = false;
            }else if(input.isKeyPressed(Keyboard.KEY_Q)){
                System.exit(0);
            }else if(input.isKeyPressed(Keyboard.KEY_M)){
                esc = false;
                sbg.enterState(0);
                Mouse.setGrabbed(false);
            }
        }


    //calculate collisions
    AABB();



    //TODO -- FIX COLLISIONS , thats what we need to do :/

    if(input.isKeyDown(Input.KEY_RIGHT)){//arrow keys, check if player can move and decide, see AABB() method!
        if(cRight){
            x += vel * delta;
        }
    }

    if(input.isKeyDown(Input.KEY_LEFT)){
        if(cLeft){
            x -= vel * delta;
        }
    }

    if(input.isKeyDown(Input.KEY_UP)){
        if(cUp){
            y -= vel * delta;
        }
    }

    if(input.isKeyDown(Input.KEY_DOWN)){
        if(cDown){
            y += vel * delta;
        }
    }

        }

@Override
public int getID() {//get the id of the class
    return state;
}

private void AABB(){

    cLeft = false;//re-initialize
    cRight = false;
    cUp = false;
    cDown = false;

    tileX = (int) Math.round(Math.ceil(x / TILE_SIZE));//get the tile of the player
    tileY = (int) Math.round(Math.ceil(y / TILE_SIZE));

    int diffX = (int) Math.round(Math.ceil(x % TILE_SIZE));//get the remainder , sorry for the name
    int diffY = (int) Math.round(Math.ceil(y % TILE_SIZE));

    int HALF_TILE_SIZE = 32 / 2;//get half the tile size

    //Start handling collisions

    if(diffX == HALF_TILE_SIZE){//if the player is actually on a number that can be divided by 32 without remainder , do a simple up/down check
        if(obj[tileX][tileY - 1] == 0){
            cUp = true;
        }   
        if(obj[tileX][tileY + 1] == 0){
            cDown = true;
        }
    }else{
        if(diffX > HALF_TILE_SIZE){//if it is not , check the other nearby squares.Here because diffX > HALF_TILE_SIZE , I get the one near these tiles. its obj[numberoftilex][numberoftiley] to get the tile's id. it returns 0 if it is empty.
            if(obj[tileX][tileY - 1] == 0 && obj[tileX + 1][tileY - 1] == 0){
                cUp = true;
            }
            if(obj[tileX][tileY + 1] == 0 && obj[tileX + 1][tileY + 1] == 0){
                cDown = true;
            }
        }else if(diffX < HALF_TILE_SIZE){
            if(obj[tileX][tileY - 1] == 0 && obj[tileX - 1][tileY - 1] == 0){
                cUp = true;
            }
            if(obj[tileX][tileY + 1] == 0 && obj[tileX - 1][tileY + 1] == 0){
                cDown = true;
            }
        }
    }
    //same things done with X are done with Y
    if(diffY == HALF_TILE_SIZE){
        if(obj[tileX - 1][tileY] == 0){
            cLeft = true;
        }

        if(obj[tileX + 1][tileY] == 0){
            cRight = true;
        }
    }else{
        if(diffY > HALF_TILE_SIZE){
            if(obj[tileX - 1][tileY] == 0 && obj[tileX - 1][tileY - 1] == 0){
                cLeft = true;
            }
            if(obj[tileX + 1][tileY] == 0 && obj[tileX + 1][tileY - 1] == 0){
                cRight = true;
            }
        }else if(diffY < HALF_TILE_SIZE){
            if(obj[tileX - 1][tileY] == 0 && obj[tileX - 1][tileY + 1] == 0){
                cLeft = true;
            }
            if(obj[tileX + 1][tileY] == 0 && obj[tileX + 1][tileY + 1] == 0){
                cRight = true;
            }
        }


    }

}

} //有帮助吗?

1 个答案:

答案 0 :(得分:0)

我做出以下假设:

  1. 图块从0开始,宽TILE_SIZE,因此它跨越0到TILE_SIZE - 1
  2. 网格的原点(图块0,0)位于网格的左上角
  3. 边缘周围有非空的瓷砖边框,因此玩家瓷砖永远不会脱离边缘
  4. 播放器磁贴的播放器磁贴x和y坐标是(TILE_SIZE/2 ,TILE_SIZE/2 )相对于其左上角的像素的位置
  5. Assumed mapping of variables to tiles

    我相信在AABB()末尾添加以下代码块应该可以修复它:

        if(diffX>HALF_TILE_SIZE){
            cRight=true;
        }else if(diffX<HALF_TILE_SIZE){
            cLeft=true;
        }
        if(diffY>HALF_TILE_SIZE){
            cDown=true;
        }else if(diffY<HALF_TILE_SIZE){
            cUp=true;
        }
    

    你忘了考虑如果玩家在右边,那么他们可以向左走。在上面的图片中,玩家应该能够向上,向左和向右移动;但是,您的代码不会考虑当前正方形中有可用空间来移动。