Reputation: 367
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
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