2

我想了解如何制作一个可以在地图上顺畅行走的 AI(在窗口大小之间)。就像,如果人工智能到达了那个定义的地点,那么它就会走到另一个地点。这是我尝试过的,

首先,我得到一个从 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();
        }

精灵确实移动了,但只是向右下方移动。一旦它到达同一个特定的位置,它只会在那里停留并振动......如果我的解释不够清楚或没有提供足够的信息,请原谅。 在此处输入图像描述

4

1 回答 1

1

以下是一些应该对您有所帮助的事情:

1)在RandomMove,你的最后一个else没有大括号,因为你正在执行两个操作,你应该像在其他地方一样将它们都包裹在大括号中

2)float比较是棘手的。PosX == MapX || PosY == MapY你触发的可能性很小。一个更好的主意是计算distance当前位置和随机位置之间的值,然后在distance小于epsilon(小值)时执行代码。这是关于浮动比较的非常详细的帖子(链接

3)GenRandom总是赋予 和 相同的MapXMapY。您应该尝试执行两个随机调用(并且可能使用 aconst float来定义您的最大值或使其可配置而不是硬编码该宽度

4)你的RandomMove方法有点误导。它不是在执行随机运动,而是朝着MapXMapY。您应该将调用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
}

有不明白的部分欢迎评论

于 2014-12-07T07:07:35.313 回答