SFML и C++ Уроки \ Разработка игр › Форумы › Логика игр › Обнаружение персонажа врагом
В этой теме 13 ответов, 5 участников, последнее обновление Yurec 8 года/лет, 4 мес. назад.
-
АвторСообщения
-
Я хотел сделать обнаружение персонажа врагом но столкнулся с небольшой проблемой ,враг видит перса через стену. Как решить проблем я не знаю.
C++123FloatRect getEnemyview(){//ф-ция получения поля зрения врага.return FloatRect(x , y, w+vec, h);// vec вектор взгляда врага}C++12345678Entity *t = *it;if (t->getEnemyview().intersects(p.getRect()))//проверка на пересеченя{if (t->name == "CheliEnemy")t->state2 = t->stay;// если враг заметил игрока}Если что то не так или предложите систему по совершенней я готов переделать :).
Ты научил врага глядеть на тебя, и понимать что это ты, научи его понимать что стена это стена) Если стена, то считать тебя в не зоны видимости.
Поставь проверку на стену перед этим, и задавай соответствующий флаг, если стена то игнорируй действие обнаружения.
так же проверкой пересечения только со стеной.C++12if (t->getEnemyview().intersects(p.getRect()))//проверка на пересечениясделать проверку что игрок и стена находятся в одном направлении. можно ведь проверять одновременно если игрок там и стена в этом же направлении, то не преследовать и не видеть игрока
Фишка в том что нада убрать обнаружения только за стеной. Когда я чекаю наличие стены враг не реагирует на игрока вообще даже в упор:)
чекнул стену – поставил переключатель на то, что есть стена. и в зависимости от этого переключателя враг должен реагировать на игрока или нет (т.е он начинает реагировать на него, если isWall==false, а иначе не реагирует)
Я понял что он имеет ввиду. Пробуй сравнивать расстояние, если стена ближе чем ты, то реакции нет, и наоборот, если ты ближе чем стена к врагу то реакция есть)
C++12345678for (int i = 0; i<obj.size(); i++){if (t->getEnemyview().intersects(obj[i].rect)){if (obj[i].name == "solid")isWall = true;}}Но как чекнуть что сена перед игроком а не за? За координатами игрока и стены ?
C++12345678if(Расстояние до стены < Расстояние до врага) {if(Пересечение сходится)Не реагировать;}if(Расстояние до стены > Расстояние до врага) {if(Пересечение сходится)Реагировать;}Но как чекнуть что сена перед игроком а не за? За координатами игрока и стены ?
если стена перед игроком, значит она должна быть и перед врагом.
можно попробовать как сказал Heisenberg – расстояния.
у тебя игрок &, стена |, враг E.
предположим что наши символы и есть игрок стена враг и смоделируем такую ситуацию:
& | E
тогда имеем условие:
если (у игрока по иксу правее есть стена) и (у врага по иксу левее есть стена) и (икс врага больше чем х игрока), то {враг не видит игрока;}
разумеется это не единственное условие и не единственная ситуация. но можно попробовать по аналогии и со следующими.так же может быть случай, когда между на стене по горизонтали ними маленькая дырка,в которую они пролазят но стоят немного не ровно по отношению к ней и враг вобще должен увидеть игрока (но не увидит, т.к сработает наше условие выше). для этого надо дополнительно проверять разность координат по игреку. чтобы убрать вот такую погрешность в расчете.
это все из головы. может там на деле нюансы всплывут какие.. а может и прокатит. попробуй )
Реально в SFML сделать проверку не через Rect, а через круг? к примеру стратегия где у юнита радиус поражения не прямоугольный, а круглый?
Да. Но код проверки нужен свой, в стандартных функциях sfml не видел такого.
К примеру в определенном радиусе проверять каждую клетку на пересечение с прямоугольниками объектов из списка?
Не знаю, насколько этот код корректен, но вот тебе для примера мой вариант, где овцы убегают от волков.
C++12345if((*it)->name=="Sheep" && (*it2)->name=="Wolf")if(abs((*it)->x-(*it2)->x)<(*it)->SeeSheepRadius && abs((*it)->y-(*it2)->y)<(*it)->SeeSheepRadius){if((*it)->x<(*it2)->x) (*it)->dx = -0.01; else (*it)->dx = 0.01;if((*it)->y<(*it2)->y) (*it)->dy = -0.01; else (*it)->dy = 0.01;}я зделал через создание круглой формы, радиус которой равен радиусу поражения юнита, дальше
CircleShape AttackRangeCircle;
AttackRangeCircle.setRadius(attack_radius);установил этот круг в центр моего юнита в команде update(), теперь он будет двигаться с моим юнитом:
AttackRangeCircle.setPosition(x – AttackRangeCircle.getRadius(), y – AttackRangeCircle.getRadius());//обновляем положение круга который является радиусом атаки обьектаи в игровом цикле установил проверку на пересечение с обьектами через функцию:
if (Object1->AttackRangeCircle.getGlobalBounds().intersects(Object2->sprite.getGlobalBounds()))
{
return true;
}
когда спрайт объекта2 попадает на форму круга объекта1, функция возвращает true и первый обьект стреляет во второй. -
АвторСообщения
Для ответа в этой теме необходимо авторизоваться.