By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
439,931 Members | 1,976 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 439,931 IT Pros & Developers. It's quick & easy.

Tkinter event using arrow keys

TMS
100+
P: 119
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... ?

Expand|Select|Wrap|Line Numbers
  1. """
  2. Build the maze and pathway
  3. """
  4. from Tkinter import *
  5. import time
  6. root = Tk()
  7. root.title("Background")
  8. canvasOne = Canvas(width = 800, height = 700, bg = 'black')
  9. canvasOne.pack()
  10. def createWall((x0, y0), (x1, y1), colour = 'blue', width = 3):
  11.     """ create a double wall outlining the maze. """
  12.     canvasOne.create_line(x0, y0, x1, y1, width = width, fill = colour)
  13.     canvasOne.create_line(350, 630, 450, 630, width = 3, fill = 'gold', tag = 'gate')
  14. def buildPathHorizontal((val1, val2, number), increment = 20, delta = 5):
  15.     """ build the horizontal path through the maze, small white squares"""
  16.     for i in range(number):
  17.         val1 += increment
  18.         x, y = val1, val2
  19.         deltax = x + delta
  20.         deltay = y + delta
  21.         canvasOne.create_rectangle(x, y, deltax, deltay, fill = 'white')
  22. def buildPathVertical((val1, val2, number), increment = 20, delta = 5):
  23.     """ build the vertical path through the maze, small white squares"""
  24.     for i in range(number):
  25.         val2 += increment
  26.         x, y = val1, val2
  27.         deltax = x + delta
  28.         deltay = y + delta
  29.         canvasOne.create_rectangle(x, y, deltax, deltay, fill = 'white')
  30.  
  31. outerWall = [(450, 640), (475, 640), (475, 640), (475, 690), (475, 690), (790, 690), (790, 690),
  32.                  (790, 530), (790, 530), (660, 530), (660, 530), (660, 360), (790, 360), (790, 10), (790, 10),
  33.                  (10, 10), (10, 10), (10, 360), (10, 360), (150, 360), (150, 360), (150, 530), (150, 530),
  34.                  (10, 530), (10, 530), (10, 690), (10, 690), (325, 690), (325, 690), (325, 640), (325, 640),
  35.                  (350, 640), (350, 630), (350, 630), (315, 630), (315, 680), (20, 680), (20, 680), (20, 560),
  36.              (20, 540), (160, 540), (160, 540), (160, 350), (20, 350), (20, 350), (20, 20), (20, 20),
  37.              (380, 20), (380, 20), (380, 130), (380, 130), (420, 130), (420, 130), (420, 20), (420, 20),
  38.              (780, 20), (780, 350), (780, 350), (650, 350), (650, 350), (650, 540), (650, 540), (780, 540),
  39.              (780, 540), (780, 680), (780, 680), (485, 680), (485, 630), (485, 630), (450, 630), (450, 630),
  40.              (450, 640)]
  41. topLeftBox = [(130, 105), (130, 125), (130, 125), (250, 125), (250, 125), (250, 105),
  42.                     (130, 105), (250, 105)]
  43. secondTopLeftBox = [(160, 215), (160, 225), (160, 215), (230, 215), (230, 215),
  44.                     (230, 225), (160, 225), (230, 225)]
  45. topRightBox = [(545, 105), (545, 125), (545, 125), (665, 125), (665, 125), (665, 105), 
  46.              (545, 105), (665, 105)]
  47. secondTopRightBox = [(560, 215), (560, 225), (560, 215), (625, 215), (625, 215), (625, 225),
  48.                      (625, 225), (560, 225)]
  49. middleT = [(345, 240), (455, 240), (345, 240), (345, 240), (345, 250), (395, 250), (395, 250), (395, 335),
  50.          (395, 335), (405, 335), (405, 335), (405, 250), (405, 250), (455, 250), (455, 250), (455, 240)]
  51. leftSidewaysT = [(275, 340), (275, 500), (275, 340), (285, 340), (285, 340), (285, 415), (285, 415), (345, 415),
  52.                  (345, 415), (345, 425), (285, 425), (345, 425), (285, 425), (285, 500), (275, 500), (285, 500)]
  53. rightSidewaysT = [(525, 340), (525, 500), (525, 340), (515, 340), (515, 340), (515, 415), (515, 415), (455, 415),
  54.                  (455, 415), (455, 425), (515, 425), (455, 425), (515, 425), (515, 500), (515, 500), (525, 500)]
  55. walls = [outerWall] 
  56. for wall in walls: 
  57.     for i in range(len(wall) - 1):
  58.         createWall(outerWall[i], outerWall[i+1])    
  59. boxes = [topLeftBox, secondTopLeftBox, topRightBox, secondTopRightBox]
  60. for box in boxes:
  61.     for i in range(len(box)-1):
  62.         createWall(topLeftBox[i], topLeftBox[i+1]),
  63.         createWall(secondTopLeftBox[i], secondTopLeftBox[i+1]),
  64.         createWall(topRightBox[i], topRightBox[i+1]),
  65.         createWall(secondTopRightBox[i], secondTopRightBox[i+1])
  66. Ts = [middleT, leftSidewaysT, rightSidewaysT]
  67. for t in Ts:
  68.     for i in range(len(t)-1):
  69.         createWall(middleT[i], middleT[i+1]),
  70.         createWall(leftSidewaysT[i], leftSidewaysT[i+1]),
  71.         createWall(rightSidewaysT[i], rightSidewaysT[i+1])
  72.  
  73. horizontalPath = [(40, 610, 9), (60, 290, 14), (60, 50, 12), (60, 170, 33), (440, 290, 1),
  74.                      (440, 290, 14), (480, 50, 12), (320, 370, 6), (300, 510, 9), (220, 570, 5), (460, 570, 5), (580, 610, 8),
  75.                  (0,0,0)]
  76. verticalPath = [(60, 30, 13), (220, 290, 15), (300, 50, 11), (500, 30, 13), (340, 290, 4), (340, 290, 4),
  77.                 (400, 370, 6), (320, 510, 3), (460, 290, 4), (480, 510, 3), (580, 290, 16), (720, 30, 13), (0,0,0)]
  78. paths = [horizontalPath, verticalPath]
  79. for path in paths:
  80.     for i in range(len(path)-1):
  81.         buildPathHorizontal(horizontalPath[i]),
  82.         buildPathVertical(verticalPath[i])
  83.  
  84. image = 'DustY.gif'
  85. photo = PhotoImage(file=image)
  86. xGif = 100
  87. yGif = 610
  88. ph = canvasOne.create_image(xGif, yGif, image = photo)
  89. graph = {(100, 610) : [(270, 610)],
  90.          (270, 610) : [(270, 280), (270, 560), (100, 610)],
  91.          (270, 560) : [(400, 550), (370, 560), (270, 280), (270, 610)],
  92.          (270, 280) : [(110, 280), (300, 290), (380, 290), (270, 610)],
  93.          (370, 560) : [(370, 500), (270, 280)],
  94.          (370, 500) : [(450, 500), (370, 560)],
  95.          (450, 500) : [(390, 300), (450, 370), (370, 500)],
  96.          (450, 370) : [(390, 370), (450, 500)],
  97.          (390, 370) : [(390, 290), (450, 370)],
  98.          (390, 290) : [(350, 290), (390, 370)],
  99.          (350, 290) : [(350, 170), (110, 280), (390, 290)],
  100.          (350, 170) : [(110, 170), (350, 290), (350, 290)],
  101.          (110, 280) : [(110, 170), (110, 40), (270, 280)],
  102.          (110, 170) : [(350, 170), (110, 280)],
  103.          (110, 40) : [(350, 40), (110, 170), (110, 280)],
  104.          (350, 40) : [(350, 170), (110, 40)],
  105.          (350, 170) : [(550, 170), (110, 170), (350, 40)],
  106.          (550, 170) : [(550, 40), (550, 280), (350, 170), (750, 170)],
  107.          (550, 40) : [(770, 40), (550, 40)],
  108.          (550, 280) : [(510, 280), (520, 200), (520, 40)],
  109.          (510, 280) : [(510, 360), (550, 280)],
  110.          (510, 360) : [(450, 370), (510, 280)],
  111.          (770, 40) : [(770, 280), (770, 170), (550, 40)],
  112.          (770, 280) : [(630, 280), (550, 280), (470, 280), (770, 40)],
  113.          (630, 280) : [(630, 610), (550, 280), (470, 280), (770, 280)],
  114.          (630, 610) : [(790, 610), (630, 560), (630, 570), (630, 280)],
  115.          (630, 560) : [(530, 560), (630, 280), (630, 610)],
  116.          (530, 560) : [(530, 500), (630, 560)],
  117.          (530, 500) : [(450, 500), (530, 370)],
  118.          (450, 500) : [(450, 350), (530, 500)],
  119.          (790, 610) : [(630, 610)]}
  120. """
  121. find_all_paths is a greedy algorithm based function that will get the .gif moving on the
  122. path. It returns the path for the .gif to follow. 
  123. """
  124. def find_all_paths(graph, start, end, path=[]):
  125.         path = path + [start]
  126.         if start == end:
  127.             return [path]
  128.         if not graph.has_key(start):
  129.             return []
  130.         paths = []
  131.         for node in graph[start]:
  132.             if node not in path:
  133.                 newpaths = find_all_paths(graph, node, end, path)
  134.                 for newpath in newpaths:
  135.                     paths.append(newpath)
  136.         return paths
  137. def move_gif(pic, x = xGif, y = yGif):
  138.     endX = 790
  139.     endY = 610
  140.     mode = .001
  141.     path = find_all_paths(graph, (x, y), (endX, endY))
  142.     try:
  143.         for i in path[7]:
  144.             dest = list(i)
  145.             newX = dest[0]
  146.             newY = dest[1]
  147.             if newX == x:
  148.                 while y != newY:
  149.                     if y > newY:
  150.                         y -= 2
  151.                         canvasOne.coords(pic, x, y)
  152.                         time.sleep(mode)
  153.                         canvasOne.update()
  154.                         path = find_all_paths(graph, (x, y), (endX, endY))
  155.                     if y < newY:
  156.                         y+=2
  157.                         canvasOne.coords(pic, x, y)
  158.                         time.sleep(mode)
  159.                         canvasOne.update()
  160.                         path = find_all_paths(graph, (x, y), (endX, endY))
  161.             if newY == y:
  162.                 while x != newX:
  163.                     if x > newX:
  164.                         x -= 2
  165.                         canvasOne.coords(pic, x, y)
  166.                         time.sleep(mode)
  167.                         canvasOne.update()
  168.                         path = find_all_paths(graph, (x, y), (endX, endY))
  169.                     if x < newX:
  170.                         x += 2
  171.                         canvasOne.coords(pic, x, y)
  172.                         time.sleep(mode)
  173.                         canvasOne.update()
  174.                         path = find_all_paths(graph, (x, y), (endX, endY))
  175.     except IndexError:
  176.         print 'path: ' , path
  177.         print "out of range"
  178.  
  179. move_gif(ph)        
  180. root.mainloop()    
  181.  
  182.  
  183.  
May 18 '07 #1
Share this Question
Share on Google+
3 Replies


bartonc
Expert 5K+
P: 6,596
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.
May 19 '07 #2

TMS
100+
P: 119
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
May 19 '07 #3

bartonc
Expert 5K+
P: 6,596
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
Expand|Select|Wrap|Line Numbers
  1. time.sleep(mode)
  2. canvasOne.update()
  3.  
works. I think that calling update() will be enough for your keyboard events to get processed, but I'm not sure about that.
May 19 '07 #4

Post your reply

Sign in to post your reply or Sign up for a free account.