python-3.x 重载pygame.surface以动态增加表面的大小

dpiehjr4  于 2023-02-01  发布在  Python
关注(0)|答案(1)|浏览(165)

我试图建立一个应用程序,要求用户画的东西。
为此,我创建了一个画布(一个pygame.Surface对象),然后我把它放到窗口上。我希望画布是“无限的”,这样当用户滚动时,他可以继续绘制(当然,画布上只有一小部分被涂在窗口上)。但是,实际上,Pygame中的Surface需要有限的宽度和高度,最重要的是,它不是那么大!(我想那是因为它实际上锁定了内存中的空间)。
所以,我试着创建:每个块都有固定的大小(比如两倍屏幕大小),并且每个块都分配了一个特定的表面。2块是动态创建的,按需创建,总体上运行得很好。
我的问题是,当我试图画出跨越多个块的线时,需要花很大的力气来计算这条线实际上应该画在哪些块上,应该在哪些块上断开。我甚至没有尝试画矩形,因为让“画线”功能工作起来真的很痛苦。
那时候我觉得我所做的根本就是错的我不想重写所有pygame.draw和pygame.gfxdraw函数,让它们基本上完成每个块的工作,我应该重载pygame.Surface(比如,创建Surface的MySurface子类),这样无论何时修改像素,我都会在内部选择它属于哪个块,并在该块上实际更改它,然后将新的Surface对象传递给pygame函数。
我在the pygame doc上搜索了很多,但是没有解释如何操作。我甚至不知道当我在一个Surface对象上进行blit/draw时,它的哪些方法会被内部调用!我也在谷歌上搜索了一下,我没有发现有人试图做这种事情(也许我走错了路?)
因此,我的问题是:这是正确的方法吗?如果是,我应该如何实现它?
我不张贴代码,因为我需要的是更多的解释,在哪里可以找到我试图做什么比代码审查更多的文件。

hrirmatl

hrirmatl1#

你不能只子类化Surface,因为它不是用python写的,而是用C.Here's the source code写的;你自己看吧。
您可以采用另一种方法,不计算在哪里绘制内容,而是先将其blit到临时Surface上,然后将其blit到与块位置相关的块上。
下面是一个简单的例子:

import pygame

class Chunk(pygame.sprite.Sprite):
    def __init__(self, grid_pos, size, color):
        super().__init__()
        self.image = pygame.Surface(size)
        self.rect = self.image.get_rect(
            x = grid_pos[0] * size[0],
            y = grid_pos[1] * size[1]
        )
        self.image.fill(pygame.Color(color))

    def patch(self, surface):
        self.image.blit(surface, (-self.rect.x, -self.rect.y))

def main():
    pygame.init()
    size = 800, 600
    screen = pygame.display.set_mode(size)
    chunks = pygame.sprite.Group(
        Chunk((0,0), size, 'green'),
        Chunk((1,0), size, 'red'),
        Chunk((0,1), size, 'blue'),
        Chunk((1,1), size, 'yellow')
    )
    dragging = None
    drawing = None
    tmp_s = pygame.Surface(size, pygame.SRCALPHA)

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return
            if event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 3:
                    dragging = event.pos
                if event.button == 1:
                    drawing = event.pos

            if event.type == pygame.MOUSEBUTTONUP:
                if event.button == 3:
                    dragging = None
                if event.button == 1:
                    drawing = None
                    for chunk in chunks:
                        chunk.patch(tmp_s)

            if event.type == pygame.MOUSEMOTION:
                if dragging:
                    for chunk in chunks:
                        chunk.rect.move_ip(event.rel)

        screen.fill((0, 0, 0))
        chunks.draw(screen)

        tmp_s.fill((0,0,0,0))
        if drawing:
            size = pygame.Vector2(pygame.mouse.get_pos()) - drawing
            pygame.draw.rect(tmp_s, pygame.Color('white'), (*drawing, *size), 10)

        screen.blit(tmp_s, (0, 0))
        chunks.update()
        pygame.display.flip()

main()

如你所见,画布由4块组成,用鼠标右键移动画布,用鼠标左键开始画矩形。

相关问题