在 Pygame 中使用精灵进行碰撞检测

发布于 2024-10-11 10:55:48 字数 751 浏览 6 评论 0原文

我正在尝试使用碰撞检测来检测鼠标何时点击我导入的图像。我收到错误“元组没有属性矩形”

 def main():


    #Call the SDL arg to center the window when it's inited, and then init pygame
    os.environ["SDL_VIDEO_CENTERED"] = "1"
    pygame.init()

    #Set up the pygame window
    screen = pygame.display.set_mode((600,600))


    image_one = pygame.image.load("onefinger.jpg").convert()

    screen.fill((255, 255, 255))
    screen.blit(image_one, (225,400))
    pygame.display.flip()

    while 1:
        mousecoords = pygame.mouse.get_pos() 
        left = (mousecoords[0], mousecoords[1], 10, 10)
        right = image_one.get_bounding_rect()
        if pygame.sprite.collide_rect((left[0]+255, left[1]+400, left[2], left[3]), right):
            print('Hi')

I'm trying to use collision detection to detect when my mouse hits an image that I've imported. I get the error "tuple does not have attribute rect"

 def main():


    #Call the SDL arg to center the window when it's inited, and then init pygame
    os.environ["SDL_VIDEO_CENTERED"] = "1"
    pygame.init()

    #Set up the pygame window
    screen = pygame.display.set_mode((600,600))


    image_one = pygame.image.load("onefinger.jpg").convert()

    screen.fill((255, 255, 255))
    screen.blit(image_one, (225,400))
    pygame.display.flip()

    while 1:
        mousecoords = pygame.mouse.get_pos() 
        left = (mousecoords[0], mousecoords[1], 10, 10)
        right = image_one.get_bounding_rect()
        if pygame.sprite.collide_rect((left[0]+255, left[1]+400, left[2], left[3]), right):
            print('Hi')

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

卖梦商人 2024-10-18 10:55:48

Peter 建议,并且您也发现了,在处理碰撞检测时,使用矩形而不是位置更容易。

我会更进一步:始终与Sprites一起工作!

使用 Sprites,您可以访问 pygame.sprite 中所有方便的碰撞检测功能。如果您决定移动该图像,则更新位置和动画会更容易。它还包含图像表面,全部位于单个对象中。更不用说精灵了!

Sprites 也有一个 .rect 属性,所以如果你愿意的话,你总是可以使用 mysprite.rect 进行低级的矩形操作

也就是说,这里是你如何获取 Sprite 的方法图像的:

image_one = pygame.sprite.Sprite()
image_one.image = pygame.image.load("image_one.png").convert()
image_one.rect = pygame.Rect((image_x, image_y), image_one.image.get_size())

image_two_ Three 等创建更多精灵。或者创建一个函数(或者更好的是,子类 Sprite),接收位置和文件名作为参数,因此您可以在单行中创建精灵,如下所示:

image_two = MySprite(filename, x, y)

现在您可以选择将它们分组:

my_images = pygame.sprite.Group(image_one, image_two, image_three)

绘图就像这样简单:

my_images.draw(screen)

这将一次blit所有图像,各就各位!很酷吧?

让我们为鼠标光标创建一个“假”精灵:

mouse = pygame.sprite.Sprite()
mouse.rect = pygame.Rect(pygame.mouse.get_pos(), (1, 1))

我将其制作为 1x1 精灵,因此它仅在鼠标热点上发生碰撞。请注意,它没有 .image 属性(因此是“假”精灵),但 pygame 并不关心,因为我们无论如何也不会绘制它。

现在是最好的部分:

imagehit = pygame.sprite.spritecollideany(mouse, my_images)
print imagehit

在一行中,您测试了与所有图像的碰撞,您不仅知道是否鼠标与任何图像发生碰撞,还它做到了哪一个

使用 Sprites 真的很值得;)

Peter suggested, and you also figured it out, that it's easier to work with Rects instead of positions when dealing with collision detection.

I would take that one step further: always work with Sprites!

With Sprites you get access to all those handy collision detection functions in pygame.sprite. And if you ever decide to move that image around, it's much easier to update position and animate. It also contains the image surface, all in a single object. Not to mention sprite Groups!

Sprites also have a .rect attribute, so you can always do low level rect manipulation if you want to with mysprite.rect

That said, here's how you can get a Sprite out of your image:

