创建一个简单的2D AI C++
问题描述:
我想知道如何制作AI,它可以在地图上平滑地走动(在窗口大小之间)。就像,如果AI达到了定义的地点,那么它会走到另一个地方。 这是我试过的,创建一个简单的2D AI C++
首先,我得到一个从0.0f到608.0f的随机浮点数,因为我的窗口大小是640,640。
void AIntelligence::GenRandom()
{
MapX = static_cast <float> (rand())/(static_cast <float> (RAND_MAX/608.0f));
MapY = MapX;
}
然后,我在精灵的当前位置传递给这个函数
void AIntelligence::RandomMove(float PosX, float PosY)
{
this->PosX = PosX;
this->PosY = PosY;
if (PosX == MapX || PosY == MapY) //If the current is the same as the generated random, then
{ generate it again.
GenRandom();
}
else
{
if (PosX < MapX || PosY < MapY) //If not then I see if the position less than the
{ generated and translate it.
this->PosX += 8.0f;
this->PosY += 8.0f;
}
else if (PosX > MapX || PosY > MapY)
{
this->PosX -= 8.0f;
this->PosY -= 8.0f;
}
else
this->PosX += 0.0f;
this->PosY += 0.0f;
}
}
在我的消息循环,这里是我如何调用该方法
while (GetMessage(&Msg, NULL, 0, 0))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
Inputs->GetInput(); //Not related
Moving->RandomMove(PosX,PosY);
D3DXVECTOR2 SpritePos = D3DXVECTOR2(Moving->getPosX(), Moving->getPosY());
PosX = Moving->getPosX();
PosY = Moving->getPosY();
Graphic->ClearBegin(); //Begin the direct3d scene
Sprite->Begin(D3DXSPRITE_ALPHABLEND);
float Radian = D3DXToRadian(Rotation);
D3DXMatrixTransformation2D(&Mat, NULL, 0.0f, &SpriteScaling, &SpriteCenter, Radian, &SpritePos); // This is where the transformation is set.
Sprite->SetTransform(&Mat);
Sprite->Draw(Texture, NULL, NULL, NULL, D3DCOLOR_XRGB(255, 255, 255));
Sprite->End();
Graphic->EndPresent();
}
的精灵做移动但只能向右移动。一旦它达到相同的地点,它只会停留在那里,并震动......很抱歉,如果我的解释不够清楚或没有提供足够的信息需要。
答
这里有几件事情,应该可以帮助您:
1)在RandomMove
,你最后else
没有括号,因为你正在执行两项操作,你应该在括号括住他们两个像你在别处做的那样
2)float
比较棘手。这是不太可能的,你的PosX == MapX || PosY == MapY
会触发。如果distance
小于epsilon
(小值),则更好的办法是计算当前位置和随机位置之间的distance
,然后执行代码。这里是一个非常详细的关于浮点数比较的文章(link)
3)GenRandom
总是将相同的值分配给MapX
和MapY
。你应该尝试,而不是执行两个随机电话(可能使用一个const float
来定义您的最大值或使其配置,而不是硬编码该宽度
4)你RandomMove
方法是有点误导。它不会执行随机移动,它将朝着MapX
和MapY
。您应该将移动代码中的呼叫分开到GenRandom
。
5)您的移动代码仅适用于对角线,因为您始终在相同的方向上同时增加或减少两个轴的位置。
这里是你的代码可能是什么样子的建议(没有测试):
void AIntelligence::GenRandom(const float in_MaxValueX, const float in_MaxValueY)
{
MapX = in_MaxValueX * (float)rand()/(float)RAND_MAX;
MapY = in_MaxValueY * (float)rand()/(float)RAND_MAX;
}
bool AIntelligence::MoveTowards(const float in_PosX, const float in_PosY)
{
// how far are we from our objective
const float distX = in_PosX - PosX; // by calculating the distance from the target position, it makes our speed calculations easier later on
const float distY = in_PosY - PosY;
// tolerance in pixels
const float tolerance = 1.0f;
const float absDistX = abs(distX);
const float absDistY = abs(distY);
if(absDistX <= tolerance && absDistY <= tolerance) // destination reached
return true;
else
{
// here, normally, you would use a desired speed AND a delta time (your message loop is not really good for that though) to compute how much movement you can execute in a given frame
const float movement = min(10.f, absDistX + absDistY); // by using min, we're making sure not to overshoot our destination
// compute how this movement is spread on each axis
const float movementX = movement * distX/(absDistX + absDistY);
const float movementY = movement * distY/(absDistX + absDistY);
PosX += movementX;
PosY += movementY;
}
return false;
}
// in your loop
if(Moving->MoveTowards(MapX, MapY))
{
Moving->GenRandom(608.f, 608.f); // you should definitely not hardcode these values
}
随意评论,如果有部分你不太明白
嘿@emartel感谢这么很多有用的指南。由于我正在计算距离,是否可以使用'D3DXVECTOR2(x,y)'?我的意思是,我如何使用这些向量来翻译精灵? – Student 2014-12-07 08:36:50
@Student我会远离API矢量类,并使用我自己的。当你打电话给MoveToward时,你的翻译会发生,所以你应该没问题 – emartel 2014-12-07 19:45:55
好的。谢谢:D它已经正常工作了。 – Student 2014-12-07 20:47:26