#python #pygame
#python #pygame
Вопрос:
Я работаю над симуляцией на основе агентов. Я хочу, чтобы каждый агент выбирал, на каком другом агенте сосредоточиться. Существует много разных входных данных, но здесь я спрашиваю о видении. Таким образом, агент должен видеть, какой другой агент находится ближе всего, также учитывая размер. Они должны заботиться о больших вещах больше, чем о меньших, крошечный агент очень близко не такая большая проблема, как огромный агент чуть дальше. Пока все в порядке, за исключением того, что при рассмотрении вопроса о том, кто ближе и больше, также учитываются другие, которые находятся вне визуального диапазона.
У меня это пока:
# both seen and viewer are two different groups
def sight(seen, viewer)
for entity in viewer:
# This is needed later to decide which way to go, not used here
currentDir = entity.Direction
# Figure out where the viewer is
pos = pygame.math.Vector2(entity.rect.centerx, entity.rect.centery)
# Find out who is closest.
# Uses viewer location and location of each agent in the other group to see who is closest.
# At the end, divided by size*size of the agent in the other group (for height / width).
# Otherwise they'd pay attention to a tiny agent that's close by
# instead of a huge agent that's just a bit further away.
closeby = min([e for e in seen.sprites()], key=lambda e: (pos.distance_to(pygame.math.Vector2(e.rect.centerx, e.rect.centery)) / (e.size * e.size)))
vector = pygame.math.Vector2((entity.rect.centerx - closeby.rect.centerx), (entity.rect.centery - closeby.rect.centery))
# Get the distance to that other agent
distance = math.hypot(entity.rect.centerx - closeby.rect.centerx, entity.rect.centery - closeby.rect.centery)
# They can't see forever, so they have a sight limit
if distance < entity.sight:
Blah blah, rest of the code here
Вот проблема: «если distance <entity.sight» появляется ПОСЛЕ того, как они выбирают «closeby», означает, что они могут «выбрать» крупного агента в качестве ближайшего, который затем устраняется, потому что они слишком далеко.
Представьте это: я агент X. Есть кто-то маленький, о ком я должен беспокоиться (агент Y), который находится в пределах моего визуального диапазона. Однако есть кто-то (агент Z), который действительно большой, который находится за пределами моего визуального диапазона. Агент Z настолько велик, что я выбираю его в качестве «ближайшего». Тогда он находится за пределами визуального диапазона, поэтому никто не выбирается «if distance <entity.sight». Теперь никто не выбран, даже если агент Y находится достаточно близко, он должен был быть выбран.
Я чувствую, что либо поиск
closeby = min([e for e in etc etc etc
должно быть ограничено тем, кто находится в пределах визуального диапазона (но я не знаю, как это сделать), или что, если агент, выбранный как «closeby», находится за пределами визуального диапазона, следует выбрать ВТОРОЙ ближайший. Если они снова находятся вне визуального диапазона, следует выбрать ТРЕТИЙ ближайший и т.д., пока он не попадет в визуальный диапазон. Но я тоже не уверен, как это сделать.
Любая помощь, которую кто-либо может предложить в ограничении «min ([e для e в бла-бла-бла» или для выбора следующего min в этой группе, если первый не означает критерии «entity.sight», была бы чрезвычайно признательна. Я чувствую, что второй вариант (итерация по группе), скорее всего, будет возможен, но я довольно новичок в python, поэтому я не знаю.
Большое вам всем спасибо!
Ответ №1:
Либо используйте цикл, чтобы найти ближайший, а также видимый элемент:
import math
def sight(seen, viewer)
for entity in viewer:
currentDir = entity.Direction
entityPos = pygame.math.Vector2(entity.rect.center)
minE = None
minCloseByDist = math.inf
for e for e in seen.sprites():
ePos = pygame.math.Vector2(e.rect.center)
distance = entityPos.distance_to(ePos)
if distance < entity.sight:
closeByDist = distance / (e.size * e.size)
if minE == None or closeByDist < minCloseByDist:
minE = e
minCloseByDist = minE
if minE != None:
# [...]
Или вы можете сначала найти все элементы в поле зрения, а затем ближайший элемент:
def sight(seen, viewer)
for entity in viewer:
currentDir = entity.Direction
entityPos = pygame.math.Vector2(entity.rect.center)
inSight = [e for e in seen.sprites() if entityPos.distance_to(pygame.math.Vector2(e.rect.center)) < entity.sight]
if inSight:
closeby = min([e for e in inSight], key=lambda e: (pos.distance_to(pygame.math.Vector2(e.rect.center)) / (e.size * e.size)))
# [...]