Python 2.7 Python-boids实现
我试图用python实现一个相当基本的boids模拟。我的目标是有一个基本的捕食者-猎物设置的模拟。我发现了一些伪代码(不能发布超过两个链接,但如果你用谷歌搜索boids伪代码,这是第一个结果)和一些代码,并决定试一试。因为我想添加捕食者,所以我决定使用我发现的代码修改它,让那些会成为猎物的水蟒成为精灵,然后从那里开始。然而,我遇到了这个问题 在我修改代码以使用pygame sprites之后,所有的BOID都移动到右下角(原始代码工作正常) 我的代码(只是复制repo)是(github)。有人碰到过第一期吗?有人有办法解决这个问题吗?至于问题2,有人能解释一下怎么做吗 谢谢你,任何帮助都将不胜感激 附言 boids的行为(他们的运动)似乎很好,除了他们总是走到右下角这一事实 p.p.S 多亏了furas,猎物现在行为正常了 p.p.p.SPython 2.7 Python-boids实现,python-2.7,pygame,boids,Python 2.7,Pygame,Boids,我试图用python实现一个相当基本的boids模拟。我的目标是有一个基本的捕食者-猎物设置的模拟。我发现了一些伪代码(不能发布超过两个链接,但如果你用谷歌搜索boids伪代码,这是第一个结果)和一些代码,并决定试一试。因为我想添加捕食者,所以我决定使用我发现的代码修改它,让那些会成为猎物的水蟒成为精灵,然后从那里开始。然而,我遇到了这个问题 在我修改代码以使用pygame sprites之后,所有的BOID都移动到右下角(原始代码工作正常) 我的代码(只是复制repo)是(github)。有人
由于调试问题已经解决,我剩下的问题部分涉及到解释,我认为应该集中在主题上。您必须了解代码中的差异
\uuuu init\uuuu
中,您在启动时使用不同的速度,但这不应该造成差异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