Python-pygame 如何在精灵之间进行光环碰撞? [英] Python-pygame How to make an aura collision between sprites?

查看:54
本文介绍了Python-pygame 如何在精灵之间进行光环碰撞?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以,当精灵玩家绕过(而不是越过)另一个精灵时,我试图得到一个反应.

so, Im trying to get a reaction when the sprite player pass around (not over) another sprite.

到目前为止,我的想法是这样的:

So far my idea is something like:

if (sprite.x +100) > player.x > (sprite.x -100) and (sprite.y +100) > player.y > (sprite.y -100):
    print("hit")
# Sprite.x and y are the position of the rect, not the whole image

这行得通,但有什么方法可以简化它吗?我也在想如何摆脱 100 像素

This works but there is some way to simplify it? Also Im thinking how to get rid of the 100 pixels

推荐答案

如果您想使用缩放的 rect 进行碰撞检测,您可以扩大您的原始 rect(或创建一个新的)并将其分配为单独的属性到你的精灵(我称之为 hitbox 在这里).原始的 rect 将仅用于存储位置.

If you want to use a scaled rect for the collision detection, you can inflate your original rect (or create a new one) and assign it as a separate attribute to your sprite (I call it hitbox here). The original rect will only be used to store the position.

创建一个自定义碰撞检测函数,该函数必须作为 collided 参数传递给 pygame.sprite.spritecollidegroupcollide.在这个函数中,你可以使用 hitbox 矩形的 colliderect 方法来检查它是否与另一个精灵的矩形发生碰撞.

Create a custom collision detection function which has to be passed as the collided argument to pygame.sprite.spritecollide or groupcollide. In this function you can use the colliderect method of the hitbox rect to check if it collides with the rect of the other sprite.

def hitbox_collision(sprite1, sprite2):
    """Check if the hitbox of the first sprite collides with the
    rect of the second sprite.

    `spritecollide` will pass the player object as `sprite1`
    and the sprites in the enemies group as `sprite2`.
    """
    return sprite1.hitbox.colliderect(sprite2.rect)

然后这样调用spritecollide:

collided_sprites = pg.sprite.spritecollide(
    player, enemies, False, collided=hitbox_collision)

这是一个完整的例子(红色矩形是hitbox,绿色矩形是用作blit位置的self.rect):

Here's a complete example (the red rect is the hitbox and the green rect the self.rect which is used as the blit position):

import pygame as pg


class Player(pg.sprite.Sprite):

    def __init__(self, pos, *groups):
        super().__init__(*groups)
        self.image = pg.Surface((30, 50))
        self.image.fill(pg.Color('dodgerblue1'))
        self.rect = self.image.get_rect(center=pos)
        # Give the sprite another rect for the collision detection.
        # Scale it to the desired size.
        self.hitbox = self.rect.inflate(100, 100)

    def update(self):
        # Update the position of the hitbox.
        self.hitbox.center = self.rect.center


class Enemy(pg.sprite.Sprite):

    def __init__(self, pos, *groups):
        super().__init__(*groups)
        self.image = pg.Surface((30, 50))
        self.image.fill(pg.Color('sienna1'))
        self.rect = self.image.get_rect(center=pos)


def hitbox_collision(sprite1, sprite2):
    """Check if the hitbox of the first sprite collides with the
    rect of the second sprite.

    `spritecollide` will pass the player object as `sprite1`
    and the sprites in the enemies group as `sprite2`.
    """
    return sprite1.hitbox.colliderect(sprite2.rect)


def main():
    screen = pg.display.set_mode((640, 480))
    clock = pg.time.Clock()
    all_sprites = pg.sprite.Group()
    enemies = pg.sprite.Group()

    player = Player((100, 300), all_sprites)
    enemy = Enemy((320, 240), all_sprites, enemies)

    done = False

    while not done:
        for event in pg.event.get():
            if event.type == pg.QUIT:
                done = True
            elif event.type == pg.MOUSEMOTION:
                player.rect.center = event.pos

        all_sprites.update()
        collided_sprites = pg.sprite.spritecollide(
            player, enemies, False, collided=hitbox_collision)
        for enemy_sprite in collided_sprites:
            print(enemy_sprite)

        screen.fill((30, 30, 30))
        all_sprites.draw(screen)
        pg.draw.rect(screen, (0, 255, 0), player.rect, 1)
        pg.draw.rect(screen, (255, 0, 0), player.hitbox, 1)

        pg.display.flip()
        clock.tick(30)


if __name__ == '__main__':
    pg.init()
    main()
    pg.quit()

<小时>

如果你想要一个圆形的碰撞区域,你可以通过 pygame.sprite.collide_circle 函数作为 collided 参数.

给你的精灵一个 self.radius 属性,

Give your sprites a self.radius attribute,

class Player(pg.sprite.Sprite):

    def __init__(self, pos, *groups):
        super().__init__(*groups)
        self.radius = 100

并在主循环中将collide_circle传递给spritecollide.

and in the main loop pass collide_circle to spritecollide.

collided_sprites = pg.sprite.spritecollide(
    player, enemies, False, collided=pg.sprite.collide_circle)

这篇关于Python-pygame 如何在精灵之间进行光环碰撞?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