在Tkinter画布控件中移动球(简单的打砖块游戏)

2 投票
2 回答
29430 浏览
提问于 2025-04-17 05:31

我正在尝试用Python和Tkinter写一个简单的打砖块游戏。我的目标是让球能够从顶部、右侧和左侧反弹。如果玩家没有接住球,导致球碰到底部,游戏就会结束。

这是我的代码:

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()

为什么球的反弹方向不对呢?

程序截图

2 个回答

13

要移动一个物体,你需要使用 coords 方法或者 move 方法,这两个方法都可以改变物体的位置。你可以用 coords 方法来获取物体当前的位置。

如果你想做动画,可以使用 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)

撰写回答