I have a school project for Pygame over the winter break, as a summative. I made the basis of the game (Flappy Bird), but the problem is that the collisions aren't working properly. The problem is that it counts going through the pipes as a collision.
Could you guys please check my code and fix it up?
import pygame
import sys
import math
import random
from pygame.locals import *
a=320
b=240
da=1
db=0
x=25
y=25
e=50
da2=0
c=200
d=10
c_change=0
d_change=0
clock = pygame.time.Clock()
bg=(36,38,82)
wood=(253,197,136)
green=(79, 255, 101)
pipe=(152,228,86)
end=(137, 226, 57)
bg1=(40,42,86)
gold=(219,178,58)
golden=(254, 197, 34)
golder=(255, 206, 63)
black=(0,0,0)
red=(255, 47, 47)
white=(255,255,255)
pygame.init()
screen = pygame.display.set_mode((1400,700))
class Wall(pygame.sprite.Sprite):
def __init__(self, x, y, width, height):
super().__init__()
self.image = pygame.Surface([width, height])
self.image.fill(GREY)
self.rect = self.image.get_rect()
self.rect.y = y
self.rect.x = x
crashFlag=0
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type==pygame.KEYDOWN:
if event.key==pygame.K_SPACE:
c_change=-1
d_change=1
if event.type==pygame.KEYUP:
if event.key==pygame.K_SPACE:
c_change=1
if event.type==pygame.KEYDOWN:
crashFlag==0
c+=c_change
d+=d_change
screen.fill(bg)
pygame.draw.rect(screen,bg1, (0,350,1400,350), 0)
pygame.draw.circle(screen,white, (d,c),5)
#for f in range(195, 390 ,5):
if d>200 and d<275:
if c>340:
crashFlag=1
pygame.draw.rect(screen,end, (195,300,80,40), 0)
pygame.draw.rect(screen,pipe, (200,0,70,300), 0)
pygame.draw.rect(screen,pipe, (350,0,70,450), 0)
pygame.draw.rect(screen,end, (345,420,80,40), 0)
pygame.draw.rect(screen,pipe, (490,0,70,480), 0)
pygame.draw.rect(screen,end, (485,480,80,40), 0)
pygame.draw.rect(screen,pipe, (630,0,70,450), 0)
pygame.draw.rect(screen,end, (625,450,80,40), 0)
pygame.draw.rect(screen,pipe, (770,0,70,430), 0)
pygame.draw.rect(screen,end, (765,420,80,40), 0)
pygame.draw.rect(screen,pipe, (910,0,70,400), 0)
pygame.draw.rect(screen,end, (905,400,80,40), 0)
pygame.draw.rect(screen,pipe, (1050,0,70,470), 0)
pygame.draw.rect(screen,end, (1045,470,80,40), 0)
pygame.draw.rect(screen,pipe, (1190,0,70,430), 0)
pygame.draw.rect(screen,end, (1185,430,80,40), 0)
pygame.draw.rect(screen,gold, (1330,0,70,410), 0)
pygame.draw.rect(screen,golder, (1350,0,70,410), 0)
pygame.draw.rect(screen,golden, (1325,410,80,40), 0)
pygame.draw.rect(screen,pipe, (200,400,70,240), 0)
#lower pipes
pygame.draw.rect(screen,end, (195,400,80,40), 0)
pygame.draw.rect(screen,pipe, (350,520,70,500), 0)
pygame.draw.rect(screen,end, (345,515,80,40), 0)
pygame.draw.rect(screen,pipe, (490,570,70,100), 0)
pygame.draw.rect(screen,end, (485,570,80,40), 0)
pygame.draw.rect(screen,pipe, (630,570,70,100), 0)
pygame.draw.rect(screen,end, (625,540,80,40), 0)
pygame.draw.rect(screen,pipe, (770,550,70,120), 0)
pygame.draw.rect(screen,end, (765,510,80,40), 0)
pygame.draw.rect(screen,pipe, (910,530,70,220), 0)
pygame.draw.rect(screen,end, (905,490,80,40), 0)
pygame.draw.rect(screen,pipe, (1050,560,70,220), 0)
pygame.draw.rect(screen,end, (1045,560,80,40), 0)
pygame.draw.rect(screen,pipe, (1190,530,70,220), 0)
pygame.draw.rect(screen,end, (1185,530,80,40), 0)
pygame.draw.rect(screen,gold, (1330,530,70,220), 0)
pygame.draw.rect(screen,golder, (1350,530,70,220), 0)
pygame.draw.rect(screen,golden, (1325,510,80,40), 0)
pygame.draw.rect(screen, wood, (0,650,1400,50), 0)
pygame.draw.rect(screen,green, (0,640,1400,10), 0)
if crashFlag==1:
pygame.draw.rect(screen,white, (0,0,1400,700), 0)
font = pygame.font.SysFont("Berlin Sans FB Demi", 100, True, False)
text = font.render("You Lost", True, black)
screen.blit(text, (500, 100))
pygame.draw.rect(screen,green, (600,400,190,60), 0)
font = pygame.font.SysFont("Aharoni", 50, True, False)
text = font.render("RESET", True, white)
screen.blit(text, (630, 410))
pygame.display.update()
clock.tick(150)
pygame.quit()
There is too many changes to describe them all.
I keep all pipes on list all_pipes
as (END, pygame.Rect(195,300,80,40))
and then I can use for
loop to draw them
for pipe_color, pipe_rect in all_pipes:
pygame.draw.rect(screen, pipe_color, pipe_rect, 0)
and to check collision with player.
for pipe_color, pipe_rect in all_pipes:
if pipe_rect.collidepoint(player_x, player_y):
state = STATE_GAMEOVER
break # no need to check other
Full code
import pygame
# --- constants --- (UPPER_CASE_NAMES)
# - colors -
BACKGROUND_0 = (36, 38, 82)
BACKGROUND_1 = (40, 42, 86)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 47, 47)
GREEN = (79, 255, 101)
WOOD = (253, 197, 136)
PIPE = (152, 228, 86)
END = (137, 226, 57)
GOLD = (219, 178, 58)
GOLDEN = (254, 197, 34)
GOLDER = (255, 206, 63)
# - states -
STATE_INTRO = 1
STATE_GAME = 2
STATE_GAMEOVER = 3
# --- classes --- (CamelCaseNames)
#class Wall(pygame.sprite.Sprite):
#
# def __init__(self, x, y, width, height):
# super().__init__()
#
# self.image = pygame.Surface((width, height))
# self.image.fill(GREY)
#
# self.rect = self.image.get_rect()
# self.rect.y = y
# self.rect.x = x
# --- functions --- (lower_case_names)
# empty
# --- main ---
# - init -
pygame.init()
screen = pygame.display.set_mode((1400,700))
font1 = pygame.font.SysFont("Berlin Sans FB Demi", 100, True, False)
text1 = font1.render("You Lost", True, BLACK)
font2 = pygame.font.SysFont("Aharoni", 50, True, False)
text2 = font2.render("RESET", True, WHITE)
# - objects -
player_y = 200
player_x = 10
x_change = 5
y_change = 0
all_pipes = [
#upper pipes
(END, pygame.Rect(195,300,80,40)),
(PIPE, pygame.Rect(200,0,70,300)),
(PIPE, pygame.Rect(350,0,70,450)),
(END, pygame.Rect(345,420,80,40)),
(PIPE, pygame.Rect(490,0,70,480)),
(END, pygame.Rect(485,480,80,40)),
(PIPE, pygame.Rect(630,0,70,450)),
(END, pygame.Rect(625,450,80,40)),
(PIPE, pygame.Rect(770,0,70,430)),
(END, pygame.Rect(765,420,80,40)),
(PIPE, pygame.Rect(910,0,70,400)),
(END, pygame.Rect(905,400,80,40)),
(PIPE, pygame.Rect(1050,0,70,470)),
(END, pygame.Rect(1045,470,80,40)),
(PIPE, pygame.Rect(1190,0,70,430)),
(END, pygame.Rect(1185,430,80,40)),
(GOLD, pygame.Rect(1330,0,70,410)),
(GOLDER, pygame.Rect(1350,0,70,410)),
(GOLDEN, pygame.Rect(1325,410,80,40)),
(PIPE, pygame.Rect(200,400,70,240)),
#lower pipes
(END, pygame.Rect(195,400,80,40)),
(PIPE, pygame.Rect(350,520,70,500)),
(END, pygame.Rect(345,515,80,40)),
(PIPE, pygame.Rect(490,570,70,100)),
(END, pygame.Rect(485,570,80,40)),
(PIPE, pygame.Rect(630,570,70,100)),
(END, pygame.Rect(625,540,80,40)),
(PIPE, pygame.Rect(770,550,70,120)),
(END, pygame.Rect(765,510,80,40)),
(PIPE, pygame.Rect(910,530,70,220)),
(END, pygame.Rect(905,490,80,40)),
(PIPE, pygame.Rect(1050,560,70,220)),
(END, pygame.Rect(1045,560,80,40)),
(PIPE, pygame.Rect(1190,530,70,220)),
(END, pygame.Rect(1185,530,80,40)),
(GOLD, pygame.Rect(1330,530,70,220)),
(GOLDER, pygame.Rect(1350,530,70,220)),
(GOLDEN, pygame.Rect(1325,510,80,40)),
(WOOD, pygame.Rect(0,650,1400,50)),
(GREEN, pygame.Rect(0,640,1400,10)),
]
# - mainloop -
state = STATE_INTRO # STATE_GAME, STATE_GAMEOVER
clock = pygame.time.Clock()
done = False
while not done:
# - events -
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if state == STATE_INTRO:
if event.type == pygame.KEYDOWN:
state = STATE_GAME
elif state == STATE_GAME:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
y_change = -5
elif event.type == pygame.KEYUP:
if event.key == pygame.K_SPACE:
y_change = 5
elif state == STATE_GAMEOVER:
if event.type == pygame.KEYDOWN:
state = STATE_INTRO
player_y = 200
player_x = 10
# - updates (without draws) -
if state == STATE_GAME:
player_x += x_change
player_y += y_change
# check collisions with all pipes
for pipe_color, pipe_rect in all_pipes:
if pipe_rect.collidepoint(player_x, player_y):
state = STATE_GAMEOVER
break # no need to check other
# - draws (without updates) -
if state in (STATE_INTRO, STATE_GAME):
screen.fill(BACKGROUND_0)
pygame.draw.rect(screen, BACKGROUND_1, (0, 350, 1400, 350), 0)
# draw all pipes
for pipe_color, pipe_rect in all_pipes:
pygame.draw.rect(screen, pipe_color, pipe_rect, 0)
pygame.draw.circle(screen, WHITE, (player_x, player_y), 5)
if state == STATE_GAMEOVER:
screen.fill(WHITE)
screen.blit(text1, (500, 100))
pygame.draw.rect(screen, GREEN, (600, 400, 190, 60), 0)
screen.blit(text2, (630, 410))
pygame.display.update()
clock.tick(25)
# - end -
pygame.quit()