Я пытаюсь сделать так, чтобы животные шли к ближайшему существу, которым они питаются

Я пытаюсь заставить свою программу определить расстояние между несколькими разными спрайтами и перейти к ближайшему, но она этого не делает, вместо этого она выбирает фиксированный, и все они перестают двигаться после того, как один из них съел спрайт вместо этого они следует пойти за новым ближайшим, если они все еще голодны.

if len(preys) > 0:
            for wolf in Wolf_group:
                for rabbits in Rabbit_group:
                    preysX,preysY=wolf.findClosestPrey(self,rabbit.x,rabbit.y)
                    movementx, movementy = Track(wolf.x, preysX, wolf.y, preysY)#how the predators move
                    wolf.move(movementx,movementy)#movementx, #movementy)

функция

 def findClosestPrey(self,preyX,preyY):
        tempdist=math.sqrt((self.x-preyX)**2 + (self.y-preyX)**2)
        if tempDist<dist:
            xpos=preyX
            ypos=preyX

        return xpos, ypos

Я не уверен, почему он это делает, так как все должно быть хорошо

полный код:

#simulates interactions of wild life
import math
import random
import pygame,sys 
import random
import pdb
import time
from pygame.locals  import *

pygame.init()#setsup pygame
screen = pygame.display.set_mode((1000,800))#setsup screen size
clock = pygame.time.Clock()#tells program how fast to update
timmer = 1#how long program has gone on for


#colours
grey=(60,60,60)
dark_grey=(20,20,20)
dark_blue=(0,0,160)
black=(0,0,0)



#classes-------------------------------------------------------------------
class Animal(pygame.sprite.Sprite):#main class
    def __init__(self, image, x, y):
        super().__init__()
        self.x = x #min(max(0, self.x), screen_width)
        self.y = x #min(max(0, self.y), screen_height)
        self.image = image
        self.rect = self.image.get_rect(center = (x, y))
        self.Energy=10
        
        
    def move(self, mx, my):#moves the sprite
        self.x += mx
        self.y += my
        self.rect = self.image.get_rect(center = (self.x, self.y))#sets the image to the position

    def is_collided_with(self, sprite):#is the eat function
        return self.rect.colliderect(sprite.rect)
    
    def checkEnergy(self):#checks the energy of an animal
        EnergyVal=self.energy
        return EnergyVal

    
    def starve(self,sprite):# kills of sprite if energy hits bottom.
        if self.energy<=0:
            sprite.kill()
        else:
            self.energy-=1
            print("starving")
            self.starvetimmer=0

    
    
class Predator(Animal):#class for predators
    def __init__(self,image, x, y):
        super().__init__(image, x, y)
        self.energy=9
        self.starvetimmer=0
        self.dist=1000

    def reproduce(self):
        if self.energy >= 15:
            predator = Predator(self.image,600,600 )#elf.x, self.y)
            all_sprites.add(predator)
            Wolf_group.add(predator)
            self.energy -= 6
            

    def findClosestPrey(self,preyX,preyY):
        tempdist=math.sqrt((self.x-preyX)**2 + (self.y-preyY)**2)
        if tempdist<self.dist:
            xpos=preyX
            ypos=preyX
    

  
         
class Prey(Animal):
    def __init__(self, image, x, y):
        super().__init__(image, x, y)
        self.energy=7
        self.starvetimmer=0
        self.dist=10000
        

    def reproduce(self):
        if self.energy >= 10:
            prey = Prey(self.image,self.x-50,self.y+50 )#elf.x, self.y)
            all_sprites.add(prey)
            Rabbit_group.add(prey)
            self.energy -= 6
            
    

        return xpos, ypos
            
        
        


class Carrot(pygame.sprite.Sprite):#food for prey class
    def __init__(self,image,x,y):
        super().__init__()
        self.x = x
        self.y = y
        self.image = image
        self.rect = self.image.get_rect(center = (self.x, self.y))

        def carrot_creation():
            randomx=random.randint(0,9)
            randomy=random.randint(0,9)

            randomx=randomx*100
            randomy=randomy*100
            
            carrot=Carrot(carrot_image,(randomx,randomy))
            all_sprites.add(carrot)
            carrot_group.add(carrot)





# Functions--------------------------------------------------------------
def Track(AgressorX,DefenderX,AgressorY,DefenderY):#finds comapres X and Y, tells sprite how to move
    if AgressorX > DefenderX:
        XMovement=-1
    elif AgressorX< DefenderX:
        XMovement=1
    else:
        XMovement=0
        
    if AgressorY > DefenderY:
        YMovement=-1
    elif AgressorY < DefenderY: 
        YMovement=1
    else:
        YMovement=0
    return XMovement, YMovement

def leavingWindow(Xpos, Ypos):#boundry, keeps sprites in the window
    if Xpos<=0:
        return True
    elif Xpos>=950:
        return True   
    if Ypos<=0:
        return True
    elif Ypos>=750:
        return True