image_one = pygame.sprite.Sprite()
image_one.image = pygame.image.load("image_one.png").convert()
image_one.rect = pygame.Rect((image_x, image_y), image_one.image.get_size())

Create more sprites for image_two, _three, etc. Or create a function (or, even better, subclass Sprite), receiving position and filename as arguments, so you can create sprites in a single line as:

image_two = MySprite(filename, x, y)

Now you can optionally group them:

my_images = pygame.sprite.Group(image_one, image_two, image_three)

Drawing is as easy as:

my_images.draw(screen)

That will blit all images at once, each one in their own positions! Cool, huh?

Let's create a "fake" Sprite for the mouse cursor:

mouse = pygame.sprite.Sprite()
mouse.rect = pygame.Rect(pygame.mouse.get_pos(), (1, 1))

I've made it a 1x1 sprite so it only collide on mouse hotspot. Notice that it does not have an .image attribute (hence "fake" sprite), but pygame does not care since we're not going to draw it anyway.

And now the best part:

imagehit = pygame.sprite.spritecollideany(mouse, my_images)
print imagehit

In a single line you tested collision against all images, and not only you know if the mouse collided with any, but also which one it did!

It really pays off to use Sprites ;)

似狗非友 2024-10-18 10:55:48

问题是 pygame.sprite.collide_rect() 需要两个 Sprite 对象。您向它传递了两个元组 - 光标和图像都不是精灵,因此缺少 rect 属性。

您可以使用 image_one 制作 Sprite,但将光标转换为 Sprite 会更加棘手。我认为手动测试光标是否在图像内会更容易。

#Set up the pygame window
screen = pygame.display.set_mode((200,200))
screen.fill((255, 255, 255))

#Set up image properties (would be better to make an object)
image_one = pygame.image.load("image_one.png").convert()
image_x = 225
image_y = 400
image_width = image_one.get_width()
image_height = image_one.get_height()

# Mouse properties
mouse_width = 10
mouse_height = 10

screen.blit(image_one, (image_x, image_y))
pygame.display.flip()

while 1:
    for event in pygame.event.get():
        if event.type == pygame.MOUSEMOTION:
            mouse_x, mouse_y = pygame.mouse.get_pos()

            # Test for 'collision'
            if image_x - mouse_width < mouse_x < image_x + image_width and image_y - mouse_height < mouse_y < image_y + image_height:
                print 'Hi!'

请注意,我在测试鼠标是否在图像中之前测试了鼠标是否已移动,以避免不必要的重复计算。

The problem is that pygame.sprite.collide_rect() takes two Sprite objects. You are passing it two tuples - neither the cursor nor the image are Sprites and so lack a rect attribute.

You could make a Sprite using image_one, but it will be more tricky to convert the cursor into a Sprite. I think it would be easier to manually test whether the cursor is within the image.

#Set up the pygame window
screen = pygame.display.set_mode((200,200))
screen.fill((255, 255, 255))

#Set up image properties (would be better to make an object)
image_one = pygame.image.load("image_one.png").convert()
image_x = 225
image_y = 400
image_width = image_one.get_width()
image_height = image_one.get_height()

# Mouse properties
mouse_width = 10
mouse_height = 10

screen.blit(image_one, (image_x, image_y))
pygame.display.flip()

while 1:
    for event in pygame.event.get():
        if event.type == pygame.MOUSEMOTION:
            mouse_x, mouse_y = pygame.mouse.get_pos()

            # Test for 'collision'
            if image_x - mouse_width < mouse_x < image_x + image_width and image_y - mouse_height < mouse_y < image_y + image_height:
                print 'Hi!'

Notice that I test whether the mouse has moved before testing whether it's in the image, to avoid repeating the calculation needlessly.

oО清风挽发oО 2024-10-18 10:55:48

这与 pygame 或 python 无关,但可能会有所帮助。

Lazy Foo 有许多很棒的 SDL 教程,但它们都是用 C++ 编写的。不过,他们的评论非常好。它们的链接在这里: http://www.lazyfoo.net/SDL_tutorials/index.php< /a>

This isn't related to pygame or python, but may help.

Lazy Foo has a number of great tutorials for SDL, but they are in C++. They are extremely well commented though. The link to them is here: http://www.lazyfoo.net/SDL_tutorials/index.php

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文