问题
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