random — Создание простого 2D переполнения стека 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();
}

Спрайт двигался, но двигался только вниз вправо. И как только он достигнет того же самого определенного места, он будет только оставаться и вибрировать там … Извините, если мое объяснение недостаточно ясное или не предоставило достаточно информации, необходимой.
введите описание изображения здесь

2

Решение

Вот несколько вещей, которые должны вам помочь:

1) В RandomMove, Твоя последняя else не имеет фигурных скобок, так как вы выполняете две операции, вы должны завернуть их в фигурные скобки, как вы это делали в другом месте

2) float Сравнение сложно. Очень маловероятно, что ваш PosX == MapX || PosY == MapY когда-нибудь сработает. Лучше было бы рассчитать distance между вашей текущей позицией и случайной позицией, а затем выполнить код, если distance меньше чем epsilon (малая стоимость). Вот довольно подробный пост о сравнении с плавающей точкой (ссылка на сайт)

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
}

Не стесняйтесь комментировать, если есть части, которые вы не совсем понимаете

1

Другие решения


По вопросам рекламы [email protected]