这是我的代码,用于检查图块的类型。如果是倾斜的瓷砖,则更新
角色的位置。如照片所示,我的角色没有沿着斜坡移动。我究竟做错了什么?
bool Entity::PosValidTile(Tile* Tile, int tileX, int tileY)
{
if(Tile->TypeID == TILE_TYPE_ANGLEUP)
{
int Slope, Intercept;
int newY;
Vector P1,P2;
P1.X = tileX; P1.Y = tileY + TILE_SIZE;
P2.X = tileX + TILE_SIZE; P2.Y = tileY;
if(X + (Width/2) > tileX)
{
Slope = -(P2.Y- P1.Y) / (P2.X - P1.X);
Intercept = Slope * (-P1.X + P1.Y);
newY = Slope * ((X + Width/2) + Intercept);
Y = (newY - Height);
return true;
}
}
}
角色的尺寸为48 X 96;分别是宽度和高度。他的起源像瓷砖一样,位于左上角。
这是该功能的使用方式
bool Entity::PosValid(int NewX, int NewY)
{
bool Return = true;
int StartX = (NewX + Col_X) / TILE_SIZE;
int StartY = (NewY + Col_Y) / TILE_SIZE;
int EndX = ((NewX + Col_X) + Width - Col_Width - 1) / TILE_SIZE;
int EndY = ((NewY + Col_Y) + Height - Col_Height - 1) / TILE_SIZE;
if(Flags & ENTITY_FLAG_IGNOREMAP)
{
}else
{
for(int iY = StartY; iY <= EndY;iY++)
{
for(int iX = StartX;iX <= EndX;iX++)
{
Tile* Tile = Area::AreaControl.GetTile(iX * TILE_SIZE, iY * TILE_SIZE);
int atileY = iY * TILE_SIZE;
int atileX = iX * TILE_SIZE;
if(PosValidTile(Tile,atileX,atileY) == false)
{
Return = false;
}
}
}
}
if(Flags & ENTITY_FLAG_MAPONLY)
{
}else
{
for(int i = 0;i < (int)EntityList.size();i++)
{
if(PosValidEntity(EntityList[i], NewX, NewY) == false)
{
Return = false;
}
}
}
return Return;
}
调用上一个函数是我的OnMove函数。
void Entity::OnMove(float MoveX, float MoveY)
{
if(MoveX == 0 && MoveY == 0) return;
double NewX = 0;
double NewY = 0;
CanJump = false;
MoveX *= Time::TimeControl.GetDeltaTime();
MoveY *= Time::TimeControl.GetDeltaTime();
if(MoveX != 0)
{
if(MoveX >= 0) NewX = Time::TimeControl.GetDeltaTime();
else NewX = -Time::TimeControl.GetDeltaTime();
}
if(MoveY != 0)
{
if(MoveY >= 0) NewY = Time::TimeControl.GetDeltaTime();
else NewY = -Time::TimeControl.GetDeltaTime();
}
while(true)
{
if(Flags & ENTITY_FLAG_GHOST)
{
PosValid((float)(X + NewX), (float)(Y + NewY));
X += (float)NewX;
Y += (float)NewY;
}else
{
if(PosValid((float)(X + NewX), (int)(Y)))
{
X += (float)NewX;
}else
{
SpeedX = 0;
}
if(PosValid((float)(X), (float)(Y + NewY)))
{
Y += (float)NewY;
}else
{
if(MoveY > 0)
{
CanJump = true;
}
SpeedY = 0;
}
}
MoveX += (float)-NewX;
MoveY += (float)-NewY;
if(NewX > 0 && MoveX <= 0) NewX = 0;
if(NewX < 0 && MoveX >= 0) NewX = 0;
if(NewY > 0 && MoveY <= 0) NewY = 0;
if(NewY < 0 && MoveY >= 0) NewY = 0;
if(MoveX == 0) NewX = 0;
if(MoveY == 0) NewY = 0;
if(MoveX == 0 && MoveY == 0) break;
if(NewX == 0 && NewY == 0) break;
}
}
然后在主循环中调用此函数,如下所示
OnMove(SpeedX,SpeedY);
速度计算为休假
SpeedX += AccelX * Time::TimeControl.GetDeltaTime();
SpeedY += AccelY * Time::TimeControl.GetDeltaTime();
最佳答案
我给出一个“答案”,但它可能更适合作为注释……几点:
第一个问题,调试器中发生了什么?您甚至加入if
吗?
我在任何地方都没有提到delta time
,应该使用它来获得与时间有关的平稳运动(与帧无关)PosValidTile
对该功能的作用没有太多说明...您似乎在修改Entity
Y
的值,但没有修改X
?如果您没有在斜坡上水平移动,那您也不会上坡是很正常的!TILE_TYPE_ANGLEUP
对我来说没有多大意义,因为如果您的角色从右向左旋转并且其角度为“向下”,
我猜角色移动是在其他地方确定的吗?应该考虑角色的标题,以了解要走的坡度的哪一侧(您的“下一个” X
,这里似乎没有计算出来)
这里的功能不完整吗?并非所有路径都返回值
编辑:您在使用PosValidEntity
和NewX
的地方使用NewY
张贴了新代码-我们看不到这些值的设置位置,但请记住,您的PosValidTile
似乎直接修改了Y
,不是“暂定的NewY”。
另外,我不太确定您的Intercept
应该做什么。基本上,您有Slope
,并且想知道沿着X
轴的像素数,将Slope
乘以该相对值,然后添加基数Y
。在您的情况下,Slope
始终为TILE_SIZE / TILE_SIZE
-> 1
,因此查找新的Y
应该很简单-如果并非总是1
,只需将相对X
乘以该斜率即可
Y = X + (Width/2) - tileX + tileY;
放置角色的
X
位置,添加Half Width
并移除图块的基础X
值,这将使您沿坡度上的X
轴走多远。由于您的斜率始终为1
,因此您沿着Y
轴的距离与在X
轴上的距离一样远,因此,如果您add
(或subtract
,因为我认为较高的值表示较低的值)在屏幕上的坐标中?)将此值设为基础Y
,您应该得到Y
值。关于c++ - 2D 45度斜角瓷砖,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13774853/