2012-11-21 69 views
0

如何管理光滑碰撞?java遊戲 - 光滑 - 碰撞處理

我創建的地圖和每個瓦片是牆有選項blocked = true;

如何實現碰撞,如果我撞牆,我可以移動它的槽? 此外,如果我達到地圖的邊緣,塊移動。

package javagame; 

import org.newdawn.slick.Animation; 
import org.newdawn.slick.GameContainer; 
import org.newdawn.slick.Graphics; 
import org.newdawn.slick.Image; 
import org.newdawn.slick.Input; 
import org.newdawn.slick.SlickException; 
import org.newdawn.slick.state.BasicGameState; 
import org.newdawn.slick.state.StateBasedGame; 
import org.newdawn.slick.tiled.TiledMap; 

public class Play extends BasicGameState { 

    Animation movingUp, movingDown, movingLeft, movingRight; 
    Animation player; 
    int[] duration = {200, 200, 200}; 
    float playerX = 0; 
    float playerY = 0; 
    float cameraX; 
    float cameraY; 
    float screenWidth; 
    float screenHeight; 
    private TiledMap map = null; 
    private static final float SPEED = 0.1f; 

    private boolean[][] blocked; 

    public Play(int state, int x, int y) { 
     playerX = (float) x; 
     playerY = (float) y; 
    } 

    private boolean blocked(float x, float y) { 
     return blocked[(int) x][(int) y]; 
    } 

    @Override 
    public void init(GameContainer gc, StateBasedGame sbg) throws SlickException { 

     map = new TiledMap("map/map.tmx"); 

     // build a collision map based on tile properties in the TileD map 
     blocked = new boolean[map.getWidth()][map.getHeight()]; 
     for (int x = 0; x < map.getWidth(); x++) { 
      for (int y = 0; y < map.getHeight(); y++) { 
       int tileID = map.getTileId(x, y, 0); 
       String value = map.getTileProperty(tileID, "blocked", "false"); 
       if ("true".equals(value)) { 
        blocked[x][y] = true; 
       } 
      } 
     } 

     Image[] walkUp = { 
      new Image("graphics/player/up0.png"), 
      new Image("graphics/player/up1.png"), 
      new Image("graphics/player/up2.png") 
     }; 

     Image[] walkDown = { 
      new Image("graphics/player/down0.png"), 
      new Image("graphics/player/down1.png"), 
      new Image("graphics/player/down2.png") 
     }; 
     Image[] walkLeft = { 
      new Image("graphics/player/left0.png"), 
      new Image("graphics/player/left1.png"), 
      new Image("graphics/player/left2.png") 
     }; 
     Image[] walkRight = { 
      new Image("graphics/player/right0.png"), 
      new Image("graphics/player/right1.png"), 
      new Image("graphics/player/right2.png") 
     }; 

     movingUp = new Animation(walkUp, duration, false); 
     movingDown = new Animation(walkDown, duration, false); 
     movingLeft = new Animation(walkLeft, duration, false); 
     movingRight = new Animation(walkRight, duration, false); 

     player = movingDown; 

    } 

    @Override 
    public void render(GameContainer gc, StateBasedGame sbg, Graphics g) throws SlickException { 

     screenWidth = gc.getWidth(); 
     screenHeight = gc.getHeight(); 

     cameraX = (screenWidth/2) - (playerX/2); 
     cameraY = (screenHeight/2) - (playerY/2); 

     map.render((int) playerX, (int) playerY); 

     player.draw(cameraX, cameraY); 

     g.drawString("X: " + playerX + "\nY: " + playerY, 520, 20); 
     g.resetTransform(); 

    } 

    @Override 
    public void update(GameContainer gc, StateBasedGame sbg, int delta) throws SlickException { 
     Input input = gc.getInput(); 

     if (input.isKeyDown(Input.KEY_UP) || input.isKeyDown(Input.KEY_W)) { 
      player = movingUp; 
      playerY += delta * SPEED; 
      player.update(delta); 
     } else if (input.isKeyDown(Input.KEY_DOWN) || input.isKeyDown(Input.KEY_S)) { 
      player = movingDown; 
      playerY -= delta * SPEED; 
      player.update(delta); 
     } else if (input.isKeyDown(Input.KEY_LEFT) || input.isKeyDown(Input.KEY_A)) { 
      player = movingLeft; 
      playerX += delta * SPEED; 
      player.update(delta); 
     } else if (input.isKeyDown(Input.KEY_RIGHT) || input.isKeyDown(Input.KEY_D)) { 
      player = movingRight; 
      playerX -= delta * SPEED; 
      player.update(delta); 
     } 

    } 

} 

下面是示例的源代碼(NetBeans項目):

https://www.box.com/s/9nicp0n067de632kcpj3

回答

2

在更新,你可以簡單地檢查數組。如果它是一堵牆不更新。如果是邊框,請勿更新。

@Override 
public void update(GameContainer gc, StateBasedGame sbg, int delta) throws SlickException { 
    Input input = gc.getInput(); 
    float yChange = 0, xChange=0; 
    boolean capturedInput = false; 
    if (input.isKeyDown(Input.KEY_UP) || input.isKeyDown(Input.KEY_W)) { 
     player = movingUp; 
     yChange += delta * SPEED; 
     capturedInput = true; 
    } else if (input.isKeyDown(Input.KEY_DOWN) || input.isKeyDown(Input.KEY_S)) { 
     player = movingDown; 
     yChange -= delta * SPEED; 
     capturedInput = true; 
    } else if (input.isKeyDown(Input.KEY_LEFT) || input.isKeyDown(Input.KEY_A)) { 
     player = movingLeft; 
     xChange += delta * SPEED; 
     capturedInput = true; 
    } else if (input.isKeyDown(Input.KEY_RIGHT) || input.isKeyDown(Input.KEY_D)) { 
     player = movingRight; 
     xChange -= delta * SPEED; 
     capturedInput = true; 
    } 
    if(capturedInput==true && !blocked(playerX+xChange,playerY+yChange)){ 
     playerX += xChange; 
     playerY += yChange; 
     player.update(delta); 
    } 
} 

private boolean blocked(float x, float y) { 
    return blocked[(int) x][(int) y]; 
} 

相當多,不要改變價值,直到你先檢查它,然後改變玩家的價值,如果一切正常。

編輯:我添加了一個變量capturedInput,這會讓我知道我們實際上有一個keyDown事件。對此有兩點評論。我認爲這是一個「黑客」,使您的代碼工作,而不是最美麗的。我個人會嘗試添加一個事件監聽器到窗口來監聽關鍵點擊,當一個關鍵點擊時我會改變位置信息,所有的幀都在刷新並且會更新,或者現在只有刷新纔有變化通過調用repaint()。

有很多的教程在那裏收聽onKeyDown。你的代碼現在應該會更好,並且不需要像你那樣手動捕捉邊緣,你應該能夠在布爾塊數組的邊緣繪製圍牆,否則你可以繼續使用你的方法。

+0

我更新了代碼以反映您的意見 – msj121

+1

對我不起作用,錯誤:'java.lang.ArrayIndexOutOfBoundsException:21'如果我在某處(無法移動),動畫還在繼續。 –

+1

你可以給我你的郵件或Skype嗎?我會將您的源代碼發送給您,以便查看錯誤和異常。 –

0

嘗試從XY位置創建塊的矩形乘以瓦片尺寸,然後與intersects()方法驗證它是否與你的實體碰撞時,如在wiki Slick說明。

我希望這對你有用。