gpt4 book ai didi

c++ - 等距碰撞 - 'Diamond' 形状检测

转载 作者:太空狗 更新时间:2023-10-29 21:19:14 25 4
gpt4 key购买 nike

我的项目暂时使用等距透视图,我在它们上方以网格格式显示坐标以进行调试。但是,当涉及到播放器的碰撞/网格锁定时,我遇到了一个问题。

由于 sprite 绘图的性质,我的数学计算在纹理的“三角形”角空白区域产生了一些问题。我认为问题如下所示(蓝色是我认为我的瓷砖被检测到的方式,而红色是理想情况下应该如何检测它们以在瓷砖上进行准确的漫游运动:

Reference Screenshot

如您所见,检查我所站立的方 block 的 bool 值(它取玩家脚中心的像素,玩家稍后将是一辆汽车并根据移动方向取一个像素)返回 false并在几种情况下拒绝移动,以及让玩家在某些不应被允许的地方移动。

我认为这是因为每个纹理的截止区域(我认为)被认为是网格区域的一部分,所以当玩家在这些角落区域之一时,它并没有真正检查正确的图 block ,因此返回错误的结果。

我用来创建网格的代码是这样的:

int VisualComponent::TileConversion(Tile* tileToConvert, bool xOrY)
{
int X = (tileToConvert->x - tileToConvert->y) * 64; //change 64 to TILE_WIDTH_HALF
int Y = (tileToConvert->x + tileToConvert->y) * 25;

/*int X = (tileToConvert->x * 128 / 2) + (tileToConvert->y * 128 / 2) + 100;
int Y = (tileToConvert->y * 50 / 2) - (tileToConvert->x * 50 / 2) + 100;*/
if (xOrY)
{
return X;
}
else
{
return Y;
}

}

检查玩家移动的代码是:

bool Clsentity::CheckMovementTile(int xpos, int ypos, ClsMapData* mapData) //check if the movement will end on a legitimate road tile UNOPTIMISED AS RUNS EVERY FRAME FOR EVERY TILE
{
int x = xpos + 7; //get the center bottom pixel as this is more suitable than the first on an iso grid (more realistic 'foot' placement)
int y = ypos + 45;

int mapX = (x / 64 + y / 25) / 2; //64 is TILE-WIDTH HALF and 25 is TILE HEIGHT

int mapY = (y / 25 - (x / 64)) / 2;

for (int i = 0; i < mapData->tilesList.size(); i++) //for each tile of the map
{
if (mapData->tilesList[i]->x == mapX && mapData->tilesList[i]->y == mapY) //if there is an existing tile that will be entered
{
if (mapData->tilesList[i]->movementTile)
{
HAPI->DebugText(std::to_string(mapX) + " is the x and the y is " + std::to_string(mapY));
return true;
}
}
}
return false;
}​

在游戏循环方面解决这个问题之前,我有点卡在进度上。如果有人认为他们知道这个问题或者可能能够提供帮助,那就太好了,我将不胜感激。也供引用,我的图 block 纹理是 128x64 像素,将它们绘制到屏幕背后的数学将它们视为 128x50(以干净地链接在一起)。

最佳答案

与其为渲染和点击映射编写特定的例程,不如认真考虑将它们视为数据的两个 View ,它们可以根据坐标空间的矩阵变换进行变换。您可以有两个坐标空间 - 一个是用于定位和逻辑的漂亮矩形网格。另一个是用于显示和输入的等距 View 。

如果您不熟悉线性代数,您可能需要一点时间来了解它,但一旦您了解了,一切都会变得微不足道。

那么,它是如何工作的呢?您的等距 View 只是沼泽标准 GridView 的旋转,对吗?好吧,关闭。如果您从正方形网格开始,等距 View 也会更改尺寸。总之:我们可以做一个简单的坐标变换吗?

逻辑坐标系->显示系统(例如渲染)

纹理点 => 旋转 45 度 => 按 sqrt(2) 缩放,因为 45 度旋转会按 sqrt(1 * 1 + 1 * 1) 改变 block 的尺寸

显示系统 -> 逻辑坐标系(例如将点击映射到逻辑空间)

点击点 => 按 sqrt(2) 去缩放到 unsquish => 取消旋转 45 度

为什么?

如果您可以进行坐标转换,那么您编写的所有其他内容都将处理一个漂亮的沼泽标准矩形网格,这将使您的任何其他逻辑变得更加简单。您在那里的计算不会涉及计算角度或斜率。例如。现在你的“我可以'向下'移动吗”逻辑要简单得多。

为简单起见,假设您有 64 x 64 的图 block 。现在将屏幕空间点击转换为逻辑图 block 很简单:

(int, int) whichTile(clickX, clickY) {
logicalX, logicalY = transform(clickX, clickY)
return (logicalX / 64, logicalY / 64)
}

您可以通过一些简单的操作来检查 x0,y0 和 x1,y1 是否在逻辑空间中的同一个图 block 上:

bool isSameTile(x0, y0,  x1, y1) {
return floor(x0/64) == floor(x1/64) && floor(y0/64) == floor(y1/64)
}

一旦您定义了转换并在逻辑空间中工作,一切都会变得更加简单。

http://en.wikipedia.org/wiki/Rotation_matrix

http://en.wikipedia.org/wiki/Scaling_%28geometry%29#Matrix_representation

http://www.alcove-games.com/advanced-tutorials/isometric-tile-picking/

如果您不想处理某些矩阵库,您可以非常直接地进行等效数学计算,但是如果您通过这些转换将逻辑管理的关注点与显示/输入分开,我想您会更容易时间到了。

关于c++ - 等距碰撞 - 'Diamond' 形状检测,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27982541/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com