如何转换我在代码中加载的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()
答案 0 :(得分:1)
所以 - 事实证明你想要的东西比你在那里尝试的要复杂一点。
Pygame在一个函数中有像素碰撞检测,即#py; pygame.sprite.collide_mask"。尝试使用Python代码检查带有image.get_at
的像素以检查透明像素的像素验证太慢 - 通过像素的纯Python循环可能比在本机代码中检查的代码慢几千倍。这意味着您必须使用pygame.sprite.collide_mask
。
该函数的问题在于它只适用于图像蒙版 - 它们必须附加到一个精灵对象,它也必须有一个有效的"矩形"属性。 (https://www.pygame.org/docs/ref/sprite.html#pygame.sprite.collide_mask)
不好的是你必须正确地创造所有这些东西。好的部分是你可以通过在代码中使用Sprite对象获得一些额外的好处 - 比如封装一些逻辑,以及" posx"和"诗句"协调自己。我保留了单独的变量,因此您可以想出最好的方法。
另一个坏消息是,尽管理论上还可以,而且工作效果很好&#34 ;,但是有一些极端情况下使用了mask-collsion检测。你会注意到当你跑到角落时运行这些例子,你可能会卡住。我试图用另一个来减轻这种情况"展望未来"步入碰撞检测功能 - 对我来说感觉好一点,但移动的圆圈有时会卡住。
无论如何,所有的代码都是:
"""
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_mask
方法需要一个Sprite对象,该对象具有rect
和mask
属性 - rect
包含游戏字段中的精灵位置,以及mask
是从图像创建的蒙版。
迷宫可以成为覆盖所有领域的单个精灵(同样,它必须按比例缩小以适合您的屏幕尺寸 - 我通过调用...rotozoom
来实现。它已经包含透明度,它是全部设置的(同样,请注意,如果您要拥有纯色背景,则不需要第二个图像 - 您可以使用fill
曲面方法)。
现在,"圈"角色必须有一个图像 - 所以我花了一些线创建一个内存表面,并绘制一个圆圈,并使用这个表面作为"圆"子画面。
由于我们的精灵必须自己拥有一个类,我将colsiion检测逻辑作为一种方法 - 它基本上需要一个"未来的偏移"当要移动精灵时,第二个精灵 - 在这种情况下,总是迷宫。它"模拟"新职位,并检查是否"自我" (即圆形精灵)将与"其他精灵碰撞"面具在那个位置。如果是这样,游戏逻辑中的if
语句会阻止更新位置。 (稍微调整这些if语句可能会让你获得更好的体验,防止"粘性"角落,因为它们存在于当前的迷宫中)。
总而言之,我希望您能够理解这里所做的工作,并且您可以改进此代码以获得更好的使用体验。