如何在pygame中的类中使用while循环?

时间:2015-01-24 15:46:18

标签: python while-loop pygame instance instantiation

当我点击鼠标并慢慢淡出时,我试图让一个实例类(Block)产生,并且我希望能够产生无限数量的淡出块,只要点击鼠标即可足够快。

为此,我想在第一次生成实例时启动fade()函数,并将tick设置为255并将alpha设置为ticks。

然而,当使用while循环时,该函数在不更新显示的情况下自行完成,因为程序被限制为fade()函数中的while循环。

有人可以帮助我为每个实例调用淡入淡出函数255次吗?

import pygame,sys,time,Blockm
from pygame.locals import *
black,white=(0,0,0),(255,255,255)
size=w,h=1400,800
screen=pygame.display.set_mode(size)
pygame.init()

class Block(object):

    sprite = None

    def __init__(self, x, y):
        if not Block.sprite:
            Block.sprite = pygame.image.load("Block.png").convert_alpha()
        self.rect = Block.sprite.get_rect(top=y, left=x)
        self.fade()

    def fade(self):
        ticks=255
        Block.sprite.set_alpha(ticks)
        while ticks!=0:
            ticks-=1
            print(ticks)



while True:
    blocks = []
    mmraw=pygame.mouse.get_pos()
    mmx,mmy=mmraw[0]-(pygame.image.load("Block.png").get_width())/2,mmraw[1]-(pygame.image.load("Block.png").get_width())/2
    for event in pygame.event.get():
        if event.type== pygame.QUIT:
            pygame.quit()
            sys.exit()
        if event.type == pygame.MOUSEBUTTONDOWN:
            print('click')
            blocks.append(Block(mmx,mmy))

    for block in blocks:
        screen.blit(block.sprite, block.rect)
        print('trying to blit')
        print(Block.sprite.get_offset())
    pygame.display.update()

2 个答案:

答案 0 :(得分:1)

您可能想要使用threads。这些允许您一次运行多个事物。对于您的代码,请按以下方式进行更改:

from threading import Thread
import pygame, sys, time, Blockm
from pygame.locals import *
black = (0,) * 3
white = (255,) * 3
size = w, h = 1400, 800
screen = pygame.display.set_mode(size)
pygame.init()

class Block(object):

    sprite = None

    def __init__(self, x, y):
        if not Block.sprite:
            Block.sprite = pygame.image.load("Block.png").convert_alpha()
        self.rect = Block.sprite.get_rect(top=y, left=x)
        Thread(target=self.fade) # Made this a Thread so it runs separately.

    def fade(self):
        for tick in range(255, 0, -1):
            Block.sprite.set_alpha(tick)
            print(tick)


def game():
    while True:
        # The contents of that while True loop at the end


def main():
    Thread(target=Main)


if __name__ == "__main__":
    main()

这也为您的程序添加了一个缺少的入口点。此外,Block.fade实际上并不会做你想要的,因为你只set_alpha一次。我用for循环来修复它。另外,请注意,您现在可以return打破整个游戏。

答案 1 :(得分:1)

我有一个适合你的解决方案应该达到你想要的目标,但我承认并没有完全按照要求回答问题。

您可能遇到的第一个也是最令人阻碍的问题是,您需要使用pygame.image.load("Block.png").convert()而不是pygame.image.load("Block").convert_alpha(),因为.convert_alpha()不能与.set_alpha(..)一起使用。 由于screen未在update之前刷新,因此您可能无法注意到任何解决方案中的块何时淡入淡出。新的,褪色的街区正在被吸引到更加明亮的地方。那些,没有产生差异(尽管有重叠的块)。我在下面的解决方案代码中添加了一个权宜之计,用蓝色填充屏幕,但我想你会想要一些与众不同的东西。它标有评论。

我建议让每个Block在你的for block in blocks:块中的主循环调用期间在本地处理其alpha值。这个版本的代码应该可以提供你想要的结果,虽然它只使用主循环,而不是像你要问的并行循环......

import pygame,sys,time,Blockm
from pygame.locals import *
black,white=(0,0,0),(255,255,255)
size=w,h=1400,800
screen=pygame.display.set_mode(size)
pygame.init()

class Block(object):

    sprite = None

    def __init__(self, x, y):
        if not Block.sprite:
            Block.sprite = pygame.image.load("Block.png").convert()
            # ^  MODIFIED: .convert_alpha() won't recognize the effects of .set_alpha(), so use regular .convert() instead.
        self.rect = Block.sprite.get_rect(top=y, left=x)
        self.ticks = 255 # NEW: Set a local tick count.
        # REMOVED `self.fade()`: This runs on main now.

    def fade(self):
        ## REPURPOSED METHOD: Runs each frame that the Block is active. Called on main loop.
        # MODIFIED BLOCK: Update local tick count before setting the class's sprite alpha.
        self.ticks -= 1
        Block.sprite.set_alpha(self.ticks) # MOVED, MODIFIED: uses local tick count for alpha.
        print(self.ticks) # UPDATED: Using local ticks.


blocks = [] # MOVED: Make a list for the Blocks, but don't clear it on frame.
while True:    
    mmraw=pygame.mouse.get_pos()
    mmx,mmy=mmraw[0]-(pygame.image.load("Block.png").get_width())/2,mmraw[1]-(pygame.image.load("Block.png").get_width())/2
    # ^  There may be a tidier way of doing this. Described in solution body...
    for event in pygame.event.get():
        if event.type== pygame.QUIT:
            pygame.quit()
            sys.exit()
        if event.type == pygame.MOUSEBUTTONDOWN:
            print('click')
            blocks.append(Block(mmx,mmy))

    screen.fill((22,22,222))
    # ^  NEW: Fill the screen with some backdrop so that the erasure is obvious!
    #         If you don't do this, you'll be blitting faded images over brighter ones and there will be no real change!!
    for block in blocks:
        block.fade()    # NEW: Update this block.
        if block.ticks < 1: # NEW BLOCK: If the block has become invisible...
            blocks.remove(block) # NEW: Expunge this invisible block.
            continue # NEW: Immediately move on to the next block.
        screen.blit(Block.sprite, block.rect)
        print('trying to blit')
        print(Block.sprite.get_offset())
    pygame.display.update()

它有一个小问题,即消失的块会触发闪烁&#39;在其他剩余的块中(或者至少是blocks中的下一个块),我不知道为什么或如何。


在我看的时候,我发现了一些你可能想要考虑的事情:

...在class Block:中:

- 使用sprite = pygame.image.load("Block.png").convert()代替sprite = None。这样,您可以使用mmx,mmy = mmraw[0] - Block.sprite.get_rect.centerx, mmraw[1] - Block.sprite.get_rect().centery之类的内容,而不是暂时加载图像,只是为了知道它的大小。由于所有Block都使用相同的图形,因此它不应该有所不同,这样,如果在运行时更改Block.sprite,则不必重新获取偏移量!< / p>

- 将Block精灵的副本分配给每个实例,而不是使用类的Surface。这会占用更多的处理能力,但只是暂时用作return而不是class Block(object): ... def fade(self): sprite = Block.sprite.copy() sprite.set_alpha(self.ticks) self.ticks -= 1 return sprite ... while True: # main loop ... for block in blocks: screen.blit(block.fade(), block.rect) # Although there are more Pythonic ways of writing this. 。例如:

screen.blit(sprite, self.rect)

或者,您可以在Block.fade()中使用fade而不是使用主要内容,并完全放弃退货。由于alpha是在本地设置的,因此每次Block运行时都不会重置sprite未绑定{{1}}可以保持新鲜!

无论如何,我希望这可以解决你的问题,即使它没有(完全)回答你的问题!