Tkinter event using arrow keys

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • TMS
    New Member
    • Sep 2006
    • 119

    Tkinter event using arrow keys

    Hey all:

    I'm working on this 'pac man' like game I've been writing in Tkinter. The temporary gif I'm using (I can't attach it, sorry) goes around the maze based on a dictionary that has each path location as the key, and alternate, or connecting locations as the definition to the key. Now I need to 'interrupt' the path and give it a new path based on a keyboard event, like an arrow up, left, down or right. At the next key point if there is a keyboard event, the gif should respond to the keyboard event, not the default path. I sure hope that makes sense.

    I know I that the path updates every loop (the function is move_gif) and I should be able to tell it that if there is a keyboard event before the next point, it should do something, but I'm just not sure what that 'do something' should be. Can't wrap my brain around it.

    In order to run the program you will need a gif, but I can't attach the one I'm using. I suppose you could use any .gif you have, but it needs to be in the same file as this program.

    I could use some ideas... ?

    Code:
    """
    Build the maze and pathway
    """
    from Tkinter import *
    import time
    root = Tk()
    root.title("Background")
    canvasOne = Canvas(width = 800, height = 700, bg = 'black')
    canvasOne.pack()
    def createWall((x0, y0), (x1, y1), colour = 'blue', width = 3):
    	""" create a double wall outlining the maze. """
    	canvasOne.create_line(x0, y0, x1, y1, width = width, fill = colour)
    	canvasOne.create_line(350, 630, 450, 630, width = 3, fill = 'gold', tag = 'gate')
    def buildPathHorizontal((val1, val2, number), increment = 20, delta = 5):
    	""" build the horizontal path through the maze, small white squares"""
    	for i in range(number):
    		val1 += increment
    		x, y = val1, val2
    		deltax = x + delta
    		deltay = y + delta
    		canvasOne.create_rectangle(x, y, deltax, deltay, fill = 'white')
    def buildPathVertical((val1, val2, number), increment = 20, delta = 5):
    	""" build the vertical path through the maze, small white squares"""
    	for i in range(number):
    		val2 += increment
    		x, y = val1, val2
    		deltax = x + delta
    		deltay = y + delta
    		canvasOne.create_rectangle(x, y, deltax, deltay, fill = 'white')
     
    outerWall = [(450, 640), (475, 640), (475, 640), (475, 690), (475, 690), (790, 690), (790, 690),
    				 (790, 530), (790, 530), (660, 530), (660, 530), (660, 360), (790, 360), (790, 10), (790, 10),
    				 (10, 10), (10, 10), (10, 360), (10, 360), (150, 360), (150, 360), (150, 530), (150, 530),
    				 (10, 530), (10, 530), (10, 690), (10, 690), (325, 690), (325, 690), (325, 640), (325, 640),
    				 (350, 640), (350, 630), (350, 630), (315, 630), (315, 680), (20, 680), (20, 680), (20, 560),
    			 (20, 540), (160, 540), (160, 540), (160, 350), (20, 350), (20, 350), (20, 20), (20, 20),
    			 (380, 20), (380, 20), (380, 130), (380, 130), (420, 130), (420, 130), (420, 20), (420, 20),
    			 (780, 20), (780, 350), (780, 350), (650, 350), (650, 350), (650, 540), (650, 540), (780, 540),
    			 (780, 540), (780, 680), (780, 680), (485, 680), (485, 630), (485, 630), (450, 630), (450, 630),
    			 (450, 640)]
    topLeftBox = [(130, 105), (130, 125), (130, 125), (250, 125), (250, 125), (250, 105),
    					(130, 105), (250, 105)]
    secondTopLeftBox = [(160, 215), (160, 225), (160, 215), (230, 215), (230, 215),
    					(230, 225), (160, 225), (230, 225)]
    topRightBox = [(545, 105), (545, 125), (545, 125), (665, 125), (665, 125), (665, 105), 
    			 (545, 105), (665, 105)]
    secondTopRightBox = [(560, 215), (560, 225), (560, 215), (625, 215), (625, 215), (625, 225),
    					 (625, 225), (560, 225)]
    middleT = [(345, 240), (455, 240), (345, 240), (345, 240), (345, 250), (395, 250), (395, 250), (395, 335),
    		 (395, 335), (405, 335), (405, 335), (405, 250), (405, 250), (455, 250), (455, 250), (455, 240)]
    leftSidewaysT = [(275, 340), (275, 500), (275, 340), (285, 340), (285, 340), (285, 415), (285, 415), (345, 415),
    				 (345, 415), (345, 425), (285, 425), (345, 425), (285, 425), (285, 500), (275, 500), (285, 500)]
    rightSidewaysT = [(525, 340), (525, 500), (525, 340), (515, 340), (515, 340), (515, 415), (515, 415), (455, 415),
    				 (455, 415), (455, 425), (515, 425), (455, 425), (515, 425), (515, 500), (515, 500), (525, 500)]
    walls = [outerWall] 
    for wall in walls: 
    	for i in range(len(wall) - 1):
    		createWall(outerWall[i], outerWall[i+1])	
    boxes = [topLeftBox, secondTopLeftBox, topRightBox, secondTopRightBox]
    for box in boxes:
    	for i in range(len(box)-1):
    		createWall(topLeftBox[i], topLeftBox[i+1]),
    		createWall(secondTopLeftBox[i], secondTopLeftBox[i+1]),
    		createWall(topRightBox[i], topRightBox[i+1]),
    		createWall(secondTopRightBox[i], secondTopRightBox[i+1])
    Ts = [middleT, leftSidewaysT, rightSidewaysT]
    for t in Ts:
    	for i in range(len(t)-1):
    		createWall(middleT[i], middleT[i+1]),
    		createWall(leftSidewaysT[i], leftSidewaysT[i+1]),
    		createWall(rightSidewaysT[i], rightSidewaysT[i+1])
     
    horizontalPath = [(40, 610, 9), (60, 290, 14), (60, 50, 12), (60, 170, 33), (440, 290, 1),
    					 (440, 290, 14), (480, 50, 12), (320, 370, 6), (300, 510, 9), (220, 570, 5), (460, 570, 5), (580, 610, 8),
    				 (0,0,0)]
    verticalPath = [(60, 30, 13), (220, 290, 15), (300, 50, 11), (500, 30, 13), (340, 290, 4), (340, 290, 4),
    				(400, 370, 6), (320, 510, 3), (460, 290, 4), (480, 510, 3), (580, 290, 16), (720, 30, 13), (0,0,0)]
    paths = [horizontalPath, verticalPath]
    for path in paths:
    	for i in range(len(path)-1):
    		buildPathHorizontal(horizontalPath[i]),
    		buildPathVertical(verticalPath[i])
     
    image = 'DustY.gif'
    photo = PhotoImage(file=image)
    xGif = 100
    yGif = 610
    ph = canvasOne.create_image(xGif, yGif, image = photo)
    graph = {(100, 610) : [(270, 610)],
    		 (270, 610) : [(270, 280), (270, 560), (100, 610)],
    		 (270, 560) : [(400, 550), (370, 560), (270, 280), (270, 610)],
    		 (270, 280) : [(110, 280), (300, 290), (380, 290), (270, 610)],
    		 (370, 560) : [(370, 500), (270, 280)],
    		 (370, 500) : [(450, 500), (370, 560)],
    		 (450, 500) : [(390, 300), (450, 370), (370, 500)],
    		 (450, 370) : [(390, 370), (450, 500)],
    		 (390, 370) : [(390, 290), (450, 370)],
    		 (390, 290) : [(350, 290), (390, 370)],
    		 (350, 290) : [(350, 170), (110, 280), (390, 290)],
    		 (350, 170) : [(110, 170), (350, 290), (350, 290)],
    		 (110, 280) : [(110, 170), (110, 40), (270, 280)],
    		 (110, 170) : [(350, 170), (110, 280)],
    		 (110, 40) : [(350, 40), (110, 170), (110, 280)],
    		 (350, 40) : [(350, 170), (110, 40)],
    		 (350, 170) : [(550, 170), (110, 170), (350, 40)],
    		 (550, 170) : [(550, 40), (550, 280), (350, 170), (750, 170)],
    		 (550, 40) : [(770, 40), (550, 40)],
    		 (550, 280) : [(510, 280), (520, 200), (520, 40)],
    		 (510, 280) : [(510, 360), (550, 280)],
    		 (510, 360) : [(450, 370), (510, 280)],
    		 (770, 40) : [(770, 280), (770, 170), (550, 40)],
    		 (770, 280) : [(630, 280), (550, 280), (470, 280), (770, 40)],
    		 (630, 280) : [(630, 610), (550, 280), (470, 280), (770, 280)],
    		 (630, 610) : [(790, 610), (630, 560), (630, 570), (630, 280)],
    		 (630, 560) : [(530, 560), (630, 280), (630, 610)],
    		 (530, 560) : [(530, 500), (630, 560)],
    		 (530, 500) : [(450, 500), (530, 370)],
    		 (450, 500) : [(450, 350), (530, 500)],
    		 (790, 610) : [(630, 610)]}
    """
    find_all_paths is a greedy algorithm based function that will get the .gif moving on the
    path. It returns the path for the .gif to follow. 
    """
    def find_all_paths(graph, start, end, path=[]):
    		path = path + [start]
    		if start == end:
    			return [path]
    		if not graph.has_key(start):
    			return []
    		paths = []
    		for node in graph[start]:
    			if node not in path:
    				newpaths = find_all_paths(graph, node, end, path)
    				for newpath in newpaths:
    					paths.append(newpath)
    		return paths
    def move_gif(pic, x = xGif, y = yGif):
    	endX = 790
    	endY = 610
    	mode = .001
    	path = find_all_paths(graph, (x, y), (endX, endY))
    	try:
    		for i in path[7]:
    			dest = list(i)
    			newX = dest[0]
    			newY = dest[1]
    			if newX == x:
    				while y != newY:
    					if y > newY:
    						y -= 2
    						canvasOne.coords(pic, x, y)
    						time.sleep(mode)
    						canvasOne.update()
    						path = find_all_paths(graph, (x, y), (endX, endY))
    					if y < newY:
    						y+=2
    						canvasOne.coords(pic, x, y)
    						time.sleep(mode)
    						canvasOne.update()
    						path = find_all_paths(graph, (x, y), (endX, endY))
    			if newY == y:
    				while x != newX:
    					if x > newX:
    						x -= 2
    						canvasOne.coords(pic, x, y)
    						time.sleep(mode)
    						canvasOne.update()
    						path = find_all_paths(graph, (x, y), (endX, endY))
    					if x < newX:
    						x += 2
    						canvasOne.coords(pic, x, y)
    						time.sleep(mode)
    						canvasOne.update()
    						path = find_all_paths(graph, (x, y), (endX, endY))
    	except IndexError:
    		print 'path: ' , path
    		print "out of range"
     
    move_gif(ph)		
    root.mainloop()
  • bartonc
    Recognized Expert Expert
    • Sep 2006
    • 6478

    #2
    Originally posted by TMS
    I know I that the path updates every loop (the function is move_gif) and I should be able to tell it that if there is a keyboard event before the next point, it should do something, but I'm just not sure what that 'do something' should be. Can't wrap my brain around it.
    After thinking about it for a little while, it seems that with one (or maybe two) variable(s) that has (have) a positive or a negative (and maybe zero, for "don't care") value, your path could be reversed by looking at that variable each time through the loop. Then, in your event handler for the arrow keys, set the value of those variables accordingly.

    Comment

    • TMS
      New Member
      • Sep 2006
      • 119

      #3
      hmmm... that is interesting. Create a 'flag' that says an event has occured, and stop the gif at the next vertex (if that is what it is called). Then update the base path and continue on its way. Hmmmm. Very interesting.

      I'll give it a try and report back.

      Thanks!

      tms

      Comment

      • bartonc
        Recognized Expert Expert
        • Sep 2006
        • 6478

        #4
        Originally posted by TMS
        hmmm... that is interesting. Create a 'flag' that says an event has occured, and stop the gif at the next vertex (if that is what it is called). Then update the base path and continue on its way. Hmmmm. Very interesting.

        I'll give it a try and report back.

        Thanks!

        tms
        A lot depends on how[CODE=python]
        time.sleep(mode )
        canvasOne.updat e()
        [/CODE]works. I think that calling update() will be enough for your keyboard events to get processed, but I'm not sure about that.

        Comment

        Working...