简体   繁体   English

使 object 特征可继承

[英]Make object traits inheritable

I'm making a natural selection simulator program.我正在制作一个自然选择模拟器程序。 One of the things I want to happen is when two parent objects collide for an offspring object to be created that randomly inherits some of its parents traits.我想要发生的事情之一是,当两个父对象发生碰撞时,将创建一个随机继承其父对象某些特征的后代 object。 In particular, I'm looking to pass on the int values width and height.特别是,我希望传递 int 值宽度和高度。 The problem is, I'm only looking to pass on width and height into the object when it is offspring.问题是,我只想在 object 成为后代时将宽度和高度传递给它。 I want the initial spawn of parent objects to have completely randomized values.我希望父对象的初始生成具有完全随机的值。

My whole code is:我的整个代码是:

import pygame, random

pygame.init()

map_width = 800
map_height = 800
size = [map_width, map_height]
screen = pygame.display.set_mode(size)

# pygame already defines a lot of colors, we we just use them
colors = pygame.color.THECOLORS
pygame.display.set_caption("Natural Selection Game")
done = False
clock = pygame.time.Clock()

# just a simple generator to generate an id for each object 
def id_generator():
    i = 0
    while True:
        i += 1
        yield i

ids = id_generator()

# just a helper function that wraps pygame.sprite.collide_mask
# to prevent a sprite from colliding with itself
def collide(a, b):
    if a.id == b.id:
        return False
    return pygame.sprite.collide_mask(a, b)

class Organism(pygame.sprite.Sprite):

    def __init__(self, id, org_list, width, height, color = None):
        pygame.sprite.Sprite.__init__(self, org_list)
        self.org_list = org_list
        self.id = id
        # Speed and direction
        self.change_x = random.randrange(0,6)
        self.change_y = random.randrange(0,6)

        # Dimensions
        self.width = width or random.randrange(20,60)
        self.height = height or random.randrange(20,60)

        x = random.randrange(0 + width, map_width - width )
        y = random.randrange(0 + height, map_height - height)
        self.rect = pygame.rect.Rect(x, y, width, height)
        self.image = pygame.surface.Surface((width, height))
        self.image.fill(colors['hotpink2'])
        self.image.set_colorkey(colors['hotpink2'])

        # we either pass in the color, or create a random one
        self.color = color or random.choice([colors['red'], colors['green'], colors['blue']])
        pygame.draw.ellipse(self.image, self.color, [0, 0, width, height])
        self.mask = pygame.mask.from_surface(self.image)

        # we keep track of collisions currently happening
        # so we only spawn one children for each collisions  
        self.collisions = set()

        # just something to limit the number of organisms
        self.age = 0
        self.children = 0

    # Initiate movement
    def update(self):
        self.age += 1

        # we move by simply moving the rect
        # the Group's draw function will look that the rect attribute 
        # to determine the position for drawing the image 
        self.rect.move_ip(self.change_x, self.change_y)

        # we can make use of a lot of Rect's attributes to make 
        # this computation simpler
        if self.rect.left < 0 or self.rect.right > map_width:
            self.change_x *= -1

        if self.rect.top < 0 or self.rect.bottom > map_height:
            self.change_y *= -1

        # only reproduce if we are at least 200 ticks old
        # so newly created organisms spwan new ones at the
        # very moment they spawned themself
        if self.age < 200:
            return

        # just an arbitary limit so the screen does not get too full
        if self.age > 500:
            print (self.id, ' died of age')

            # kill() removes the Sprite from all its Groups (which is only org_list at the moment)
            self.kill()
            return

        # just an arbitary limit so the screen does not get too full 
        if self.children > 4:
            print (self.id, ' died of too many children')
            self.kill()
            return

        # check if we collided with another Sprite
        collided = pygame.sprite.spritecollideany(self, self.org_list, collide)

        # also check if this 
        # - is a new collision
        # - the other organism is at least 200 ticks old
        # - there are not too many organisms at the screen at the moment
        if collided and not collided.id in self.collisions and collided.age > 200 and len(self.org_list) < 100:

            # keep track of the current collision, so this code is not triggerd 
            # every frame while the colliding organisms move other each other
            self.collisions.add(collided.id)
            collided.collisions.add(self.id)
            print (self.id, ' collided with ', collided.id)

            # inherit parent dimensions
            width = random.choice(self.width, collided.width)
            height = random.choice(self.height, collided.height)

            # let the dimensions mutate sometimes for fun
            if random.randrange(0, 100) < 5:
                width = random.randrange(5, 100)
                print ('Offspring of', self.id, ' and ', collided.id, ' mutates a dimension change')
            elif random.randrange(0, 100) < 5:
                height = random.randrange(5, 100)    
                print ('Offspring of', self.id, ' and ', collided.id, ' mutates a dimension change')
            elif random.randrange(0, 100) < 5:
                width = random.randrange(5, 100)
                height = random.randrange(5, 100)  
                print ('Offspring of', self.id, ' and ', collided.id, ' mutates a dimension change')

            # let the color mutate sometimes for fun
            if random.randrange(0, 100) < 5:
                color[random.randrange(0, 3)] = random.randrange(0, 256)
                print ('Offspring of', self.id, ' and ', collided.id, ' speciates')

            # create the new child with the new color
            Organism(next(ids), self.org_list, list(map(int, color)))
            self.children += 1
            collided.children += 1
        else:
            # if there are currently no collisions, we clear the collisions set
            # so new collisions can happen
            self.collisions = set()

# we use a Group for all the draw/update/collision magic
org_list = pygame.sprite.Group()

for _ in range(15):
    Organism(next(ids), org_list)

while not done:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True

    # we just call update on the group so update is called
    # an every sprite in the group
    org_list.update()

    screen.fill(colors['white'])

    # same for drawing: just call draw on the group
    org_list.draw(screen)

    clock.tick(60)
    pygame.display.flip()

pygame.quit()

Again, specifically, I'm looking to pass on width and height when there are parents with width and height, but in the initial genesis spawn when there have been no parents, I want those values to have been randomly generated.再次,具体来说,当有具有宽度和高度的父母时,我希望传递宽度和高度,但是在没有父母的初始创世纪中,我希望这些值是随机生成的。

Actually, the constructor of the class organism has a width and a height argument and these then set the attributes self.width and self.height with them if they are not empty ( None ) and if they are, they are set by random values:实际上,class organism的构造函数有一个width和一个height参数,如果它们不为空( None ),然后用它们设置属性self.widthself.height ,如果它们是,则由随机值设置:

 class Organism(pygame.sprite.Sprite): def __init__(self, id, org_list, width, height, color = None): pygame.sprite.Sprite.__init__(self, org_list) self.width = width or random.randrange(20,60) self.height = height or random.randrange(20,60) # [...]

Therefore, if you want random values, you must pass None to these arguments:因此,如果你想要随机值,你必须将None传递给这些 arguments:

for _ in range(15):
    Organism(next(ids), org_list, None, None)

Alternatively, you can pass concrete values, for example, the width and height of the parent:或者,您可以传递具体值,例如父级的宽度和高度:

class Organism(pygame.sprite.Sprite):
    # [...]

    def update(self):
        # [...]

        if collided and not collided.id in self.collisions and collided.age > 200 and len(self.org_list) < 100:
            # [...]

            Organism(next(ids), self.org_list, self.width, self.height, list(map(int, color)))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM