Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 3.x 重载pygame.Surface,以便动态增大曲面的大小_Python 3.x_Pygame_Pygame Surface - Fatal编程技术网

Python 3.x 重载pygame.Surface,以便动态增大曲面的大小

Python 3.x 重载pygame.Surface,以便动态增大曲面的大小,python-3.x,pygame,pygame-surface,Python 3.x,Pygame,Pygame Surface,我正在尝试构建一个应用程序,它需要用户绘制一些东西 为此,我创建了一个画布(一个pygame.Surface对象),在上面注册了图形,然后将其放到窗口上。我希望画布是无限的,这样当用户滚动时,他就可以继续绘制(当然,只有画布的一小部分会显示在窗口上)。但是,实际上,pygame中的曲面需要有限的宽度和高度,最重要的是,它没有那么大!(我认为这是因为它实际上锁定了内存中的空间) 因此,我尝试创建块:每个块都有固定的大小(比如,屏幕大小的两倍),每个块都分配了一个特定的曲面。区块是按需以友好方式创建

我正在尝试构建一个应用程序,它需要用户绘制一些东西

为此,我创建了一个画布(一个pygame.Surface对象),在上面注册了图形,然后将其放到窗口上。我希望画布是无限的,这样当用户滚动时,他就可以继续绘制(当然,只有画布的一小部分会显示在窗口上)。但是,实际上,pygame中的曲面需要有限的宽度和高度,最重要的是,它没有那么大!(我认为这是因为它实际上锁定了内存中的空间)

因此,我尝试创建:每个块都有固定的大小(比如,屏幕大小的两倍),每个块都分配了一个特定的曲面。区块是按需以友好方式创建的,总体上运行良好

我的问题是,当我试图在多个块上画交叉线时,需要花很大的精力来计算该线应该画在哪些块上,以及应该在哪些块上断开。我甚至没有尝试画矩形,因为让“画一条线”功能工作起来真的很痛苦

当时我认为我所做的是根本错误的:与其试图重写所有pygame.draw和pygame.gfxdraw函数,以便它们基本上完成每一块的工作,不如让pygame.Surface过载(比如,创建一个MySurface类Surface的子类),这样每当修改像素时,我在内部选择了它所属的块,并在该块上实际更改它,然后将新的曲面对象传递给pygame函数

我在上搜索了很多,但没有解释如何做到这一点。我甚至不知道当我在曲面对象上blit/draw时,它的内部调用了什么方法!我也在谷歌上搜索过,我没有发现有人试图做那种事情(也许我走错了方向?)

因此,我的问题是:这是正确的方法吗?如果是的话,我该如何认识到这一点


我不发布代码,因为我需要的不仅仅是代码审查,更重要的是解释在哪里可以找到我试图做的事情的文档。

你不能只是子类
Surface
,因为它不是用python编写的,而是用C编写的;你自己找吧

您可以采用另一种方法,而不是计算在何处绘制内容,首先将其放到一个临时的
表面上,然后将其与块的位置相对应地映射到块上

下面是我拼凑的一个简单例子:

 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个块组成。使用鼠标右键移动画布,左键开始绘制矩形。

。。。我想我可以看到两个选择:进入C级或者简单地接受你的伟大解决方案(我已经做出了选择:P)。顺便说一句,如果我理解的很好,我不必对我的块做任何特殊的事情,但是我仍然需要为标准的绘图函数创建包装器?无论如何,谢谢你的回答和反应!您不必包装绘图函数本身。只是不要直接画到屏幕表面。好的,我已经实现了它,但是我在性能上遭受了巨大的损失。我从~300fps以~30fps的速度通过,只是因为我在每一帧将临时曲面blit到块上。当你想永久改变块时,你只需要将临时曲面blit到块上。此外,由于您的块与屏幕一样大或更大,因此最多有四个块需要更改。你应该知道当前哪些块是可见的,并且只在临时表面上显示这些块。这实际上就是我后来试图提高效率的地方(要求块比屏幕大,生成看到的块的坐标,检索这些块或者创建它们(如果它们还不存在),最后只显示一次,当用户尝试滚动时,请重置临时曲面。因此,我认为我的性能问题来自我的程序中的一个bug,而不是您的解决方案,我将修复它(迟早)。谢谢你的帮助!