有没有办法简化这个 pygame 代码?

Is there a way to simplify this pygame code?

我对pygame有点陌生,我不知道有没有办法简化这个,如果你能在绘图时改变颜色也很好。我已经尝试过实现它,但找不到让它工作的方法。它基本上是一个简单的像素艺术游戏:

import pygame
from sys import exit


def MousePos():
    mouse_pos = pygame.mouse.get_pos()
    return mouse_pos[0] // grid_size, mouse_pos[1] // grid_size


def DrawGrid():
    for x in range(0, WIDTH, grid_size):
        for y in range(0, HEIGHT, grid_size):
            rect = pygame.Rect(x, y, grid_size, grid_size)
            pygame.draw.rect(screen, "Black", rect, 1)


def DrawSquare():
    mouse_buttons = pygame.mouse.get_pressed()
    if mouse_buttons[0] and MousePos() not in pressed:
        pressed.append(MousePos())
    if mouse_buttons[1] and MousePos() not in pressed:
        pressed.clear()
    if mouse_buttons[2] and MousePos() in pressed:
        pressed.remove(MousePos())
    for coordinates in pressed:
        rectangle = pygame.Rect(coordinates[0]*grid_size, coordinates[1]*grid_size, grid_size, grid_size)
        pygame.draw.rect(screen, "Black", rectangle)
    cursor = pygame.Rect(MousePos()[0]*grid_size, MousePos()[1]*grid_size, grid_size, grid_size)
    pygame.draw.rect(screen, "Grey", cursor)


pygame.init()
clock = pygame.time.Clock()

WIDTH = 800
HEIGHT = 400
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("PixelArt!")

grid_size = 25
pressed = []
pygame.mouse.set_visible(False)

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            exit()

    screen.fill("White")

    MousePos()
    DrawGrid()
    DrawSquare()

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

编辑: 也许这个问题应该在类似的门户网站上继续 Code Review or Game Development


我一直在变量中绘制颜色并使用键来更改它。

1 = Red2 = Green3 = Blue0 = Black

但现在它需要用 pos 保留 color - 我使用字典 pressed[pos] = color

但也许您应该为网格中的所有方块创建完整的二维列表,而不是 pressed,并在开始时将 White 放在所有位置。如果您将颜色设置为元组,即 (255,0,0) 而不是字符串 Red 那么您可以将其保存在 numpy.array 中并简单地保存在文本文件中或将 numpy.array 转换为 Pillow.Image 和另存为 JPG/PNG/TIFF.

因为现在它可以绘制不同的颜色所以当我按下第一个按钮时我不检查是否 pos not in pressed 因为它不允许替换正方形的颜色。


没有那么多要简化的。

DrawSquare() 中你 运行 MousePos() 很多次但你可以 运行 它一次并分配给变量。

您可以使用 x, y = ... 代替 pos = ...pos[0]pos[1]
或者您可以同时使用 x, y = pos = ....

您可以在开始时创建 cursor = Rect(...),然后使用 cursor.topleft = new_position 移动它。

也许在 draw.rect(...) 中你可以直接使用元组 (x, y, width, height) 而不是 Rect(x, y, width, height)


我使用了 PEP 8 -- Style Guide for Python Code

中的规则
  • lower_case_names 函数名称
  • verbs 用于函数名称 - convert 而不是 MousePos
    (变量 nouns 和 类)

完整代码:

import pygame
from sys import exit

# --- constants ---  # PEP8: `UPPER_CASE_NAMES`

WIDTH = 800
HEIGHT = 400

SQUARE_SIZE = 25

# --- classes ---   # PEP8: `CamelCaseNames`

# empty

# --- functions ---  # PEP8: `lower_case_names` 

def convert_pos(pos):
    x, y = pos
    return (x // SQUARE_SIZE, y // SQUARE_SIZE)

def draw_grid():
    for x in range(0, WIDTH, SQUARE_SIZE):
        for y in range(0, HEIGHT, SQUARE_SIZE):
            rect = pygame.Rect(x, y, SQUARE_SIZE, SQUARE_SIZE)
            pygame.draw.rect(screen, "Black", rect, 1)

def draw_square():
    mouse_buttons = pygame.mouse.get_pressed()

    mouse_pos = pygame.mouse.get_pos()
    
    grid_x, grid_y = grid_pos = convert_pos(mouse_pos)

    cursor.topleft = (grid_x*SQUARE_SIZE, grid_y*SQUARE_SIZE)
    
    if mouse_buttons[0]:
        pressed[grid_pos] = draw_color
        
    if mouse_buttons[1]: # and grid_pos not in pressed:
        pressed.clear()
        
    if mouse_buttons[2] and grid_pos in pressed:
        #del pressed[grid_pos]
        pressed.pop(grid_pos)

    for (x, y), color in pressed.items():
        rectangle = pygame.Rect(x*SQUARE_SIZE, y*SQUARE_SIZE, SQUARE_SIZE, SQUARE_SIZE)
        pygame.draw.rect(screen, color, rectangle)
    
    pygame.draw.rect(screen, "Grey", cursor)

# --- main ---

pygame.init()
                         
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("PixelArt!")

pygame.mouse.set_visible(False)

pressed = {}  # dictionary for `pressed[position] = color

cursor = pygame.Rect(0, 0, SQUARE_SIZE, SQUARE_SIZE)

draw_color = 'Black'

# - mainloop -

clock = pygame.time.Clock()

while True:

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            exit()

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_1:
                draw_color = 'Red'         
            elif event.key == pygame.K_2:
                draw_color = 'Green'         
            elif event.key == pygame.K_3:
                draw_color = 'Blue'         
            elif event.key == pygame.K_0:
                draw_color = 'Black'         

    # - draw -
 
    screen.fill("White")

    draw_grid()
    draw_square()

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