Python 如何将PNG图像转换为边框(用于圆)[pygame]?

Python 如何将PNG图像转换为边框(用于圆)[pygame]?,python,python-3.x,pygame,Python,Python 3.x,Pygame,如何将加载到代码中的PNG文件(用于pygame)转换为圆的边界 我有以下图像(png): 我正在使用jpeg文件作为白色背景 我的意思是,如何防止圆进入PNG图像?圆圈使用箭头键向左、向右、向上、向下移动 我的代码: import pygame def main1(): width, height = 600, 600 posx, posy = 300, 300 screen = pygame.display.set_mode((width, height))

如何将加载到代码中的PNG文件(用于
pygame
)转换为圆的边界

我有以下图像(
png
):

我正在使用
jpeg
文件作为白色背景

我的意思是,如何防止圆进入PNG图像?圆圈使用箭头键向左、向右、向上、向下移动

我的代码:

import pygame

def main1():
    width, height = 600, 600
    posx, posy = 300, 300
    screen = pygame.display.set_mode((width, height))
    clock = pygame.time.Clock()
    velocity = (0, 0)
    done = False
    pygame.display.update()
    bg = pygame.image.load("maze1.png")
    bg1 = pygame.image.load("maze2.jpeg")
    while not done:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                done = True

        keys = pygame.key.get_pressed()
        screen.blit(bg1, (0, 0))
        screen.blit(bg, (0, 0))
        if keys[pygame.K_RIGHT]:
            posx += 3
        if keys[pygame.K_UP]:
            posy -= 3
        if keys[pygame.K_LEFT]:
            posx -= 3
        if keys[pygame.K_DOWN]:
            posy += 3
        cir = pygame.draw.circle(screen, (255, 200, 240), (posx,posy), 10)
        pygame.display.flip()
        clock.tick(30)

if __name__ == '__main__':
   pygame.init()
   main1()
   pygame.quit()

所以,事实证明,你想要的比你在那里尝试的要复杂一些

Pygame的一个功能是“Pygame.sprite.collide_mask”,其中包含像素碰撞检测。尝试用Python代码自己进行像素验证,用
图像检查像素。在
处检查透明像素的速度太慢了-通过像素的纯Python循环可能比在本机代码中检查像素的代码慢数千倍。这意味着您必须使用
pygame.sprite.collide\u mask

该函数的问题在于,它只适用于图像遮罩——它们必须附加到精灵对象,该对象还必须具有有效的“矩形”属性。()

糟糕的是,你必须正确地创造所有这些东西。好的方面是,在代码中使用Sprite对象可以带来一些额外的好处,比如封装一些逻辑,“posx”和“posy”相互协调。我保留了单独的变量,这样你就可以想出最好的方法

另一个坏消息是,尽管理论上还可以,而且工作“相当好”,但仍有一些使用掩码冲突检测的角落案例。在运行这些示例时,您会注意到,当您遇到拐角时,您可能会被卡住。我试图通过碰撞检测功能中的另一个“向前看”步骤来缓解这种情况——对我来说感觉好一点,但移动的圆圈有时会卡住

总之,所有代码都是这样的:

"""
Author: Muhammad Nouman
https://stackoverflow.com/questions/45673808/how-to-convert-png-image-to-boundries-for-circle-pygame

"""
import pygame


class GameObject(pygame.sprite.Sprite):
    def __init__(self, image):
        super().__init__()
        self.image = image
        self.rect = self.image.get_rect()
        self.mask = pygame.mask.from_surface(image)

    def can_move(self, delta_pos, wall_map, count=1):
        old_pos = self.rect.center
        self.rect.centerx = self.rect.centerx + delta_pos[0]
        self.rect.centery = self.rect.centery + delta_pos[0]
        result = bool(pygame.sprite.collide_mask(self, wall_map))
        if count:
            result &= not self.can_move(delta_pos, wall_map, count - 1)
        self.rect.center = old_pos
        return not result


def main1():
    width, height = 600, 600
    posx, posy = 300, 300
    screen = pygame.display.set_mode((width, height))
    clock = pygame.time.Clock()
    velocity = (0, 0)
    done = False
    pygame.display.update()
    bg = pygame.image.load("maze1.png")
    bg = pygame.transform.rotozoom(bg, 0, width / bg.get_width())
    bg1 = pygame.image.load("maze2.jpeg")
    character_image = pygame.Surface((20,20), pygame.SRCALPHA)
    pygame.draw.circle(character_image, (255, 200, 240, 255), (10, 10), 10)

    character = GameObject(character_image)
    character.rect.center = (posx, posy)

    tiled_maze = GameObject(bg)

    while not done:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                done = True

        keys = pygame.key.get_pressed()
        screen.fill((255, 255,255))
        screen.blit(bg, (0, 0))
        if keys[pygame.K_RIGHT]:
            if character.can_move((3, 0), tiled_maze):
                posx += 3
        if keys[pygame.K_UP]:
            if character.can_move((0, -3), tiled_maze):
                posy -= 3
        if keys[pygame.K_LEFT]:
            if character.can_move((-3, 0), tiled_maze):
                posx -= 3
        if keys[pygame.K_DOWN]:
            if character.can_move((0, 3), tiled_maze):
                posy += 3
        character.rect.center = ((posx, posy))
        screen.blit(character.image, character.rect)
        pygame.display.flip()
        clock.tick(30)

if __name__ == '__main__':
   pygame.init()
   main1()
   pygame.quit()
所以,给大家一个大概的想法:“遮罩”是pygame可以创建的图像的简化版本,可以标记哪些像素确实包含某些内容,哪些像素是完全透明的。它们是从图像创建的。
collide\u mask
方法需要一个精灵对象,该对象具有
rect
mask
属性-
rect
包含精灵在游戏场上的位置,而
mask
是从图像创建的面具

迷宫可以被制作成一个覆盖所有区域的单精灵(同时,它必须缩小以适应您的屏幕大小-我通过调用
…rotozoom
)来制作。因为它已经包含透明度,所以它已经设置好了(另外,请注意,如果要使用纯色背景,则不需要第二张图像-可以使用曲面的
填充方法)

现在,“圆”角色必须有一个图像-所以我花了一些线在内存中创建一个曲面,并在其上绘制一个圆,并使用该曲面作为“圆”精灵的图像

因为我们的精灵必须有自己的类,所以我将colsiion检测逻辑作为一种方法——当精灵要移动时,它基本上需要一个“未来偏移”,第二个精灵——在这种情况下,总是迷宫。它“模拟”新的位置,并检查“自我”(即圆形精灵)是否会与迷宫碰撞“其他精灵”遮罩在该位置。如果是这样,游戏逻辑中的
If
语句会阻止该位置被更新。(稍微调整这些If语句可能会让你获得更好的体验,防止当前迷宫中存在的“粘性”角落)


总而言之,我希望您能理解这里所做的工作,并改进此代码以获得更好的使用体验。

查看其工作原理。这可能很难实现。我曾经尝试创建一个类似蠕虫的原型,但在像素完美地形上的移动并不令人满意。这很好,但圆陷入了迷宫(当它碰到它的时候)。有什么解决办法吗?老兄,这个圆粘得太硬了。是的,在“检查我是否能去那里,然后才去”的算法中有一些东西“这是错误的——因为应该总是可以像进入那里一样后退。也许保留一份圆圈最后位置的列表,并且总是将这些可能的位置列为白名单是一个合适的解决办法。