pygame类结构
我的目标是制作一个模块,可以在pygame的画布上创建一个网格,并允许你通过x和y坐标来高亮显示某些方框。
下面是一个简单的使用示例。
from grid import Grid
g = Grid(100, 100, 10) # width and height in cells, cell width in pixels
g.highlightBox(2, 2, (0, 255, 0)) # cell x and y, rgb color tuple
g.clearGrid()
这是我目前写的代码。问题是,我需要一个事件循环来保持窗口打开,并让关闭按钮可以正常工作,但我也需要允许其他功能在屏幕上绘图。
import pygame
import sys
class Grid:
colors = {"blue":(0, 0, 255), "red":(255, 0, 0), "green":(0, 255, 0), "black":(0, 0, 0), "white":(255, 255, 255)}
def __init__(self, width, height, cellSize, borderWidth=1):
self.cellSize = cellSize
self.borderWidth = borderWidth
self.width = width * (cellSize + borderWidth)
self.height = height * (cellSize + borderWidth)
self.screen = pygame.display.set_mode((self.width, self.height))
running = True
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
def clearGrid(self):
pass
def highlightBox(self, x, y, color):
xx = x * (self.cellSize + self.borderWidth)
yy = y * (self.cellSize + self.borderWidth)
pygame.draw.rect(self.screen, color, (xx, yy, self.cellSize, self.cellSize), 0)
当我运行第一个示例时,代码会卡在循环里,直到循环结束(也就是按下退出按钮)之前,我无法运行highlightBox
函数。
3 个回答
1
我觉得你需要把网格类和它的显示分开。你应该让它生成一些表面(Surfaces),然后由主游戏循环来把这些表面打印到屏幕上。比如,你的init、highlight_cell和clear_grid方法可以返回这些表面,或者你可以创建一个get_surface方法,每次游戏循环时调用一次。
这样做会让你有更多的灵活性。
1
首先,我建议不要把游戏循环放在初始化函数里面;找个其他地方放它。要解决这个问题,只需把你想在游戏循环中执行的代码放在处理事件的代码旁边就可以了:
running = True
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
# Print your screen in here
# Also do any other stuff that you consider appropriate
0
我用 multiprocessing 库和管道搞出了一个可用的版本。虽然这看起来有点不太符合 Python 的风格,但对于这个项目来说是可以用的。
import pygame
import sys
from multiprocessing import Process, Pipe
class Grid:
colors = {"blue":(0, 0, 255), "red":(255, 0, 0), "green":(0, 255, 0), "black":(0, 0, 0), "white":(255, 255, 255)}
def __init__(self, width, height, cellSize, borderWidth=1):
self.cellSize = cellSize
self.borderWidth = borderWidth
self.width = width * (cellSize + borderWidth)
self.height = height * (cellSize + borderWidth)
#pygame.draw.rect(self.screen, todo[1], (todo[2], todo[3], todo[4], todo[5]), 0)
self.parent_conn, self.child_conn = Pipe()
self.p = Process(target=self.mainLoop, args=(self.child_conn, self.width, self.height,))
self.p.start()
def close():
self.p.join()
def clearGrid(self):
pass
def highlightBox(self, x, y, color):
xx = x * (self.cellSize + self.borderWidth)
yy = y * (self.cellSize + self.borderWidth)
self.parent_conn.send(["box", color, xx, yy, self.cellSize, self.cellSize])
def mainLoop(self, conn, width, height):
#make window
screen = pygame.display.set_mode((self.width, self.height))
running = True
while running:
# is there data to read
if conn.poll():
#read all data
todo = conn.recv()
print("Recived " + str(todo))
#do the drawing
if todo[0] == "box":
print("drawing box")
pygame.draw.rect(screen, todo[1], (todo[2], todo[3], todo[4], todo[5]), 0) #color, x, y, width, height
todo = ["none"]
#draw to screen
pygame.display.flip()
#get events
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False