I was tinkering with PyGame, reading articles, and I came across this weird phenomenon. For some reason, pygame.colliderect returns True
when the two sprites aren't touching.Code:
import pygame
pygame.init()
screen = pygame.display.set_mode((400, 300))
running = True
spriteX = 100
spriteY = 100
spriteVY = 3
clock = pygame.time.Clock()
class Sprite(pygame.sprite.Sprite):
def __init__(self):
super(Sprite, self).__init__()
self.vel = (0, 0)
self.surf = pygame.Surface((100, 200))
self.surf.fill((255, 255, 255))
self.rectangle = self.surf.get_rect()
class Platform(pygame.sprite.Sprite):
def __init__(self):
super(Platform, self).__init__()
self.surf = pygame.Surface((200, 10))
self.surf.fill((142, 212, 25))
self.rectangle = self.surf.get_rect()
on_ground = True
while running:
platform_group = pygame.sprite.Group()
platform_group.add(Platform())
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if pygame.key.get_pressed()[pygame.K_SPACE]: spriteY -= 10
if pygame.key.get_pressed()[pygame.K_d]: spriteX += 10
if pygame.key.get_pressed()[pygame.K_a]: spriteX -= 10
print((Platform().rectangle.colliderect(Sprite().rectangle)))
screen.fill((0, 0, 0))
if spriteX >= 300:
spriteX = 300
if spriteX <= 0:
spriteX = 0
if not on_ground:
spriteY += spriteVY
spriteVY -= 3
screen.blit(Sprite().surf, ((spriteX, spriteY)))
screen.blit(Platform().surf, ((50, 20)))
pygame.display.flip()
clock.tick(24)
A pygame.Surface
has no position. Hence the position of the pygame.Rect
object which is returned by get_rect()
is (0, 0).
Note you have to specify the position when the Surface is blit()
.
Specify the position by an keyword argument, when the the rectangle is get from the surface.
Create instances of the objects before the main application loop (see Instance Objects) and add them to a pygame.sprite.Group
. Each pygame.sprite.Sprite
should have the attributes .rect
and .image
which are used by the method draw()
of the group.
Get ride of the global variables spriteX
and spriteY
and use the .rect
attribute of the sprites.
For instance:
import pygame
pygame.init()
screen = pygame.display.set_mode((400, 300))
running = True
spriteVY = 3
clock = pygame.time.Clock()
class MySprite(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.vel = (0, 0)
self.image = pygame.Surface((100, 200))
self.image.fill((255, 255, 255))
self.rect = self.image.get_rect(topleft = (x, y))
class Platform(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.image = pygame.Surface((200, 10))
self.image.fill((142, 212, 25))
self.rect = self.image.get_rect(topleft = (x, y))
sprite = MySprite(100, 100)
platform = Platform(50, 20)
group = pygame.sprite.Group([sprite, platform])
on_ground = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if pygame.key.get_pressed()[pygame.K_SPACE]: sprite.rect.y -= 10
if pygame.key.get_pressed()[pygame.K_d]: sprite.rect.x += 10
if pygame.key.get_pressed()[pygame.K_a]: sprite.rect.x -= 10
if platform.rect.colliderect(sprite.rect):
print("hit")
if sprite.rect.x >= 300:
sprite.rect.x = 300
if sprite.rect.x <= 0:
sprite.rect.x = 0
if not on_ground:
sprite.rect.y += spriteVY
spriteVY -= 3
screen.fill((0, 0, 0))
group.draw(screen)
pygame.display.flip()
clock.tick(24)