我在自上而下的游戏中实现了一个简单的基于图块的碰撞系统,但我遇到了跨越角落的问题。目前,我的程序占据了玩家的中心点,并在20px的正方形网格(交替的灰色cbackground)上制作了一个平铺。它检查向上,向下,向左和向右的瓷砖是否有碰撞,如果找到了,它会移动到下一个阶段。
下一步是检查玩家在牌块中的位置。为此,我有一个名为getCenterDistanceFromCurrentTile()
的功能(创意名称,我知道)。这将返回从拼贴中心点到玩家中心点的距离的Vector2i(x和y)。然后我用以下方式使用它;
我的问题是对角线。我目前没有检查对角线碰撞,但似乎我必须这样做。我已经尝试过实现它,但是当玩家碰到一个角落时,玩家会跳来跳去。我正在使用播放器x的上述方法< 0和玩家y< 0在一起,没有成功。我已经制作了一些图片来更好地解释我的问题。
此图像显示我的碰撞系统工作正常,左侧发生碰撞(由蓝色瓷砖显示),并检查粉红色瓷砖,但未发现碰撞。绿色磁贴显示玩家当前的磁贴,红色方块显示玩家的当前位置。
此图片清楚地显示了我遇到的问题。粉红色的瓷砖都没有碰到任何东西,因此不需要检查玩家的x和y。
我应该如何检查游戏中的角落碰撞?
我目前的碰撞检查代码;
public boolean isWall(Vector2i loc)
{
return this.isWall(loc.x, loc.y);
}
public boolean isWall(int x, int y)
{
if (x < 0) return true;
if (y < 0) return true;
if (y > map[0].length-1) return true;
if (x > map.length-1) return true;
return map[x][y];
}
public void phys(Player plr) {
Vector2i playerTile = plr.getTile();
// Left
if (isWall(playerTile.x-1, playerTile.y))
{
Vector2i distanceFromTile = plr.getCenterDistanceFromCurrentTile(true);
if (distanceFromTile.x < 0)
{
plr.setX(playerTile.x*BLOCK_SIZE);
}
}
// Right
if (isWall(playerTile.x+1, playerTile.y))
{
Vector2i distanceFromTile = plr.getCenterDistanceFromCurrentTile(true);
if (distanceFromTile.x > 0)
{
plr.setX(playerTile.x*BLOCK_SIZE);
}
}
// Up
if (isWall(playerTile.x, playerTile.y-1))
{
Vector2i distanceFromTile = plr.getCenterDistanceFromCurrentTile(true);
if (distanceFromTile.y < 0)
{
plr.setY(playerTile.y*BLOCK_SIZE);
}
}
// Down
if (isWall(playerTile.x, playerTile.y+1))
{
Vector2i distanceFromTile = plr.getCenterDistanceFromCurrentTile(true);
if (distanceFromTile.y > 0)
{
plr.setY(playerTile.y*BLOCK_SIZE);
}
}
}
答案 0 :(得分:1)
您的phys方法可以返回布尔值,具体取决于玩家是否与任何墙壁碰撞。然后,您可以使用此函数的结果来决定是否移回到移动前的空间中的前一个位置,或者如果您没有碰撞,则继续。
这需要您检查播放器周围的所有相邻墙壁。这将引入一种更清晰的方法来迭代phys方法中的碰撞检查。
这样的改进看起来像:
public boolean phys(Player plr)
{
java.awt.Rectangle playerBounds = new java.awt.Rectangle(plr.x, plr.y, BLOCK_SIZE, BLOCK_SIZE);
for (int y = 0; y < 3; y++)
{
for (int x = 0; x < 3; x++)
{
// Skip the tile the player is on assuming that he is not on a wall already
if (x == 1 && y == 1) continue;
java.awt.Rectangle bounds = new java.awt.Rectangle(/*tile at (x, y) xpos*/, /*tile at (x, y) ypos*/, BLOCK_SIZE, BLOCK_SIZE);
if (bounds.intersects(playerBounds))
{
return true;
}
}
}
// Did not collide
return false;
}