1

This program should print "True", only if green rect touches the red line, but it prints True every time green rect got into red lines "area"(touches the lines sprite). Is there a way to make lines sprite?

In this code green is not on line, but still prints true:



class Line(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.Surface((200, 200))
        self.rect = self.image.get_rect()
        self.rect.x = 50
        self.rect.y = 0

    def update(self):
        pygame.draw.line(screen, (255, 0, 0), (self.rect.x, self.rect.y), (200, 200))


class Rectt(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.Surface((50, 50))
        self.rect = self.image.get_rect()
        self.rect.x = 25
        self.rect.y = 100

    def update(self):
        pygame.draw.rect(screen, (0, 255, 0), self.rect)


pygame.init()
screen = pygame.display.set_mode((300, 300))
screen.fill((0, 0, 0))
running = True
l = Line()
m = Rectt()
while running:
    for event in pygame.event.get():
        if (event.type == pygame.QUIT):
            running = False
    if (pygame.sprite.collide_mask(m, l)):
        print(True)
    else:
        print(False)
    l.update()
    m.update()
    pygame.display.flip()
    screen.fill((0, 0, 0))
pygame.quit()

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
Sor4nex
  • 23
  • 5
  • usually for line collisions you would use [`clipline`](https://www.pygame.org/docs/ref/rect.html#pygame.Rect.clipline) – Matiiss Dec 27 '21 at 15:32
  • This is only a suggestion, but you could turn the line into a rect. And then you could simply do .colliderect() – CozyCode Dec 27 '21 at 17:21
  • @CozyCode that would make a rectangle where the line could be considered the diagonal, which would effectively do the same that is happening now – Matiiss Dec 27 '21 at 17:52
  • try doing `pygame.draw.rect(self.image, ...)` in the `Line`'s `update` method, so that the line is drawn on the `image` and mask is created correctly – Matiiss Dec 27 '21 at 17:53

1 Answers1

2

See Make a line as a sprite with its own collision in Pygame
Check collision between a image and a line

You need to create a image (pygame.Surface) in with a per pixel alpha format (pygame.SRCALPHA) or a black color key (pygame.Surface.get_colorkey). Draw the line on the image and blit the image on the screen:

class Line(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.Surface((200, 200))
        self.image.set_colorkey((0, 0, 0))
        pygame.draw.line(self.image, (255, 0, 0), (0, 0), (200, 200))
        self.rect = self.image.get_rect()
        self.rect.x = 50
        self.rect.y = 0

    def update(self):
        screen.blit(self.image, self.rect)

Do the same for the rectangle:

class Rectt(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.Surface((50, 50))
        self.image.set_colorkey((0, 0, 0))
        pygame.draw.rect(self.image, (0, 255, 0), (0, 0, 50, 50))
        self.rect = self.image.get_rect()
        self.rect.x = 25
        self.rect.y = 100

    def update(self):
        screen.blit(self.image, self.rect)

You do not need the update methods at all if you are using a pygame.sprite.Group and pygame.sprite.Group.draw:

import pygame

class Line(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.Surface((200, 200))
        self.image.set_colorkey((0, 0, 0))
        pygame.draw.line(self.image, (255, 255, 0), (0, 0), (200, 200), 5)
        self.rect = self.image.get_rect(topleft = (50, 50))

class Rectt(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.Surface((50, 50))
        self.image.set_colorkey((0, 0, 0))
        pygame.draw.rect(self.image, (0, 0, 255), (0, 0, 50, 50))
        self.rect = self.image.get_rect(topleft = (25, 100))

pygame.init()
screen = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()

running = True
l = Line()
m = Rectt()
group = pygame.sprite.Group([l, m])

while running:
    clock.tick(100)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    keys = pygame.key.get_pressed()
    m.rect.x += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * 3
    m.rect.y += (keys[pygame.K_DOWN] - keys[pygame.K_UP]) * 3
    m.rect.clamp_ip(screen.get_rect())
    hit = pygame.sprite.collide_mask(m, l)
   
    screen.fill((0, 0, 0))
    group.draw(screen)
    if hit:
        pygame.draw.rect(screen, (255, 0, 0), m.rect, 5)
    pygame.display.flip()
   
pygame.quit()
Rabbid76
  • 202,892
  • 27
  • 131
  • 174