首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >用吡咯制作的PixelArt

用吡咯制作的PixelArt
EN

Code Review用户
提问于 2022-02-28 20:36:53
回答 1查看 100关注 0票数 3

我对电子游戏有点陌生,我制作了这个简单的像素艺术游戏。是否有可能简化,是否有可能保存您的图纸并重新加载它们?

代码语言:javascript
复制
import pygame
from sys import exit


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


def DrawGrid():
    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 SelectColor():
    global draw_color
    mouse_pressed = pygame.mouse.get_pressed()
    bg = pygame.Rect(WIDTH, 0, SIDE, HEIGHT)
    pygame.draw.rect(screen, "Orange", bg)
    pygame.draw.rect(screen, "Purple", bg, 5)
    for item, color in enumerate(colors):
        select_color = pygame.Rect(0, 0, 120, 30)
        select_color.center = WIDTH+SIDE//2, HEIGHT*(item+1)/len(colors)-(HEIGHT/len(colors))/2
        pygame.draw.rect(screen, color, select_color)
        if select_color.collidepoint(pygame.mouse.get_pos()) and mouse_pressed[0]:
            draw_color = color
        if draw_color == color:
            pygame.draw.rect(screen, "DarkBlue", select_color, 5)


def DrawSquare():
    global draw_color
    mouse_pos = pygame.mouse.get_pos()
    mouse_pressed = pygame.mouse.get_pressed()
    grid_x, grid_y = grid_pos = ConvertPos(mouse_pos)
    cursor = (grid_x*SQUARE_SIZE, grid_y*SQUARE_SIZE, SQUARE_SIZE, SQUARE_SIZE)
    for (x, y), color in pressed.items():
        square = pygame.Rect(x*SQUARE_SIZE, y*SQUARE_SIZE, SQUARE_SIZE, SQUARE_SIZE)
        pygame.draw.rect(screen, color, square)
    if 0 < mouse_pos[0] < WIDTH-1 and 0 < mouse_pos[1] < HEIGHT-1:
        pygame.draw.rect(screen, draw_color, cursor, 3)
        if mouse_pressed[0]:
            pressed[grid_pos] = draw_color
        if mouse_pressed[2] and grid_pos in pressed:
            pressed.pop(grid_pos)
    if mouse_pressed[1]:
        pressed.clear()


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

WIDTH = 800
SIDE = 200
HEIGHT = 400
MARGIN = 50
SQUARE_SIZE = 25
screen = pygame.display.set_mode((WIDTH+SIDE, HEIGHT))
pygame.display.set_caption("PXLART")

pressed = {}
colors = ["Black", "Blue", "Green", "Red", "Pink", "Yellow", "White", "DarkGreen", "Brown", "Grey", "Cyan"]
draw_color = "Black"

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

    screen.fill("White")

    DrawGrid()
    SelectColor()
    DrawSquare()

    pygame.display.update()
    clock.tick(60)
EN

回答 1

Code Review用户

回答已采纳

发布于 2022-03-01 02:11:51

对于其他方法,ConvertPos应该是convert_pos等,这是由于PEP8。

不要保持全球状态。有几种选择,一个类是最简单的。

将鼠标操作与绘图分开,不要保留时钟或“框架循环”。您没有任何动画,所以使用事件循环代替。这比浪费要少得多。换句话说,每秒60次,如果用户完全没有发生任何事情,程序应该等待一个新的事件,而不是通过数百次抽签调用。

添加PEP484类型提示。

增加一个__main__守卫。

不要在程序终止时使用exit() --这对您的调用者不是很好,只需返回即可。

更典型的做法是在外部循环中使用y,而不是内部循环--这将产生与打字机相同的模式(左、右、上、下、慢)。

建议

代码语言:javascript
复制
import pygame
from pygame.event import Event

