Я хотел бы получить некоторое представление о том, как я могу создать ИИ, который может плавно перемещаться по карте (между размерами окна). Мол, если ИИ достиг этого определенного места, то он перейдет в другое место.
Вот что я пробовал,
Во-первых, я получаю случайное число с плавающей запятой от 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
между вашей текущей позицией и случайной позицией, а затем выполнить код, если 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
}
Не стесняйтесь комментировать, если есть части, которые вы не совсем понимаете