PyGame模拟不会呈现

时间:2016-12-10 23:39:32

标签: python pygame

我正在使用自然选择模拟器。我之前已经问了一个与之相关的问题(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()

1 个答案:

答案 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())

编辑:好的,我仔细查看了您的代码,并且您遇到了很多错误。

  1. 需要将self方法中的__init__作为第一个参数。
  2. __init__中,您有一个未识别的函数add(organisms)。删除它。
  3. __init__中,您根据条件创建color变量但不使用它。相反,您尝试使用您不具备的属性self.color。将变量color更改为属性self.color
  4. __init__,您正在尝试通过键入pygame.surface.Surface来访问类Surface。没有模块surface,类在pygame模块中。只需输入pygame.Surface即可。
  5. 像上面一样为@classmethod添加装扮器clsInitialSpawn
  6. InitialSpawn中,删除您设置颜色的if语句,因为您不需要它。它只是不必要的代码。
  7. update中,在self.change_x metod中将self.change_yself.changeX更改为self.changeYreproduce。始终如一。
  8. update中,将self.organisms更改为organisms。它是一个全局变量,而不是属性。
  9. update中,mate是未定义的变量。不知道你要做什么,所以我不知道如何解决这个问题。
  10. 这些是我发现使用Pycharm的错误。在编码时更改为可以检测错误的IDE(如Pycharm),它将为您提供极大的帮助。