简体   繁体   中英

why am i getting a trace back in my code for my move ball command as it is stopping the rest of my code from running

i am making a pong game

i managed to code the ball to bounce around the window but it seems that the code, for using user input to get the rectangles to move isn't working. when i run the code i have been getting a traceback to my move.ball command relating to making the ball bounce, and i believe that may be stopping the rest of the code from running. I have included the full code in case any errors can be spotted in it.

from tkinter import *
import tkinter as tkr
import time
tk = tkr.Tk()
Canvas = tkr.Canvas(tk, width=300, height=400)
Canvas.grid()
ball = Canvas.create_oval(3,3,40,40,fill="light blue")
player1 = Canvas.create_rectangle(20,5,90,30,fill="black")
Canvas.moveto(player1, 120, 380)
player2 = Canvas.create_rectangle(20,5,90,30,fill="black")
Canvas.moveto(player2, 120, -5)
x = 1
y = 3
while True:
    Canvas.move(ball,x,y)
    pos = Canvas.coords(ball)
if pos[3] >= 400 or pos[1] <= 0:
    y = -y
if pos[2] >= 300 or pos[0] <= 0:
    x = -x
tk.update()
time.sleep(0.025)
pass

tk.mainloop()

def left(event):
    x == -10
    y == 0
Canvas.move(player1, x, y)

def right(event):
    x == 10
    y == 0
Canvas.move(player1, x, y)

def up(event):
    x == 0
    y == -10
Canvas.move(player1, x, y)

def down(event):
    x == -10
    y == 0
Canvas.move(player1, x, y)

root.bind("<Left>", left)
root.bind("<Right>", right)
root.bind("<Up>", up)
root.bind("<Down>", down)



tk.mainloop()

i am getting this trace back-

Traceback (most recent call last):
  File "C:/Users/amarb/Desktop/code/pong.py", line 15, in <module>
    Canvas.move(ball,x,y)
  File "C:\Users\amarb\AppData\Local\Programs\Python\Python310\lib\tkinter\__init__.py", line 2949, in move
    self.tk.call((self._w, 'move') + args)
_tkinter.TclError: invalid command name ".!canvas"

.!canvas is the internal identifier of the canvas widget that you created. This error is happening because you try to run code after mainloop() returns, which is after the window being destroyed. You can't interact with widgets after they have been destroyed.

Edit: New. How to get the paddle moving and hit the paddle. I only used one player at a time. You will do the rest. I had to modify some and add some new functions. I am using new python 3.11.0b3.

from tkinter import *
import tkinter as tkr
import time
import random


tk = tkr.Tk()
width=300
height=400
Canvas = tkr.Canvas(tk, width=width, height=height)
Canvas.pack()
tk.update()

ball = Canvas.create_oval(3,3,25,25,fill="red")
Canvas.move(ball, 245, 100)

starts = [-3, -2, -1, 1, 2, 3]
random.shuffle(starts)

ball_x = starts[0]
ball_y = 3

player1 = Canvas.create_rectangle(20,5,90,30,fill="black")
Canvas.moveto(player1, 180, 380)

player2 = Canvas.create_rectangle(20,5,90,30,fill="blue")
Canvas.move(player2, 120, -5)

paddle_x = 0


def hit_bat(pos):
    bat_pos = Canvas.coords(player1) #retrieve the coordinates of the bat position - note the ball coordinates are being passed
    if pos[2] >= bat_pos[0] and pos[0] <= bat_pos[2]: #if the right side of the ball (that is the x right hand coordinate) is greater than the left side of the bat, AND the left side of the ball is less than the right side of the bat ....move etc
        if pos[3]>= bat_pos[1] and pos[3] <= bat_pos[3]: #if the bottom of the ball (pos[3]) is between the paddle's top [bat pos[1]) and bottom (pos[3])
            return True
    return False

    
def draw_ball():
    global ball_x, ball_y
    Canvas.move(ball, ball_x, ball_y)
    pos = Canvas.coords(ball)
    if pos[1] <= 0: 
            ball_y = 6
    if pos[3] >= height:
        ball_y = -6
    #Call the hit_bat function
    if hit_bat(pos) == True: #if the hit_bat function returns a value of True, the direction of the ball is changed
        ball_y = -6 #if the ball hits the bat, then send the ball flying up at a rate of -6 (higher the number the faster the fly!)
    if pos[0] <= 0:
        ball_x = 6
    if pos[2]>= width:
        ball_x = -6         
    tk.update()
     
    
def hit_paddle(pos):
    paddle_pos = Canvas.coords(ball)
    if pos[2] >= paddle_pos[0] and pos[0] <= paddle_pos[2]:
        if pos[3] >= paddle_pos[1] and pos[3] <= paddle_pos[3]:
            return True
    return False


def draw_paddle():
    global paddle_x
    Canvas.move(player1, paddle_x, 0)
    pos = Canvas.coords(player1)
    if pos[0] <= 0:
        paddle_x = 0
    elif pos[2] >= width:
        paddle_x = 0
    time.sleep(0.02)
    tk.update()


def move_left(event):
    global paddle_x
    paddle_x = -2

    
def move_right(event):
    global paddle_x
    paddle_x = 2
 

Canvas.bind_all("<KeyPress-Left>", move_left)
Canvas.bind_all("<KeyPress-Right>", move_right) 

while True:
 
    draw_ball()    
    draw_paddle()
 
 

New image:

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM