如何在 pygame 中的 class 中使用 while 循环?
How to use a while loop within a class in pygame?
我正在尝试创建一个实例 class(方块)在单击鼠标时生成并缓慢淡出,我希望能够生成无限数量的方块并淡出,前提是鼠标点击速度不够快。
为此,我想在第一次生成实例时启动 fade() 函数,并将刻度设置为 255,并将 alpha 设置为刻度。
但是,当使用 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()
您可能想使用 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
打破整个游戏。
我有一个解决方案可以满足您的要求,但我承认它没有完全按照要求回答问题。
您可能遇到的第一个也是最棘手的问题是您需要使用 pygame.image.load("Block.png").convert()
而不是 pygame.image.load("Block").convert_alpha()
,因为 .convert_alpha()
不适用于 .set_alpha(..)
.
也有可能您没有注意到块在任何解决方案中何时消失,因为 screen
在 update
之前没有被刷新。新的褪色块被绘制在 'brighter' 个块上,没有产生任何差异(尽管有重叠块)。我在下面的解决方案代码中添加了一个权宜之计,用蓝色填充屏幕,但我想您会想要一些不同的东西。它标有评论。
我建议让每个 Block
在从 for block in blocks:
块的主循环调用期间在本地处理它的 alpha,然后再 blit 它。这个版本的代码应该给你你想要的结果,尽管它只使用主循环,而不是像你问的那样并行循环...
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()
它有一个小问题,即消失的方块会触发其他剩余方块中的 'flicker'(或至少 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
,就不必重新获取偏移量!
-考虑将 Block
的精灵 copy 分配给每个实例,而不是使用 class 的表面。这将占用更多的处理能力,但如果您将其用作 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.
或者,您可以在 Block.fade()
中使用 screen.blit(sprite, self.rect)
而不是在 main 中使用 return 并完全放弃。因为alpha是本地设置的,所以不用每次fade
运行的时候都reset,Block
的unboundsprite
可以留着新鲜!
无论如何,我希望这能解决您的问题,即使它没有(准确)回答您的问题!
我正在尝试创建一个实例 class(方块)在单击鼠标时生成并缓慢淡出,我希望能够生成无限数量的方块并淡出,前提是鼠标点击速度不够快。
为此,我想在第一次生成实例时启动 fade() 函数,并将刻度设置为 255,并将 alpha 设置为刻度。
但是,当使用 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()
您可能想使用 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
打破整个游戏。
我有一个解决方案可以满足您的要求,但我承认它没有完全按照要求回答问题。
您可能遇到的第一个也是最棘手的问题是您需要使用 pygame.image.load("Block.png").convert()
而不是 pygame.image.load("Block").convert_alpha()
,因为 .convert_alpha()
不适用于 .set_alpha(..)
.
也有可能您没有注意到块在任何解决方案中何时消失,因为 screen
在 update
之前没有被刷新。新的褪色块被绘制在 'brighter' 个块上,没有产生任何差异(尽管有重叠块)。我在下面的解决方案代码中添加了一个权宜之计,用蓝色填充屏幕,但我想您会想要一些不同的东西。它标有评论。
我建议让每个 Block
在从 for block in blocks:
块的主循环调用期间在本地处理它的 alpha,然后再 blit 它。这个版本的代码应该给你你想要的结果,尽管它只使用主循环,而不是像你问的那样并行循环...
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()
它有一个小问题,即消失的方块会触发其他剩余方块中的 'flicker'(或至少 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
,就不必重新获取偏移量!
-考虑将 Block
的精灵 copy 分配给每个实例,而不是使用 class 的表面。这将占用更多的处理能力,但如果您将其用作 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.
或者,您可以在 Block.fade()
中使用 screen.blit(sprite, self.rect)
而不是在 main 中使用 return 并完全放弃。因为alpha是本地设置的,所以不用每次fade
运行的时候都reset,Block
的unboundsprite
可以留着新鲜!
无论如何,我希望这能解决您的问题,即使它没有(准确)回答您的问题!