Make a line as a sprite with its own collision in Pygame

喜你入骨 提交于 2021-01-24 07:50:28

问题


I am making a game that connects a line between a 2 players. I want to make it so I can tell when an object (which is also a sprite) collides with the line.

The way I thought of doing this is creating a line that acts a sprite. The line will be able to change length depending on where the players are.

I'm a bit new to PyGame so I'm not too sure on what I have so far:

class Line(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface([400,400])
        self.image.set_colorkey((0,0,0))
        self.rect = self.image.get_rect()
        self.rect.x = 0
        self.rect.y = 0
        pygame.draw.line(screen,(0,0,255),(0,0),(400,400),2)

NOTE: A similar post to this already exists, however, what the person is asking in that post is different than in this post. The general idea may be the same, but I'd like to know a simpler way.


回答1:


I recommend to test the collision with bit masks. See How can I made a collision mask? and the documentation of pygame.sprite.collide_mask():

Collision detection between two sprites, using masks.

collide_mask(SpriteLeft, SpriteRight) -> point

Tests for collision between two sprites, by testing if their bitmasks overlap. If the sprites have a "mask" attribute, that is used as the mask, otherwise a mask is created from the sprite image. Intended to be passed as a collided callback function to the *collide functions. Sprites must have a "rect" and an optional "mask" attribute.

All you have to do is add a mask attribute to the Sprites classes. Use pygame.mask.from_surface to creates a Mask from the given Surface:

class Line(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface([400, 400])
        self.image.set_colorkey((0, 0, 0))
        self.rect = self.image.get_rect()
        self.rect.x = 0
        self.rect.y = 0
        pygame.draw.line(screen, (0, 0, 255), (0, 0 ), (400, 400), 2)

        self.mask = pygame.mask.from_surface(self.image)

Use pygame.sprite.collide_mask() to detect the collision between 2 Sprites with a Mask:

class SpriteObject(pygame.sprite.Sprite):
    def __init__(self, x, y, image):
        super().__init__()
        self.image = image
        self.rect = self.image.get_rect(center = (x, y))
        self.mask = pygame.mask.from_surface(self.image)
other_sprite = SpriteObject(0, 0, sprite_image)
line_sprite = Line(*window.get_rect().center)
if pygame.sprite.collide_mask(line_sprite, other_sprite):
    print("hit")

See also Sprite mask


Minimal example:

import math
import pygame

class SpriteObject(pygame.sprite.Sprite):
    def __init__(self, x, y, image):
        super().__init__()
        self.image = image
        self.rect = self.image.get_rect(center = (x, y))
        self.mask = pygame.mask.from_surface(self.image)
    def update(self):
        self.rect.center = pygame.mouse.get_pos()

class Line(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__()
        self.image = pygame.Surface((200, 200))
        self.image.set_colorkey((0, 0, 0))
        self.rect = self.image.get_rect(center = (x, y))
        self.angle = 0
    def update(self):
        vec = round(math.cos(self.angle * math.pi / 180) * 100), round(math.sin(self.angle * math.pi / 180) * 100)
        self.angle = (self.angle + 1) % 360
        self.image.fill(0)
        pygame.draw.line(self.image, (255, 255, 0), (100 - vec[0], 100 - vec[1]), (100 + vec[0], 100 + vec[1]), 5)
        self.mask = pygame.mask.from_surface(self.image)
        
pygame.init()
window = pygame.display.set_mode((500, 500))
clock = pygame.time.Clock()

sprite_image = pygame.image.load('AirPlane.png').convert_alpha()
moving_object = SpriteObject(0, 0, sprite_image)
line_object = Line(*window.get_rect().center)
all_sprites = pygame.sprite.Group([moving_object, line_object])
red = 0

run = True
while run:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
 
    all_sprites.update()

    if pygame.sprite.collide_mask(moving_object, line_object):
        red = min(255, red+4)
    else: 
        red = 0

    window.fill((red, 0, 0))
    all_sprites.draw(window)
    pygame.display.flip()

pygame.quit()
exit()


来源:https://stackoverflow.com/questions/34456195/make-a-line-as-a-sprite-with-its-own-collision-in-pygame

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!