尝试生成n个不重叠的精灵;pygame崩溃

0 投票
1 回答
30 浏览
提问于 2025-04-12 14:05

我刚开始学习PyGame(两天前才开始),现在想做一个游戏,里面会随机生成一些浆果在我的岛上。

我理想中的算法是:

  1. 生成一个固定的浆果灌木
  2. 检查这个灌木是否和我之前生成的浆果有重叠
  3. 如果有重叠,就删除这个灌木,生成一个没有重叠的

我为genBerries函数写了下面的代码:

def genBerries(xRange, yRange, bushCount):  
    sucSpawns = 0
    berries = []
    while sucSpawns < bushCount:  # while you've spawned less than you want to
        spawnX = random.randint(xRange[0], xRange[1])  # randomise x coordinate for berry bush
        spawnY = random.randint(yRange[0], yRange[1])  # randomise y coordinate for berry bush
        berry = Berry(10, 5, 3, spawnX, spawnY)  # make a berry at this x and y
        for j in berries:
            collide = berry.rect.colliderect(j)  # check if berry colliding with some other berry
            if collide:
                berry.kill()  # if it is, get rid of it (and while loop will let u try again)
            else:
                sucSpawns += 1
                berries.append(berry)  # add this berry to the list of berries you've spawned successfully

xRange = island.rect.left, island.rect.right - 96  # defining x range berries can spawn in
yRange = (island.rect.top + 96, island.rect.bottom)  # defining y range berries can spawn in
bushCount = math.floor(random.normalvariate(conf['bA'], conf['bA']/5))  # defining how many berries spawn

genBerries(xRange, yRange, bushCount)

但是,一旦我这样做...

不响应

似乎出现了一种堆栈溢出(哈哈),这意味着这个过程没有结束??然后就黑屏了??

如果我把碰撞检查的部分注释掉,虽然会重叠,但结果是我想要的: 重叠的浆果

1 个回答

1

当你发现有物体碰撞时,应该立刻退出循环,并且只允许把这个物体放入列表一次,而不是对每一个没有碰撞的物体都放一次:

while len(berries) < bushCount:
    spawnX = random.randint(xRange[0], xRange[1]) 
    spawnY = random.randint(yRange[0], yRange[1])
    berry = Berry(10, 5, 3, spawnX, spawnY)
    collide = False 
    for testBerry in berries:
        collide = berry.rect.colliderect(testBerry.rect)
        if collide:
            berry.kill()
            break
    if collide == False:
        berries.append(berry)

你可以使用 collidelist() 来简化代码:

while len(berries) < bushCount:
    spawnX = random.randint(xRange[0], xRange[1]) 
    spawnY = random.randint(yRange[0], yRange[1])
    berry = Berry(10, 5, 3, spawnX, spawnY)
    collideIndex = berry.rect.collidelist(berries)
    if collideIndex == -1:
        berries.append(berry)
    else: 
        berry.kill()

下面是一个简单的例子:

import pygame
import random

pygame.init()
window = pygame.display.set_mode((400, 400))
clock = pygame.time.Clock()

bushCount = 4
berries = []
xRange = [100, 300]
yRange = [100, 300]

berrGroup = pygame.sprite.Group()
class Berry(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__()
        self.image = pygame.Surface((40, 40))
        self.image.fill((255, 0, 0))
        self.rect = self.image.get_rect(center = (x, y))
        berrGroup.add(self)

run = True
while run:
    clock.tick(5)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False 
    
    berrGroup.empty()
    berries.clear()
    while len(berries) < bushCount:
        spawnX = random.randint(xRange[0], xRange[1]) 
        spawnY = random.randint(yRange[0], yRange[1])
        berry = Berry(spawnX, spawnY)
        collideIndex = berry.rect.collidelist(berries)
        if collideIndex == -1:
            berries.append(berry) 
        else: 
            berry.kill()

    window.fill(0)
    berrGroup.draw(window)
    pygame.display.flip()

pygame.quit()
exit()

撰写回答