Python 2.7 Python-boids实现

Python 2.7 Python-boids实现,python-2.7,pygame,boids,Python 2.7,Pygame,Boids,我试图用python实现一个相当基本的boids模拟。我的目标是有一个基本的捕食者-猎物设置的模拟。我发现了一些伪代码(不能发布超过两个链接,但如果你用谷歌搜索boids伪代码,这是第一个结果)和一些代码,并决定试一试。因为我想添加捕食者,所以我决定使用我发现的代码修改它,让那些会成为猎物的水蟒成为精灵,然后从那里开始。然而,我遇到了这个问题 在我修改代码以使用pygame sprites之后,所有的BOID都移动到右下角(原始代码工作正常) 我的代码(只是复制repo)是(github)。有人

我试图用python实现一个相当基本的boids模拟。我的目标是有一个基本的捕食者-猎物设置的模拟。我发现了一些伪代码(不能发布超过两个链接,但如果你用谷歌搜索boids伪代码,这是第一个结果)和一些代码,并决定试一试。因为我想添加捕食者,所以我决定使用我发现的代码修改它,让那些会成为猎物的水蟒成为精灵,然后从那里开始。然而,我遇到了这个问题

在我修改代码以使用pygame sprites之后,所有的BOID都移动到右下角(原始代码工作正常)

我的代码(只是复制repo)是(github)。有人碰到过第一期吗?有人有办法解决这个问题吗?至于问题2,有人能解释一下怎么做吗

谢谢你,任何帮助都将不胜感激

附言

boids的行为(他们的运动)似乎很好,除了他们总是走到右下角这一事实

p.p.S

多亏了furas,猎物现在行为正常了

p.p.p.S


由于调试问题已经解决,我剩下的问题部分涉及到解释,我认为应该集中在主题上。

您必须了解代码中的差异

  • \uuuu init\uuuu
    中,您在启动时使用不同的速度,但这不应该造成差异

  • 在不同的时刻更新对象

  • 在所有计算之后,您可以同时移动所有猎物(使用组更新)

    原始代码在计算后移动每个boid,所以下一个boid使用不同的数据来计算其移动

    我将
    prey.update()
    放入
    中,用于
    循环,并删除
    所有精灵列表。update()

    我以稍微不同的方式组织代码:

    #!/usr/bin/env python
    # Prey implementation in Python using PyGame
    
    from __future__ import division # required in Python 2.7
    
    import sys
    import pygame
    import random
    import math
    
    # === constants === (UPPER_CASE names)
    
    SCREEN_SIZE = SCREEN_WIDTH, SCREEN_HEIGHT = 800, 600
    
    BLACK = (0, 0, 0)
    
    MAX_VELOCITY = 10
    NUM_BOIDS = 50
    
    BORDER = 25
    
    # === classes === (CamelCase names for classes / lower_case names for method)
    
    class Prey(pygame.sprite.Sprite):
    
        def __init__(self, x, y):
            super(Prey, self).__init__()
    
            # Load image as sprite
            self.image = pygame.image.load("ressources/img/prey.png").convert()
    
            # Fetch the rectangle object that has the dimensions of the image
            self.rect = self.image.get_rect()
    
            # Coordinates
            self.rect.x = x
            self.rect.y = y
    
    #        self.velocityX = random.randint(-10, 10) / 10.0
    #        self.velocityY = random.randint(-10, 10) / 10.0
    
            self.velocityX = random.randint(1, 10) / 10.0
            self.velocityY = random.randint(1, 10) / 10.0
    
        def distance(self, prey):
            '''Return the distance from another prey'''
    
            distX = self.rect.x - prey.rect.x
            distY = self.rect.y - prey.rect.y
    
            return math.sqrt(distX * distX + distY * distY)
    
        def move_closer(self, prey_list):
            '''Move closer to a set of prey_list'''
    
            if len(prey_list) < 1:
                return
    
            # calculate the average distances from the other prey_list
            avgX = 0
            avgY = 0
            for prey in prey_list:
                if prey.rect.x == self.rect.x and prey.rect.y == self.rect.y:
                    continue
    
                avgX += (self.rect.x - prey.rect.x)
                avgY += (self.rect.y - prey.rect.y)
    
            avgX /= len(prey_list)
            avgY /= len(prey_list)
    
            # set our velocity towards the others
            distance = math.sqrt((avgX * avgX) + (avgY * avgY)) * -1.0
    
            self.velocityX -= (avgX / 100)
            self.velocityY -= (avgY / 100)
    
    
        def move_with(self, prey_list):
            '''Move with a set of prey_list'''
    
            if len(prey_list) < 1:
                return
    
            # calculate the average velocities of the other prey_list
            avgX = 0
            avgY = 0
    
            for prey in prey_list:
                avgX += prey.velocityX
                avgY += prey.velocityY
    
            avgX /= len(prey_list)
            avgY /= len(prey_list)
    
            # set our velocity towards the others
            self.velocityX += (avgX / 40)
            self.velocityY += (avgY / 40)
    
        def move_away(self, prey_list, minDistance):
            '''Move away from a set of prey_list. This avoids crowding'''
    
            if len(prey_list) < 1:
                return
    
            distanceX = 0
            distanceY = 0
            numClose = 0
    
            for prey in prey_list:
                distance = self.distance(prey)
    
                if  distance < minDistance:
                    numClose += 1
                    xdiff = (self.rect.x - prey.rect.x)
                    ydiff = (self.rect.y - prey.rect.y)
    
                    if xdiff >= 0:
                        xdiff = math.sqrt(minDistance) - xdiff
                    elif xdiff < 0:
                        xdiff = -math.sqrt(minDistance) - xdiff
    
                    if ydiff >= 0:
                        ydiff = math.sqrt(minDistance) - ydiff
                    elif ydiff < 0:
                        ydiff = -math.sqrt(minDistance) - ydiff
    
                    distanceX += xdiff
                    distanceY += ydiff
    
            if numClose == 0:
                return
    
            self.velocityX -= distanceX / 5
            self.velocityY -= distanceY / 5
    
        def update(self):
            '''Perform actual movement based on our velocity'''
    
            if abs(self.velocityX) > MAX_VELOCITY or abs(self.velocityY) > MAX_VELOCITY:
                scaleFactor = MAX_VELOCITY / max(abs(self.velocityX), abs(self.velocityY))
                self.velocityX *= scaleFactor
                self.velocityY *= scaleFactor
    
            self.rect.x += self.velocityX
            self.rect.y += self.velocityY
    
    # === main === (lower_case names)
    
    # --- init ---
    
    pygame.init()
    screen = pygame.display.set_mode(SCREEN_SIZE)
    #screen_rect = screen.get_rect()
    
    # --- objects ---
    
    # lists
    # This is a list of 'sprites.' Each block in the program is
    # added to this list. The list is managed by a class called 'Group.'
    prey_list = pygame.sprite.Group()
    
    # This is a list of every sprite. All blocks and the player block as well.
    all_sprites_list = pygame.sprite.Group()
    
    # create prey_list at random positions
    for i in range(NUM_BOIDS):
        prey = Prey(random.randint(0, SCREEN_WIDTH), random.randint(0, SCREEN_HEIGHT))
        # Add the prey to the list of objects
        prey_list.add(prey)
        all_sprites_list.add(prey)
    
    # --- mainloop ---
    
    clock = pygame.time.Clock()
    
    running = True
    
    while running:
    
        # --- events ---
    
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    running = False
    
        # --- updates ---
    
        for prey in prey_list:
            closeBoids = []
            for otherBoid in prey_list:
                if otherBoid == prey:
                    continue
                distance = prey.distance(otherBoid)
                if distance < 200:
                    closeBoids.append(otherBoid)
    
            prey.move_closer(closeBoids)
            prey.move_with(closeBoids)
            prey.move_away(closeBoids, 20)
    
            # ensure they stay within the screen space
            # if we roubound we can lose some of our velocity
            if prey.rect.x < BORDER and prey.velocityX < 0:
                prey.velocityX = -prey.velocityX * random.random()
            if prey.rect.x > SCREEN_WIDTH - BORDER and prey.velocityX > 0:
                prey.velocityX = -prey.velocityX * random.random()
            if prey.rect.y < BORDER and prey.velocityY < 0:
                prey.velocityY = -prey.velocityY * random.random()
            if prey.rect.y > SCREEN_HEIGHT - BORDER and prey.velocityY > 0:
                prey.velocityY = -prey.velocityY * random.random()
    
            prey.update()
    
        # Calls update() method on every sprite in the list
        #all_sprites_list.update()
    
        # --- draws ---
    
        screen.fill(BLACK)
    
        # Draw all the spites
        all_sprites_list.draw(screen)
    
        # Go ahead and update the screen with what we've drawn.
        pygame.display.flip()
    
        # Limit to 60 frames per second
        # Used to manage how fast the screen updates
        clock.tick(120)
    
    # --- the end ---
    pygame.quit()
    sys.exit()
    

    在其他导入之前使用它。

    我已经重写了这段代码,并且我相当确定精灵是BOID行为异常的原因。我该如何解决这个问题?我真的很沮丧!使用多个
    print()
    查看代码中发生了什么-在变量和文本中打印值,如
    “我在其他地方”
    我尝试过了。我仍然不知道这个问题是从哪里来的,因为它只在我使用精灵时出现,而不是直接对图像进行闪烁(这就是它工作的时候)。我没有检查代码,但看起来您使用相同的值来更改精灵的位置,而不是不同的值。我将使用
    print()
    查看所有精灵的位置,并查看更改精灵位置的值。我刚刚完成检查。所有的值似乎都没有重复,在第一次迭代中有相当数量的速度是负的。谢谢,但现在BOID做了同样的事情,但移动速度也非常快。我删除了所有的
    delay()
    ,并设置
    勾选(120)
    120FPS-我理解它提供的延迟不到10ms(1000ms/120FPS)。问题是所有的boid仍然位于右下角,我运行代码,每次它们都指向不同的方向。他们在所有屏幕上移动。对我来说,boids一开始都是分散的,但很快就向右下角移动,除了靠近拐角处(每次他们出去一点,都会向拐角处返回)。
    from __future__ import division