【问题标题】:Can you help me find my issue please? My variable is not changing after a collision你能帮我找到我的问题吗?碰撞后我的变量没有改变
【发布时间】:2015-03-03 11:29:47
【问题描述】:

我仍然是初学者,我正在尝试更频繁地使用课程。我刚刚遇到了一个问题,我已经尝试了好几个小时。当敌人攻击我的星球时,我的星球的价值应该下降多少舰队的价值。如果我的星球的价值低于0,我的星球应该成为敌人的星球。但是,当敌人的舰队与我的星球相撞时,我的星球的价值上升,而所有者变量保持不变。我相信我的错误出在我的舰队类的更新函数中。我试图从代码中输出很多打印语句,这样我就可以在每个循环中看到每个变量的状态。结果,玩家的星球并没有改变所有者,但我确实看到星球的价值下降了。另外,如果你们有任何建议可以帮助我解决其他问题,我将不胜感激。哦,我知道我的颜色是硬编码的,这是暂时的。

import sys
import math
import pygame

screen_size = (640, 480)
fps = 60

class Planet(pygame.sprite.Sprite):
    ''''''

    def __init__(self, x, y, value, owner = 'free', color = (0, 0, 255)):
        pygame.sprite.Sprite.__init__(self)

        self.image = pygame.Surface((32, 32))
        self.image.fill(color)
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y
        self.value = value
        self.owner = owner
        self.color = color

        self.grow = False
        self.selected = False
        self.text = str(self.value)

    def update(self):
        if self.grow == True:
            self.value += 1
            self.grow = False
        self.text = str(self.value)
        if self.owner == 'player':
            color = (0, 255, 0)
        elif self.owner == 'free':
            color = (0, 0, 255)
        elif self.owner == 'enemy':
            color = (255, 0, 0)
        if self.selected:
            color = (255, 0, 255)
        self.image.fill(color)

    def drawValue(self):
        textToScreen(screen, self.text, self.rect.centerx, self.rect.centery)

class Fleet(pygame.sprite.Sprite):

    def __init__(self, x, y, value, owner, home, target):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface((16, 16))
        self.image.fill((255, 0, 0))
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y
        self.value = value
        self.owner = owner
        self.text = str(self.value)
        self.home = home
        self.target = target
        self.speed = 2

    def update(self):
        self.text = str(self.value)

        for planet in playerplanets: #fleet collision with
            if planet.rect.collidepoint(self.rect.x, self.rect.y):
                if self.home != planet.rect:
                    if self.owner == 'player':
                        planet.value += self.value
                    elif self.owner == 'enemy':
                        planet.value -= self.value
                        if planet.value <= 0:
                            playerplanets.remove(planet)
                            planet.owner = 'enemy'
                            enemyplanets.add(planet)
                            #planet.value = planet.value - (planet.value * 2)
                    self.kill()

        for planet in freeplanets:
            if planet.rect.collidepoint(self.rect.x, self.rect.y):
                planet.value -= self.value
                if planet.value <= 0:
                    planet.value = planet.value - (planet.value * 2)
                    freeplanets.remove(planet)
                    if self.owner == 'player':
                        planet.owner = 'player'
                        playerplanets.add(planet)
                    elif self.owner == 'enemy':
                        planet.owner = 'enemy'
                        enemyplanets.add(planet)
                self.kill()

        for planet in enemyplanets:
            if planet.rect.collidepoint(self.rect.x, self.rect.y):
                if self.home != planet.rect:
                    planet.value -= self.value
                    if planet.value <= 0:
                        planet.value = planet.value - (planet.value * 2)
                        enemyplanets.remove(planet)
                        planet.owner = 'player'
                        playerplanets.add(planet)


        dx, dy = self.rect.centerx - self.target[0], self.rect.centery - self.target[1]
        dist = math.hypot(dx, dy)
        if dist == 0:
            dist = 1
        else:
            dx, dy = dx / dist, dy / dist
        self.rect.centerx -= dx * self.speed
        self.rect.centery -= dy * self.speed



    def drawValue(self):
        textToScreen(screen, self.text, self.rect.centerx, self.rect.centery)


def main():
    global screen, clock, timer, homeplanets, playerplanets, freeplanets, enemyplanets, allplanets, playerfleets, enemyfleets, allfleets
    pygame.init()

    screen = pygame.display.set_mode((screen_size), 0)
    clock = pygame.time.Clock()
    timer = 0

    homeplanets = pygame.sprite.Group()
    playerplanets = pygame.sprite.Group()
    freeplanets = pygame.sprite.Group()
    enemyplanets = pygame.sprite.Group()
    allplanets = pygame.sprite.Group()

    playerfleets = pygame.sprite.Group()
    enemyfleets = pygame.sprite.Group()
    allfleets = pygame.sprite.Group()

    background = (200, 200, 200)

    planet01 = Planet(50, 50, 100, 'player', (0, 255, 0))
    planet02 = Planet(100, 200, 50, 'free', (0, 0, 255))
    planet03 = Planet(300, 100, 200, 'enemy', (255, 0, 0))


    homeplanets.add(planet01)
    playerplanets.add(planet01)
    allplanets.add(planet01)

    freeplanets.add(planet02)
    allplanets.add(planet02)

    enemyplanets.add(planet03)
    allplanets.add(planet03)


    while True:

        processTimer()
        processInput()
        processAI()

        allplanets.update()
        allfleets.update()

        screen.fill(background)
        allplanets.draw(screen)
        allfleets.draw(screen)

        for planet in allplanets:
            planet.drawValue()
        for fleet in allfleets:
            fleet.drawValue()


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

        #TEST
        for planet in allplanets:
            print planet.owner

def processTimer():
    global timer
    timer += 1
    if timer == 100:
        for planet in allplanets:
            planet.grow = True
        timer = 0

def processInput():
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                pygame.quit()
                sys.exit()
        elif event.type == pygame.MOUSEBUTTONDOWN:
            mousex, mousey = pygame.mouse.get_pos()
            if event.button == 1:
                processLeftClicked(mousex, mousey)
            elif event.button == 3:
                processRightClicked(mousex, mousey)

def processAI():
    for eplanet in enemyplanets:
        if eplanet.value > 10:
            for pplanet in playerplanets:
                if eplanet.value / 2 > pplanet.value + 10:
                    target = pplanet.rect.center
                    x = eplanet.rect.x
                    y = eplanet.rect.y
                    value = eplanet.value / 2
                    home = eplanet.rect

                    eplanet.value = eplanet.value / 2

                    fleet = Fleet(x, y, value, 'enemy', home, target)
                    enemyfleets.add(fleet)
                    allfleets.add(fleet)

def processLeftClicked(mousex, mousey):
    for planet in playerplanets:
        if planet.rect.collidepoint((mousex, mousey)):
            if planet.selected == True:
                planet.selected = False
            elif planet.selected == False:
                planet.selected = True

def processRightClicked(mousex, mousey):
    for planet_ in allplanets:
        if planet_.rect.collidepoint((mousex, mousey)):
            planet_.selected = False
            target = planet_.rect.center
            for planet in playerplanets:
                if planet.selected == True:
                    if planet.value != 0:
                        x = planet.rect.x
                        y = planet.rect.y
                        value = planet.value / 2
                        home = planet.rect
                        if value == 0:
                            value = 1

                        planet.value = planet.value / 2

                        fleet = Fleet(x, y, value, 'player', home, target)
                        playerfleets.add(fleet)
                        allfleets.add(fleet)



def textToScreen(screen, text, x = 100, y = 100, text_size = 15, text_color = (0, 0, 0), font_type = 'freesans.ttf'):
    try:    
        font = pygame.font.SysFont(font_type, text_size)
        text = str(text)
        text = font.render(text, True, text_color)
        text_rect = text.get_rect()
        text_rect.centerx = x
        text_rect.centery = y
        screen.blit(text, (text_rect))

    except Exception as exception:
        print('Font Error')
        raise exception


if __name__ == '__main__':
    main()

【问题讨论】:

  • 您确实需要自己尝试缩小范围。放入一些打印语句并大致找出问题所在。如果您可以缩小范围,并对一小段代码中发生的事情有疑问,请告诉我们。
  • planet.value = planet.value - (planet.value * 2) 可以更清楚地重写为 planet.value = -planet.value
  • 我认为问题在于您将它添加到enemyplanets 列表中,但是当您处理enemyplanets 时,它现在位于该列表中,因此它会再次添加回 playerplanets。换句话说,它在一次更新中被处理两次。在行星上添加某种标志,表示它已经被处理过
  • 好的,我会继续努力的。我目前正在尝试将所有碰撞从 collidepoint 更改为 pygame.sprite.collide_rect
  • @samgak 谢谢!!!!> 答案就是这样!

标签: python pygame sprite collision


【解决方案1】:

问题是您将它添加到enemyplanets 列表中,但是当您处理enemyplanets 时,它现在位于该列表中,因此它会再次添加回 playerplanets。换句话说,它在一次更新中被处理两次。在行星上添加某种标志,表示它已经被处理过。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-03-01
    • 1970-01-01
    • 2020-09-03
    • 1970-01-01
    • 1970-01-01
    • 2021-02-04
    • 1970-01-01
    • 2019-09-13
    相关资源
    最近更新 更多