user2658538
user2658538

Reputation: 367

How to find is a canvas item is touching another canvas item, Tkinter

I have a program where the user controls a block and navigates through pipes, similar to the game flappy bird. I want to know if tkinter has a way of telling me if one rectangle touches or hits another. I know there is a find_overlapping method for the canvas, but when i use find_overlapping on the pipe's rectangle it gives me the id of the pipe! I want to know if canvas items have a way of knowing if another canvas item is touching it!

Thanks

Here is my code:

from Tkinter import *
from random import *
root=Tk()
c=Canvas(root,width=600,height=600)
speed=20
num=1
first=True
b=0
pipes=[]
done=False
class Pipe():
    def __init__(self,canvas,pipes,length,width=75,color="Green",position=600,speed=5):
        self.speed=speed
        self.canvas=canvas
        self.length=length
        self.width=width
        self.color=color
        self.position=position
        self.current1=self.canvas.create_rectangle((self.position,0,self.position+self.width,self.length),outline=self.color,fill=self.color)
        self.current2=self.canvas.create_rectangle((self.position,600,self.position+self.width,self.length+150),outline=self.color,fill=self.color)
        self.pipes=pipes
        self.pipes.append(self.current1)
        self.pipes.append(self.current2)
    def move(self):
        global done
        if (len(self.canvas.find_overlapping(self.position,0,self.position+self.width,self.length))==1 and len(self.canvas.find_overlapping(self.position,600,self.position+self.width,self.length+150))==1) and not done:
            self.position-=3
            self.canvas.coords(self.current1,(self.position,0,self.position+self.width,self.length))
            self.canvas.coords(self.current2,(self.position,600,self.position+self.width,self.length+150))
            if self.position>-75:
                self.canvas.after(self.speed,self.move)
            else:
                self.pipes.remove(self.current1)
                self.pipes.remove(self.current2)
                self.canvas.delete(self.current1)
                self.canvas.delete(self.current2)
        else:
            print self.canvas.find_overlapping(self.position,0,self.position+self.width,self.length)
            print
            print self.canvas.find_overlapping(self.position,600,self.position+self.width,self.length+150)
            done=True
class Player():
    def __init__(self,canvas,x=150,y=300,size=40):
        self.size=size
        self.faller=True
        self.x=x
        self.y=y
        self.fell=5
        self.canvas=canvas
        #For now
        self.current=self.canvas.create_rectangle((self.x-20,self.y-20,self.x+20,self.y+20),tags="user",outline="Blue",fill="Blue")
        self.canvas.after(100,self.fall)
        self.canvas.bind("<1>",self.jump)
    def fall(self):
        global done
        if self.faller and not done:
            self.y+=self.fell
            self.fell*=1.001
            self.canvas.coords(self.current,(self.x-20,self.y-20,self.x+20,self.y+20))
            self.canvas.after(30,self.fall)
        elif done:
            a=600-self.y+20
            a/=50
            while self.y<580:
                self.y+=a
                self.canvas.coords(self.current,(self.x-20,self.y-20,self.x+20,self.y+20))

    def jump(self,e):
        if not done:
            self.faller=False
            for x in range(10):
                self.canvas.after(100,self.move)
            self.faller=True
            self.fell=5
    def move(self):
        self.y-=7.5
        self.canvas.coords(self.current,(self.x-20,self.y-20,self.x+20,self.y+20))
    def changey(self,a):
        self.y=a
def run():
    global b,first,done
    if not done:

        if first:
            b=randint(5,450)
            first=False
        else:
            if b<225:
                b=randint(5,b+225)
            if b>225:
                b=randint(b-225,450)
            else:
                b=randint(0,600)
        a=Pipe(c,pipes,b)
        a.move()
        c.after(2000,run)
    else:
        return
root.focus_set()
user=Player(c)
c.after(2000,run)
c.pack()
root.mainloop()

Upvotes: 2

Views: 2631

Answers (1)

FabienAndre
FabienAndre

Reputation: 4604

Canvas.find_overlapping return a tuple with all the ids of shapes in the bbox. If only your id is returned it might be because it is the sole one.

You can use it with the bbox of another shape like this : canvas.find_overlapping(*canvas.bbox(aShape)).

Note that overlapping works on rectangle and might be erroneous for instance on circles.

Upvotes: 3

Related Questions