Colliderect seems to get triggered based on height
Question:
Currently I am trying to make flappy bird in pygame, but I have stumbled upon an issue where if the bird goes lower than the top of the lower pipe, it detects it as a collision. I also used collidelist
as my pipe objects are stored in a list, to no avail. Heres the collision code:
def collide(self):
for pipe_rect in pipes:
if self.rect.colliderect(pipe_rect):
pipe.set_scroll(0)
pipe2.set_scroll(0)
print("You are dead, no big suprise")
self.death = True
Here is all the code too if that helps:
import pygame, sys
from pygame.locals import QUIT
import random
WHITE = (255, 255, 255)
YELLOW = (255, 255, 0)
GREY = (100, 100, 100)
CLOCK = pygame.time.Clock()
class Bird:
def __init__(self):
self.__x = 20
self.__y = screen_y / 2
self.__vel = 16
self.death = False
def flap(self):
self.__vel = 16
def gravity(self):
self.__y -= self.__vel
self.__vel -= 2
if self.__vel > 15:
self.__vel = 15
if self.__y > (screen_y - 50):
self.__y = screen_y - 50
def draw(self):
self.rect = pygame.draw.rect(DISPLAYWINDOW, YELLOW, (self.__x, self.__y, 50, 50))
def collide(self):
for pipe_rect in pipes:
if self.rect.colliderect(pipe_rect):
pipe.set_scroll(0)
pipe2.set_scroll(0)
print("damn you collision")
self.death = True
class Pipe:
def __init__(self, x):
self.__x = x
self.__y = 300
self.__w = 70
self.__h = 700
self.__scroll = 7.5 #world scroll
def get_w(self):
return self.__w
def set_scroll(self, x):
self.__scroll = x
def move(self):
self.__x -= self.__scroll
def draw(self):
pipes.append(pygame.draw.rect(DISPLAYWINDOW, WHITE, (self.__x, self.__y, self.__w, self.__h))) #bottom
#pipes.append(pygame.draw.rect(DISPLAYWINDOW, WHITE, (self.__x, ((self.__y - self.__h) - 250), self.__w, self.__h))) #top 150 is 3x bird height
def generation(self):
if self.__x < 0 - self.__w:
self.__y = random.randint(275, 450)
self.__x = screen_x + self.__w
pipes = []
pygame.init()
screen_x = 500
screen_y = 700
DISPLAYWINDOW = pygame.display.set_mode((screen_x, screen_y))
bird = Bird()
pipe = Pipe(screen_x)
pipe2 = Pipe((screen_x * 1.5) + pipe.get_w())
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE and bird.death == False:
bird.flap()
DISPLAYWINDOW.fill(GREY)
bird.draw()
bird.gravity()
bird.collide()
pipe.draw()
pipe2.draw()
pipe.move()
pipe2.move()
pipe.generation()
pipe2.generation()
pygame.display.update()
CLOCK.tick(30)
Answers:
The problem is that the pipes
list is filled with pipes that are never removed. You can easily test this by inserting print(len(pipe))
into the application loop.
You must create or delete the pipe list in the application loop before adding the new pipes:
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE and bird.death == False:
bird.flap()
# clear screen
DISPLAYWINDOW.fill(GREY)
# clear pipes
pipes.clear()
# draw pipes and add new pipes to list
pipe.draw()
pipe2.draw()
print(len(pipes))
# draw bird and collision detection
bird.draw()
bird.collide()
# move objects
bird.gravity()
pipe.move()
pipe2.move()
# generate new objects
pipe.generation()
pipe2.generation()
pygame.display.update()
CLOCK.tick(30)
Currently I am trying to make flappy bird in pygame, but I have stumbled upon an issue where if the bird goes lower than the top of the lower pipe, it detects it as a collision. I also used collidelist
as my pipe objects are stored in a list, to no avail. Heres the collision code:
def collide(self):
for pipe_rect in pipes:
if self.rect.colliderect(pipe_rect):
pipe.set_scroll(0)
pipe2.set_scroll(0)
print("You are dead, no big suprise")
self.death = True
Here is all the code too if that helps:
import pygame, sys
from pygame.locals import QUIT
import random
WHITE = (255, 255, 255)
YELLOW = (255, 255, 0)
GREY = (100, 100, 100)
CLOCK = pygame.time.Clock()
class Bird:
def __init__(self):
self.__x = 20
self.__y = screen_y / 2
self.__vel = 16
self.death = False
def flap(self):
self.__vel = 16
def gravity(self):
self.__y -= self.__vel
self.__vel -= 2
if self.__vel > 15:
self.__vel = 15
if self.__y > (screen_y - 50):
self.__y = screen_y - 50
def draw(self):
self.rect = pygame.draw.rect(DISPLAYWINDOW, YELLOW, (self.__x, self.__y, 50, 50))
def collide(self):
for pipe_rect in pipes:
if self.rect.colliderect(pipe_rect):
pipe.set_scroll(0)
pipe2.set_scroll(0)
print("damn you collision")
self.death = True
class Pipe:
def __init__(self, x):
self.__x = x
self.__y = 300
self.__w = 70
self.__h = 700
self.__scroll = 7.5 #world scroll
def get_w(self):
return self.__w
def set_scroll(self, x):
self.__scroll = x
def move(self):
self.__x -= self.__scroll
def draw(self):
pipes.append(pygame.draw.rect(DISPLAYWINDOW, WHITE, (self.__x, self.__y, self.__w, self.__h))) #bottom
#pipes.append(pygame.draw.rect(DISPLAYWINDOW, WHITE, (self.__x, ((self.__y - self.__h) - 250), self.__w, self.__h))) #top 150 is 3x bird height
def generation(self):
if self.__x < 0 - self.__w:
self.__y = random.randint(275, 450)
self.__x = screen_x + self.__w
pipes = []
pygame.init()
screen_x = 500
screen_y = 700
DISPLAYWINDOW = pygame.display.set_mode((screen_x, screen_y))
bird = Bird()
pipe = Pipe(screen_x)
pipe2 = Pipe((screen_x * 1.5) + pipe.get_w())
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE and bird.death == False:
bird.flap()
DISPLAYWINDOW.fill(GREY)
bird.draw()
bird.gravity()
bird.collide()
pipe.draw()
pipe2.draw()
pipe.move()
pipe2.move()
pipe.generation()
pipe2.generation()
pygame.display.update()
CLOCK.tick(30)
The problem is that the pipes
list is filled with pipes that are never removed. You can easily test this by inserting print(len(pipe))
into the application loop.
You must create or delete the pipe list in the application loop before adding the new pipes:
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE and bird.death == False:
bird.flap()
# clear screen
DISPLAYWINDOW.fill(GREY)
# clear pipes
pipes.clear()
# draw pipes and add new pipes to list
pipe.draw()
pipe2.draw()
print(len(pipes))
# draw bird and collision detection
bird.draw()
bird.collide()
# move objects
bird.gravity()
pipe.move()
pipe2.move()
# generate new objects
pipe.generation()
pipe2.generation()
pygame.display.update()
CLOCK.tick(30)