WIDTH = 800
SIDE = 200
HEIGHT = 400
MARGIN = 50
SQUARE_SIZE = 25
COLOURS = (
    "Black", "Blue", "Green", "Red", "Pink", "Yellow",
    "White", "DarkGreen", "Brown", "Grey", "Cyan",
)


def convert_pos(pos: tuple[int, int]) -> tuple[int, int]:
    x, y = pos
    return x//SQUARE_SIZE, y//SQUARE_SIZE


class Game:
    def __init__(self) -> None:
        pygame.display.set_caption("PXLART")

        self.screen: pygame.Surface = pygame.display.set_mode((WIDTH + SIDE, HEIGHT))
        self.pressed: dict[tuple[int, int], str] = {}
        self.draw_color = "Black"

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

    def draw_select_colour(self) -> None:
        background = pygame.Rect(WIDTH, 0, SIDE, HEIGHT)
        pygame.draw.rect(self.screen, "Orange", background)
        pygame.draw.rect(self.screen, "Purple", background, 5)

        for item, colour in enumerate(COLOURS):
            select_colour = pygame.Rect(0, 0, 120, 30)
            select_colour.center = (
                WIDTH + SIDE/2,
                HEIGHT/len(COLOURS)*(item + 0.5)
            )
            pygame.draw.rect(self.screen, colour, select_colour)

            if self.draw_color == colour:
                pygame.draw.rect(self.screen, "DarkBlue", select_colour, 5)

    def draw_square(self) -> None:
        mouse_x, mouse_y = mouse_pos = pygame.mouse.get_pos()
        grid_x, grid_y = convert_pos(mouse_pos)
        cursor = (grid_x*SQUARE_SIZE, grid_y*SQUARE_SIZE, SQUARE_SIZE, SQUARE_SIZE)

        for (x, y), color in self.pressed.items():
            square = pygame.Rect(x*SQUARE_SIZE, y*SQUARE_SIZE, SQUARE_SIZE, SQUARE_SIZE)
            pygame.draw.rect(self.screen, color, square)

        if 0 < mouse_x < WIDTH-1 and 0 < mouse_y < HEIGHT-1:
            pygame.draw.rect(self.screen, self.draw_color, cursor, 3)

    def handle_mouse(self, pos: tuple[int, int], left: bool, middle: bool, right: bool) -> None:
        mouse_x, mouse_y = pos
        if 0 <= mouse_x < WIDTH and 0 <= mouse_y < HEIGHT:
            grid_pos = convert_pos(pos)
        else:
            grid_pos = None

        if left:
            if grid_pos is None:
                for item, colour in enumerate(COLOURS):
                    select_colour = pygame.Rect(0, 0, 120, 30)
                    select_colour.center = (
                        WIDTH + SIDE / 2,
                        HEIGHT / len(COLOURS) * (item + 0.5)
                    )

                    if select_colour.collidepoint(pygame.mouse.get_pos()):
                        self.draw_color = colour
            else:
                self.pressed[grid_pos] = self.draw_color

        elif middle:
            self.pressed.clear()

        elif right:
            self.pressed.pop(grid_pos, None)

    def draw(self) -> None:
        self.screen.fill("White")
        self.draw_grid()
        self.draw_select_colour()
        self.draw_square()
        pygame.display.update()

    def run(self) -> None:
        while True:
            event: Event = pygame.event.wait()

            if event.type == pygame.QUIT:
                return

            if event.type == pygame.MOUSEBUTTONDOWN:
                self.handle_mouse(event.pos, *(
                    event.button == b for b in (
                        pygame.BUTTON_LEFT,
                        pygame.BUTTON_MIDDLE,
                        pygame.BUTTON_RIGHT,
                    )
                ))

            if event.type == pygame.MOUSEMOTION:
                self.handle_mouse(event.pos, *event.buttons)

            if event.type in {pygame.MOUSEBUTTONDOWN, pygame.MOUSEMOTION, pygame.WINDOWSHOWN}:
                self.draw()


if __name__ == '__main__':
    Game().run()
票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/274507

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档