我正在使用自然选择模拟器。我之前已经问了一个与之相关的问题(How to test if areas overlap)。现在我有一个我想要运行的代码版本,但事实并非如此。然而,窗口打开了,而不是获得错误消息,但模拟(否则我觉得它应该运行)不会运行。
在我看来,这个问题与初始的生成信息没有被传递到我的生物体的主类有关,但我无法确定。
如果有人能够确定代码为什么不起作用并告诉我需要纠正的内容,我真的很感激。
命令行返回代码正在运行的信息,因此问题必须是显示器不能正常工作。这肯定与我的精灵有关,因为删除
self.image.fill(colors['hotpink2'])
self.image.set_colorkey(colors['hotpink2'])
self.mask = pygame.mask.from_surface(self.image)
来自 init 的会导致矩形显示。
更新的代码如下:
# Import libraries
import pygame, random, numpy
# Initialize PyGame
pygame.init()
# Define colors
colors = pygame.color.THECOLORS
# Set window dimensions
mapWidth = 800
mapHeight = 800
size = [mapWidth, mapHeight]
screen = pygame.display.set_mode(size)
# Display program title in window
pygame.display.set_caption("Natural Selection Game")
# Loop until user closes window
done = False
# Used to manage how fast the screen updates
clock = pygame.time.Clock()
# Generate IDs for organisms
def id_generator():
i = 0
while True:
i += 1
yield i
ids = id_generator()
# Prevent organisms from colliding with self
def collide(a, b):
if a.id == b.id:
return False
return pygame.sprite.collide_mask(a, b)
# ----- Organisms -----
class Organism(pygame.sprite.Sprite):
def __init__(self, width, height, x, y, changeX, changeY, lifespan, species):
# Make PyGame Sprite
pygame.sprite.Sprite.__init__(self, organisms)
self.id = next(ids)
# Set dimensions
self.width = width
self.height = height
# Set starting point
self.x = x
self.y = y
# Set motion type
self.changeX = changeX
self.changeY = changeY
# Set lifespan
self.lifespan = lifespan
# Set species
self.species = species
if species == 'paper':
self.color = colors['red']
elif species == 'rock':
self.color = colors['green']
elif species == 'scissors':
self.color = colors['blue']
# Set age at birth
self.age = 0
# Recognize collisions as to produce only one offspring
self.colliding = set()
# Sprite body
self.rect = pygame.rect.Rect(x, y, width, height)
self.image = pygame.Surface((width, height))
self.image.fill(colors['hotpink2'])
self.image.set_colorkey(colors['hotpink2'])
# Draw
pygame.draw.ellipse(self.image, self.color, [self.x, self.y, self.width, self.height])
self.mask = pygame.mask.from_surface(self.image)
# Randomly generate traits for first generation
@classmethod
def initialSpawn(cls):
# Set dimensions for first generation
width = random.randrange(5,50)
height = random.randrange(5,50)
# Set starting point for first generation
x = random.randrange(0 + width, 800 - width)
y = random.randrange(0 + height, 800 - height)
# Set motion type for first generation
changeX = random.randrange(0,6)
changeY = random.randrange(0,6)
# Set lifespan for first generation
lifespan = random.randrange(300,700)
# Set species for first generation
species = random.choice(['paper', 'rock', 'scissors'])
return cls(width, height, x, y, changeX, changeY, lifespan, species)
# Inherit and/or mutate traits for offspring
def reproduce(self, collidee):
# Set dimensions for offspring
width = random.choice(self.width, collidee.height)
height = random.choice(self.width, collidee.height)
# Set starting points for offspring
x = random.choice(self.x, collidee.x)
y = random.choice(self.y, collidee.y)
# Set motion type for offspring
changeX = random.choice(self.changeX, collidee.changeX)
changeY = random.choice(self.changeY, collidee.changeY)
# Set lifespan for offspring
lifespan = numpy.mean(self.lifespan, collidee.lifespan)
# Set species for offspring
species = self.species
return width, height, x, y, changeX, changeY, species
def update(self):
# Update age
self.age += 1
# Update movement
self.rect.move_ip(self.changeX, self.changeY)
# Manage bouncing
if self.rect.left < 0 or self.rect.right > mapWidth:
self.changeX *= -1
if self.rect.top < 0 or self.rect.bottom > mapHeight:
self.changeY *= -1
# Death from aging
if self.age > self.lifespan:
print (self.id, ' died of age')
self.kill()
return
# Check if collided with another organism of same species for mating or predation
collidee = pygame.sprite.spritecollideany(self, organisms, collide)
# Check the prerequisites for mating:
# - Not already colliding
# - Same species
# - No overpopulation
if collidee and not collidee.id in self.colliding and self.species == collidee.species and len(self.organisms) < 100:
# Keep track of the current collision, so this code is not triggerd throughout duration of collision
self.colliding.add(collidee.id)
collidee.colliding.add(self.id)
print (self.id, ' mated with ', collidee.id)
# The fun part! ;)
self.reproduce(collidee)
# Check the prerequisites for predation:
# - Not already colliding
# - Different species
elif collidee and not collidee.id in self.colliding and self.species != collidee.species:
if self.species == 'paper' and collidee.species == 'rock':
collidee.kill()
self.lifespan += 100
elif self.species == 'rock' and collidee.species == 'scissors':
collidee.kill()
self.lifespan += 100
elif self.species == 'scissors' and collidee.species == 'paper':
collidee.kill()
self.lifespan += 100
else:
# Organism is single and ready to mingle
self.colliding = set()
# Organism group
organisms = pygame.sprite.Group()
# Initial spawner
for i in range(15):
organisms.add(Organism.initialSpawn())
# ----- Simulation -----
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# Logic
organisms.update()
# Draw screen
screen.fill(colors['white'])
# Draw organisms
organisms.draw(screen)
# FPS
clock.tick(60)
# Update drawings
pygame.display.flip()
pygame.quit()
答案 0 :(得分:1)
您正在调用类别方法Organism.initialSpawn()
,该方法会返回width, height, x, y, changeX, changeY, lifespan, species
,但您不会对其执行任何操作。它直接进入垃圾收集。
您可能正在尝试根据您提供的变量创建新的有机体,并在pygame.sprite.Group
中添加这些变量。这可以这样做:
# Organism group
organisms = pygame.sprite.Group()
# Initial spawner
for i in range(15):
temp = Organims(*Organism.initialSpawn())
organisms.add(temp)
虽然您的initialSpawn()
方法语法错误。除非指定了其他方法,否则类中的所有方法都需要self
作为第一个参数。我会把它变成一个类方法,而不是返回一堆用来创建一个新的有机体的变量,你只需要直接返回一个新的有机体。
class Organism(pygame.sprite.Sprite):
# Randomly generate traits for first generation
@classmethod
def initialSpawn(cls):
# Set dimensions for first generation
width = random.randrange(5,50)
height = random.randrange(5,50)
# Set starting point for first generation
x = random.randrange(0 + width, 800 - width)
y = random.randrange(0 + height, 800 - height)
# Set motion type for first generation
changeX = random.randrange(0,6)
changeY = random.randrange(0,6)
# Set lifespan for first generation
lifespan = random.randrange(300,700)
# Set species for first generation
species = random.choice(['paper', 'rock', 'scissors'])
if species == 'paper':
color = colors['red']
elif species == 'rock':
color = colors['green']
elif species == 'scissors':
color = colors['blue']
return cls(width, height, x, y, changeX, changeY, lifespan, species)
# Organism group
organisms = pygame.sprite.Group()
# Initial spawner
for i in range(15):
organisms.add(Organism.initialSpawn())
编辑:好的,我仔细查看了您的代码,并且您遇到了很多错误。
self
方法中的__init__
作为第一个参数。__init__
中,您有一个未识别的函数add(organisms)
。删除它。__init__
中,您根据条件创建color
变量但不使用它。相反,您尝试使用您不具备的属性self.color
。将变量color
更改为属性self.color
。__init__
,您正在尝试通过键入pygame.surface.Surface
来访问类Surface。没有模块surface
,类在pygame模块中。只需输入pygame.Surface
即可。@classmethod
添加装扮器cls
和InitialSpawn
。InitialSpawn
中,删除您设置颜色的if语句,因为您不需要它。它只是不必要的代码。update
中,在self.change_x
metod中将self.change_y
和self.changeX
更改为self.changeY
和reproduce
。始终如一。 update
中,将self.organisms
更改为organisms
。它是一个全局变量,而不是属性。update
中,mate
是未定义的变量。不知道你要做什么,所以我不知道如何解决这个问题。这些是我发现使用Pycharm的错误。在编码时更改为可以检测错误的IDE(如Pycharm),它将为您提供极大的帮助。