I'm programming a Flappy Bird and I'm almost done, but I only miss one thing: the collisions between the bird and the pipes ... I managed to make sure that if the bird hit the ground or disappears from the screen, the game is over (thanks to the function fin() ). I would like the game to end also if the bird touches the pipes but I can not do it and people who ask for such a thing use, generally, Pygame :(.
Thank you in advance for your help in hoping that the solution is simple but that I just did not find it.
I tried to manage the collisions alone (we can see the corresponding part in my program) but the bird stops randomly ...
Here are the pictures of the game (it's a mediafire link to download the zip file of the pictures)!
from tkinter import *
import random
from random import randint
def sauter(event):
canvas.move(image_oiseau, 0, -10*DY)
def deplacement():
global mouvement
global tuyx,tuyx2,h,H,oisx,oisy,solx,sol2x,score
x0, y0, x1, y1 = canvas.bbox(image_oiseau)
if y1 < 416 :
canvas.move(image_oiseau, 0, DY)
else :
fin()
if y1<=-5:
fin()
#Here are the parts supposed to handle collisions ...
if y1 >= h :
fin()
if y1 >= H :
fin()
if y0<=h-379.8:
fin()
if y0<=h-379.8:
fin()
#That's the end of the parts supposed to handle collsions...
canvas.coords(image_sol,solx,512)
if solx >= -144:
solx=solx-5
else:
solx=144
canvas.coords(image_sol2,sol2x,512)
if sol2x >= 144:
sol2x=sol2x-5
else:
sol2x=432
canvas.coords(image_tuyau_haut,tuyx,h)
canvas.coords(image_tuyau_bas,tuyx,h-379.8)
if tuyx>=-28:
tuyx=tuyx-5
else:
tuyx=316
h=randint(272,523)
score+=1
canvas.coords(image_tuyau_haut2,tuyx2,H)
canvas.coords(image_tuyau_bas2,tuyx2,H-379.8)
if tuyx2>=-28:
tuyx2=tuyx2-5
else:
tuyx2=316
H=randint(272,523)
score+=1
lscore.config(text=str(score))
mouvement =canvas.after(40,deplacement)
def debut():
pause=1
if pause==1:
M.destroy()
deplacement()
canvas.bind("<space>",sauter)
def fin():
pause=0
if pause==0:
canvas.after_cancel(mouvement)
canvas.unbind("<space>",sauter)
def rejouer():
global tuyx,tuyx2,oisx,oisy,solx,sol2x,score
tuyx=316
tuyx2=488
oisx=67
oisy=244
solx=144
sol2x=432
score=0
LARGEUR = 286
HAUTEUR = 510
DY = 5
tuyx=316
tuyx2=488
h=randint(272,523)
H=randint(272,523)
oisx=67
oisy=244
solx=144
sol2x=432
score=0
mouvement=None
fenetre = Tk()
canvas = Canvas(fenetre, width=LARGEUR, height=HAUTEUR)
fond = PhotoImage(file="background-day.png")
fond2 = PhotoImage(file="background-night.png")
fond=[fond,fond2]
F= random.choice(fond)
canvas.create_image(144,256, anchor=CENTER,image=F)
tuyau_haut = PhotoImage(file="tuyau_vers_le_haut.png")
image_tuyau_haut = canvas.create_image(tuyx,h,anchor=CENTER,image=tuyau_haut)
image_tuyau_haut2 = canvas.create_image(tuyx2,H,anchor=CENTER,image=tuyau_haut)
tuyau_bas = PhotoImage(file="tuyau_vers_le_bas.png")
image_tuyau_bas = canvas.create_image(tuyx,h,anchor=CENTER,image=tuyau_bas)
image_tuyau_bas2 = canvas.create_image(tuyx2,H,anchor=CENTER,image=tuyau_bas)
sol = PhotoImage(file="sol-day.png")
image_sol = canvas.create_image(144,512, anchor=S,image=sol)
image_sol2 = canvas.create_image(432,512, anchor=S,image=sol)
oiseau = PhotoImage(file="yellowbird-midflap.png")
oiseau2 = PhotoImage(file="bluebird-midflap.png")
oiseau3 = PhotoImage(file="redbird-midflap.png")
oiseau=[oiseau,oiseau2,oiseau3]
O=random.choice(oiseau)
image_oiseau=canvas.create_image(oisx,oisy, anchor=W,image=O)
lscore=Label(fenetre,text='0')
lscore.pack()
menu_debut=PhotoImage(file="menu_jeu.png")
M=Button(fenetre,image=menu_debut,relief=FLAT,command=debut)
Menu_w = canvas.create_window(144,256,window=M)
canvas.pack()
canvas.focus_set()
fenetre.mainloop()
You have two approaches:
1- Determine which coordinates to check for a collision with the bird perimeter, safe zones, top and bottom y, width of the pipes, movement of the pipes, and other obstacles, etc. all quite interesting to implement and check, but a bit tedious and prone to errors.
2- Take advantage of the power of tkinter canvas, and use the method find_overlapping(x0, y0, x1, y1)
that returns a tuple of all items that overlap the given rectangle, or that are completely enclosed by it, and use this to determine if a collision has occurred, maybe with the use of a tag
to mark the obstacles.
My suggestion is to use find_overlapping
.
maybe something like this (pseudocode)
obstacles = canvas.find_withtag('obstacle')
for item in canvas.find_overlapping(canvas.coords(bird)):
if item in obstacles:
bird.is_dead()