Li Joskovitch
Li Joskovitch

Reputation: 11

how can i check (easily) if two sprites are near each other

how can i check (easily) if two sprites are near each other like they have a 100 pixels difference between them and i need it to be something that doesn't require a lot of if's. the only thing i got to is doing a lot of if's and for my game (hexagon) i need it to be with not so many if's

def is_near(myPearl,bPearl):
    if (abs(myPearl.rect.x - bPearl.rect.x) == 100 and abs(myPearl.rect.y -       bPearl.rect.y) == 100) or abs(myPearl.rect.y - bPearl.rect.y) == 100 or  myPearl.rect.x == bPearl.rect.x:
      return 1  # 1 means that the pearl is near it and this pearl is next to the pushed pearl
    if abs(myPearl.rect.x - bPearl.rect.x) == 200 or abs(myPearl.rect.y - bPearl.rect.y) == 200 or myPearl.rect.x == bPearl.rect.x:
      return 2  # 2 means that the pearl is near it and this pearl is two slots near the pushed pearl

Upvotes: 1

Views: 908

Answers (1)

skrx
skrx

Reputation: 20438

I'd check if the center of a sprite is within the radius of another sprite. You can use pg.math.Vectors and their distance_to method to get the distance and then look if it's less than the radius. In the following example I do this in the circle_collision function which is passed as a callback to pg.sprite.groupcollide. I needed the if left != right: test, so that sprites don't collide with themselves.

import sys
import pygame as pg
from pygame.math import Vector2
from pygame.color import THECOLORS


class Player(pg.sprite.Sprite):

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


def circle_collision(left, right):
    if left != right:
        distance = Vector2(left.rect.center).distance_to(right.rect.center)
        return distance < left.radius
    else:
        return False


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

    sprite_group = pg.sprite.Group()
    player1 = Player((100, 300), sprite_group)
    player2 = Player((400, 300), sprite_group)
    player3 = Player((100, 100), sprite_group)

    done = False

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

        sprite_group.update()
        collided_sprites = pg.sprite.groupcollide(
            sprite_group, sprite_group, False, False,
            collided=circle_collision)

        # Draw everything.
        screen.fill(THECOLORS['lemonchiffon4'])
        sprite_group.draw(screen)

        for collided_sprite in collided_sprites:
            pg.draw.circle(screen, THECOLORS['lightcyan1'],
                           collided_sprite.rect.center,
                           collided_sprite.radius, 2)

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


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

You could also give the sprites a second, larger rect and look if it collides with the rect of the other sprite. The code is pretty much the same, but pygame.rect.colliderect is used instead of the distance < radius check.

import sys
import pygame as pg
from pygame.color import THECOLORS


class Player(pg.sprite.Sprite):

    def __init__(self, pos, *groups):
        super().__init__(*groups)
        self.image = pg.Surface((50, 30))
        self.image.fill(THECOLORS['sienna1'])
        self.rect = self.image.get_rect(center=pos)
        self.vicinity_rect = self.rect.inflate(200, 200)
        self.vicinity_rect.center = self.rect.center

    def update(self):
        self.vicinity_rect.center = self.rect.center


def vicinity_collision(left, right):
    if left != right:
        return left.vicinity_rect.colliderect(right.rect)
    else:
        return False


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

    sprite_group = pg.sprite.Group()
    player1 = Player((100, 300), sprite_group)
    player2 = Player((400, 300), sprite_group)
    player3 = Player((100, 100), sprite_group)

    done = False

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

        sprite_group.update()
        collided_sprites = pg.sprite.groupcollide(
            sprite_group, sprite_group, False, False,
            collided=vicinity_collision)

        # Draw everything.
        screen.fill(THECOLORS['lemonchiffon4'])
        sprite_group.draw(screen)

        for collided_sprite in collided_sprites:
            pg.draw.rect(screen, THECOLORS['lightcyan1'],
                         collided_sprite.vicinity_rect, 2)

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


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

Upvotes: 1

Related Questions