[英]java game - slick - collision handling
如何在浮油中管理碰撞?
我創建了地圖,牆上的每個瓷磚都有選項block = 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項目):
在更新時,您只需檢查陣列即可。 如果是牆不更新。 如果是邊框,請不要更新。
@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];
}
差不多,在你先檢查它之前不要更改值,然后如果一切正常則更改播放器值。
編輯:我添加了一個變量captureInput,這將讓我知道我們實際上有一個keyDown事件。 關於此,有兩條評論。 我認為這是一個“黑客”,使您的代碼工作,而不是最美麗。 我個人會嘗試向窗口添加一個事件監聽器來監聽按鍵點擊,當點擊一個鍵時我會改變位置信息,一直到幀刷新並且會更新,或者只是在現在有更改時刷新通過調用repaint()。
有很多教程可以用來聽onKeyDown。 你的代碼應該現在可以更好地工作,並且不需要像你一樣需要手動捕獲邊緣,你應該能夠在布爾塊數組的邊緣繪制一個牆,如果不是,你可以繼續使用你的方法。
嘗試從X
和Y
位置乘以平鋪尺寸創建塊的矩形,然后使用intersects()
方法驗證它是否與您的實體發生碰撞,如wiki Slick中所述 。
我希望這對你有用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.