我从另一个网络教程(SuperKoalio)中获取了一些关于检测我的播放器与tilemap图层中称为“墙”的图块之间的碰撞的代码。该游戏是RPG(Gauntlet)风格的游戏。碰撞检测通常有效,但偶尔玩家将穿过墙壁并在地图上显得更远,或突然超出地图范围。它几乎就像有差距。
我使用的代码似乎会立即检查播放器左侧和右侧的磁贴,然后对播放器上方和下方的磁贴执行另一次检查。我认为这个想法基本上没问题,但是这并没有考虑到对角线的移动,我认为这可能会导致玩家穿过墙壁。
我的检测程序中的代码如下:
public void checkCollisions(float delta) {
////////////////////////////////////////////////////////////////
//collision detection - X
int startX, startY, endX, endY;
startX = (int) (position.x);
endX = (int) (position.x + 1);
startY = (int) (position.y);
endY = (int) (position.y);
playerRect = rectPool.obtain();
playerRect.set(position.x, position.y, 1.0f, 1.0f);
getWalls(startX, startY, endX, endY, walls);
for (Rectangle wall : walls)
{
//Rectangle rectangle = rectangleObject.getRectangle();
if (playerRect.overlaps(wall) && velocity.x != 0) {
velocity.x = 0;
if(facingDir == 3) {
position.x = wall.x+1.1f;
} else if(facingDir == 4) {
position.x = wall.x-1.1f;
}
break;
}
// collision happened
//break;
}
playerRect.x = position.x;
// if the player is moving upwards, check the tiles to the top of it's
// top bounding box edge, otherwise check the ones to the bottom
if (velocity.y > 0)
{
startY = (int) (position.y);
endY = (int) (position.y + 1.1f);
}
else
{
startY = endY = (int) (position.y);
}
startX = (int) (position.x);
endX = (int) (position.x + 1);
getWalls(startX, startY, endX, endY, walls);
//playerRect.y = velocity.y;
for (Rectangle wall : walls)
{
if (playerRect.overlaps(wall) && velocity.y != 0)
{
velocity.y = 0;
//velocity.x = 0;
if(facingDir == 1) {
position.y = wall.y - 1.1f;
} else if(facingDir == 2) {
position.y = wall.y + 1.1f;
}
break;
}
break;
}
playerRect.y = position.y;
rectPool.free(playerRect);
velocity.x = 0;
velocity.y = 0;
}
加载墙层的“getWalls()”方法如下:
/**
* Get the walls of the map for collision detection between the player and the walls, so that
* the player cannot pass through.
* @param startX
* @param startY
* @param endX
* @param endY
* @param walls
*/
private void getWalls(int startX, int startY, int endX, int endY, Array<Rectangle> walls)
{
TiledMapTileLayer layer = (TiledMapTileLayer) MapRenderer.map.getLayers().get("walls");
layer.setVisible(false);
rectPool.freeAll(walls);
walls.clear();
for (int y = startY; y <= endY; y++)
{
for (int x = startX; x <= endX; x++)
{
TiledMapTileLayer.Cell cell = layer.getCell(x, y);
if (cell != null)
{
Rectangle rect = rectPool.obtain();
rect.set(x, y, 1, 1);
walls.add(rect);
}
}
}
}
有没有人知道为什么这个例程不是很强大?
我真的希望能够尽可能简单有效地实现这一目标。同样的技术也需要应用于敌人,以阻止他们穿过墙壁。
当然必须有一种更好,更可靠的方法,或者只是我的代码中存在缺陷/缺口 - 例如,如果我是对角线方向的墙吗?