pythonpython-3.xtkintertkinter-canvasflappy-bird-clone

How to handle collisions with coordinates? (in python)


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)!

Here are 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() 

Solution

  • 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()