【问题标题】:Move a ball inside Tkinter Canvas Widget (simple Arkanoid game)在 Tkinter Canvas Widget 内移动球(简单的打砖块游戏)
【发布时间】:2011-12-20 13:02:28
【问题描述】:

我正在尝试在 Python 和 Tkinter 的帮助下编写一个简单的 Arkanoid。目标是使球从顶部、右侧和左侧反射。如果球员错过了球,所以球触到了底边,比赛就会停止。

代码如下:

from Tkinter import *
import time

root = Tk()
canv = Canvas(root, highlightthickness=0)
canv.pack(fill='both', expand=True)
top = canv.create_line(0, 0, 640, 0, fill='green', tags=('top'))
left = canv.create_line(0, 0, 0, 480, fill='green', tags=('left'))
right = canv.create_line(639, 0, 639, 480, fill='green', tags=('right'))
bottom = canv.create_line(0, 478, 640, 478, fill='red', tags=('bottom'))

rect = canv.create_rectangle(270, 468, 365, 478, outline='black', fill='gray40', tags=('rect'))
ball = canv.create_oval(0, 20, 20, 40, outline='black', fill='gray40', tags=('ball'))

delta_x = delta_y = 3
new_x, new_y = delta_x, -delta_y
while True:
    time.sleep(0.025)
    if canv.find_overlapping(canv.coords(ball)[0], canv.coords(ball)[1], canv.coords(ball)[2], canv.coords(ball)[3])[0] == 1:
        new_x, new_y = delta_x, -delta_y
        canv.move(ball, new_x, new_y)
        print 'fitst if', new_x, new_y
    if canv.find_overlapping(canv.coords(ball)[0], canv.coords(ball)[1], canv.coords(ball)[2], canv.coords(ball)[3])[0] == 2:
        new_x, new_y = delta_x, delta_y
        canv.move(ball, new_x, new_y)
        print '2nd if', new_x, new_y
    if canv.find_overlapping(canv.coords(ball)[0], canv.coords(ball)[1], canv.coords(ball)[2], canv.coords(ball)[3])[0] == 3:
        new_x, new_y = -delta_x, delta_y
        canv.move(ball, new_x, new_y)
    if canv.find_overlapping(canv.coords(ball)[0], canv.coords(ball)[1], canv.coords(ball)[2], canv.coords(ball)[3])[0] == 4:
        new_x, new_y = delta_x, -delta_y
        canv.move(ball, new_x, new_y)
    print new_x, new_y
    canv.move(ball, new_y, new_y)
    canv.update()

def move_right(event):
        canv.move(rect, 7, 0)
        pass

def move_left(event):
    canv.move(rect, -7, 0)
    pass

root.bind('<Right>', move_right)
root.bind('<Left>', move_left)

root.geometry('%sx%s+%s+%s' %(640, 480, 100, 100))
root.resizable(0, 0)
root.mainloop()

为什么球会以错误的方式反射?

【问题讨论】:

  • “反射”不意味着运动吗?您需要先移动球,根据速度定期更新其位置。让球移动后,当它的边界框与矩形相交时,根据相交发生在哪一侧,反转速度的符号(例如 x 速度从 +5 到 -5)。另外,如果这是家庭作业,请添加“家庭作业”标签。
  • 你真的应该避免使用while Truetime.sleep。这些都不适用于事件循环。使用我向您展示的代码,使用after 更新屏幕。
  • 您的代码没有运行。完全没有。它有缩进错误,并且它引用了从未在任何地方设置过的“self”。
  • @BryanOakley,我刚刚更正了代码。它现在应该可以工作了。

标签: python canvas tkinter


【解决方案1】:

要移动对象,您需要使用coords 方法或move 方法,这会改变对象的坐标。可以使用coords方法获取当前坐标。

要制作动画,您可以使用after。调用一个函数,然后让它使用after 在不久的将来再次调用自己。未来多远将决定您的帧速率(即:每 10 毫秒意味着大约每秒 100 帧)

例如:

def moveit(self):

    # move the object
    <get the existing coordinates using the coords method>
    <adjust the coordinates relative to the direction of travel>
    <give the object new coordinates using the coords method>

    # cause this movement to happen again in 10 milliseconds
    self.after(10, self.moveit)

只要您拨打moveit() 一次,循环就开始了。相同的方法可用于更新多个对象,或者您可以为不同的对象使用不同的方法。

编辑:你已经完全改变了你的问题,从“我如何在画布上移动一些东西?”到“为什么它朝错误的方向移动?”。后者的答案很简单:您是在告诉它朝错误的方向移动。使用调试器或一些打印语句来查看计算 delta_y 的位置和方式。

【讨论】:

    【解决方案2】:

    这里有一个解决这个问题的简单技巧:

    delta_x = delta_y = 3
    while True:
          objects = canv.find_overlapping(canv.coords(ball)[0], canv.coords(ball)[1], canv.coords(ball)[2], canv.coords(ball)[3])
          for obj in objects:
            if obj == 1:
                delta_y = -delta_y
            if obj == 2:
                delta_x = -delta_x
            if obj == 3:
                delta_x = -delta_x
            if obj == 4:
                delta_y = -delta_y
    
          new_x, new_y = delta_x, delta_y
          canv.move(ball, new_x, new_y)
          canv.update()
          time.sleep(0.025)
    
          root.bind('<Right>', move_right)
          root.bind('<Left>', move_left)
    

    【讨论】:

    • 这个答案显示了一种不太理想的动画制作方式。您不应该在 GUI 中调用 sleep,而且通常也不应该有无限循环。 GUI 已经有一个无限循环——事件循环。
    猜你喜欢
    • 1970-01-01
    • 2014-09-07
    • 2018-10-05
    • 2012-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多