def Boundry(Xpos, Ypos):
    Xmovement = min(max(0, Xpos), 950)
    ymovement = min(max(0, Ypos), 750)

    return Xmovement, ymovement

def button(msg,x,y,width,height,inactiveColour,activecolour,action=None):#setup buttons
    mouse = pygame.mouse.get_pos()#gets mouses position
    click=pygame.mouse.get_pressed()#sees if the mouse is clicked

    if x+width> mouse[0] > x and y+height> mouse[1] > y:
        pygame.draw.rect(screen, activecolour,(x,y,width, height))
        if click[0]==1 and action!=None:
            if action= = "play":
                main_game()
            elif action= = "quit":
                pygame.quit
                quit()
            elif action= = "pause":
                paused()
                
    else:
        pygame.draw.rect(screen, inactiveColour,(x,y,width,height))

    smallText = pygame.font.Font("freesansbold.ttf",16)
    textSurf, textRect = text_objects(msg, smallText)
    textRect.center = ( (x+(width/2)), (y+(height/2)) )
    screen.blit(textSurf, textRect)



    button("pause",450,450,100,50,grey,dark_grey,"play")
    button("Quit",450,550,100,50,grey,dark_grey,"quit")


    
    
def text_objects(text, font):#sets up the text
    textSurface = font.render(text, True, black)
    return textSurface, textSurface.get_rect()


def paused():

    largeText = pygame.font.SysFont("comicsansms",115)
    TextSurf, TextRect = text_objects("Paused", largeText)
    TextRect.center = ((1000/2),(800/2))
    gameDisplay.blit(TextSurf, TextRect)
    

    while pause:
        for event in pygame.event.get():

            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
                
        #gameDisplay.fill(white)
        

        button("Continue",150,450,100,50,green,bright_green,unpause)
        button("Quit",550,450,100,50,red,bright_red,quitgame)

        pygame.display.update()
        clock.tick(15)  


#classes and sprites--------------------------------------------------------

#setup sprite groups

prey_image = pygame.image.load('Prey.png')
predator_image=pygame.image.load('Icon.png')
carrot_image=pygame.image.load("carrot.png")

all_sprites = pygame.sprite.Group()

carrot_group = pygame.sprite.Group()


Wolf_group= pygame.sprite.Group()
Wolf_group.add(Predator(predator_image,600,600))

Rabbit_group= pygame.sprite.Group()


#sets up multiple rabbits and carrots at start
for i in range(1, 3):
    prey = Prey(prey_image, 100 * i, 700)
    all_sprites.add(prey)
    Rabbit_group.add(prey)

for i in range(0,3):#makes arndom carrots
    randomx=random.randint(0,9)
    randomy=random.randint(0,9)

    randomx=randomx*100
    randomy=randomy*100
    
    carrot=Carrot(carrot_image,randomx,randomy)
    all_sprites.add(carrot)
    carrot_group.add(carrot)

all_sprites.add(carrot_group)
all_sprites.add(Wolf_group)
all_sprites.add(Rabbit_group)


#start of program
def main_game():
    timmer = 1
    running=True
    while running:
        clock.tick(60)
        for event in pygame.event.get():
            if event.type==pygame.QUIT:
                running=False
        #buttons
        #button("pause",650,30,100,50,grey,dark_grey,"play")
        #button("Quit",750,30,100,50,grey,dark_grey,"quit")

        carrots = carrot_group.sprites()
        preys = Rabbit_group.sprites()
        predators = Wolf_group.sprites()

        if len(preys) > 0:
            for wolf in Wolf_group:
                for rabbits in Rabbit_group:
                    preysX,preysY=wolf.findClosestPrey(rabbits.x,rabbits.y)
                    movementx, movementy = Track(wolf.x, preysX, wolf.y, preysY)#how the predators move
                    wolf.move(movementx,movementy)#movementx, #movementy)

                Leaving=leavingWindow(wolf.x,wolf.y)#keeps sprites in window
                if Leaving == True:
                    movementx,movementy=Boundry(wolf.x,wolf.y)
                    wolf.x=movementx
                    wolf.y=movementy

        if len(carrots) > 0:#the movement for prey
            for rabbit in Rabbit_group:
                for carrot in carrot_group:
                    
                   
##                  Energyval=rabbit.checkEnergy()
##                  if Energyval>=8:
                    movementx, movementy = Track(rabbit.x, carrot.x, rabbit.y, carrot.y)#how the prey move
                    rabbit.move(movementx, movementy)

                Leaving=leavingWindow(rabbit.x,rabbit.y)#keeps sprites in window
                if Leaving == True:
                    movementx,movementy=Boundry(rabbit.x,rabbit.y)
                    rabbit.x=movementx
                    rabbit.y=movementy
        
        for carrot in carrots:#removes the carrots if they contact a rabbit
            for rabbit in Rabbit_group:
                if rabbit.is_collided_with(carrot):
                    print('works')
                    carrot.kill()
                    rabbit.dist=1000

                    rabbit.energy += 5#increases the rabbits energy 
                    rabbit.reproduce()#reproduces once the
                    
                if rabbit.starvetimmer==120:#starves the animal over time
                    rabbit.starve(rabbit)
                else:
                    rabbit.starvetimmer+=1

        for wolf in Wolf_group:
            for rabbit in Rabbit_group:
                if rabbit.is_collided_with(wolf):
                    print("works 2")
                    wolf.dist=1000
                    rabbit.kill()

                    wolf.energy+=4#increases the rabbits energy 
                    wolf.reproduce()
                    

            if wolf.starvetimmer==160:
                wolf.starve(wolf)
            else:
                wolf.starvetimmer+=1


        
                
            


        screen.fill((0,128,0))#background
        all_sprites.draw(screen)#makes the sprites
        pygame.display.update()#updates screen
        timmer+=1
               
        
    pygame.quit()
    exit()



#main menu setup-----------------------------------------------------


def main_menu():

    intro = True

    while intro:
        for event in pygame.event.get():
            
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
                
        screen.fill(dark_blue)
        largeText = pygame.font.SysFont("comicsansms",100)
        TextSurf, TextRect = text_objects("Wildlife simulator", largeText)
        TextRect.center = ((1000/2),(200))
        screen.blit(TextSurf, TextRect)

        button("Start",450,450,100,50,grey,dark_grey,"play")
        button("Quit",450,550,100,50,grey,dark_grey,"quit")

        pygame.display.update()
        clock.tick(15)

play=True

#main loop
while play==True:
    #main_menu()

    main_game()

 

Что такое findClosestPrey в dist и где это определяется? Кроме того, неясно, зачем вам нужна эта функция, поскольку все, что она делает, это возвращает X и Y, которые вы передали. Окружающая логика также не ясна; вы не находите ближайшую добычу для каждого волка, вы буквально говорите каждому волку в Wolf_group идти за каждым кроликом в Rabbit_group. Итак, если каждому волку сказать сделать одно и то же, все они, вероятно, займут позицию самого последнего кролика в списке. Так же, как то, что вы описываете. Так что вообще непонятно, почему вы так написали.

Random Davis 09.12.2020 23:09
foo == True является избыточным и не имеет смысла. Просто напишите foo.
Konrad Rudolph 09.12.2020 23:09

У тебя, кажется, ошибка? Вы уверены, что хотите использовать preyX вместо preyY в методе findClosestPrey?

ShlomiF 09.12.2020 23:15

есть pygame.math.Vector2.distance_to

furas 09.12.2020 23:24

@Random, как насчет того, чтобы изменить его, чтобы каждый волк брал разные предметы?

Flat_Pancake 09.12.2020 23:29

@Flat_Pancake вы, вероятно, хотите, чтобы каждый волк шел к одному ближайшему к ним кролику. Не каждому кролику. Но я не знаю точно, как вы хотите, чтобы это работало, это ваша программа. Что касается поиска ближайшего, для каждого волка вам нужно будет получить расстояние до каждого кролика от каждого волка, затем выбрать кролика с наименьшим расстоянием до этого волка и переместить волка в это положение. Что касается того, как все это сделать, это зависит от вас, это потребует нескольких различных изменений. Мы не собираемся писать для вас правильную, полную версию, но мы можем ответить на ваши вопросы, если вы на чем-то застряли.

Random Davis 09.12.2020 23:34

не ожидал, то, что вы дали (имея вещь в стиле списка), было тем, что я ожидал в ответ, так что спасибо

Flat_Pancake 09.12.2020 23:36
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
7
68
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ваш код не может работать, потому что метод findClosestPrey ничего не возвращает:

def findClosestPrey(self,preyX,preyY):
   tempdist=math.sqrt((self.x-preyX)**2 + (self.y-preyY)**2)
   if tempdist<self.dist:
       xpos=preyX
       ypos=preyX

Вам нужно передать список или группу целей (спрайтов) в метод findClosestPrey. Метод находит цель с самым близким расстоянием и возвращает ее позицию. Вернуть позицию самого объекта, если целей нет:

class Predator(Animal):
    # [...]

    def getDistanceTo(self, preyX, preyY):
        return math.sqrt((self.x-preyX)**2 + (self.y-preyY)**2)

    def findClosestPrey(self, targets):
        if not targets:
            return self.x, self.y
        
        minDist = 1000000 # very large distance
        for target in targets:
            tempDist = self.getDistanceTo(target.x, target.y)
            if tempDist < minDist:
                targetX = target.x
                targetY = target.y
        return targetX, targetY
def main_game():
    # [...]

    while running:
        # [...]

        if len(preys) > 0:
            for wolf in Wolf_group:
                preysX, preysY = wolf.findClosestPrey(Rabbit_group)
                movementx, movementy = Track(wolf.x, preysX, wolf.y, preysY)
                wolf.move(movementx, movementy)

                # [...]

Другие вопросы по теме