Tkinter开发Pong游戏:计分器更新及文本与球碰撞问题求助
问题解决方案
1. 计分器更新问题解决
要在不改变文本位置的前提下更新计分内容,使用Tkinter Canvas的itemconfig方法修改已创建文本的内容即可。在Text类中新增更新分数的方法,每次分数变化时调用该方法同步显示:
- 在
Text类中添加:
def update_score(self, new_score): self.canvas.itemconfig(self.id, text=f"Score: {new_score}")
- 每次
score变量更新后,调用text.update_score(score)同步界面显示。
2. 球与文本碰撞交互问题解决
原代码存在两个导致碰撞失效的问题:
Ball类的__init__未保存传入的text实例,导致hit_text方法无法访问文本对象;Ball类的draw方法未调用hit_text检测碰撞并处理反弹逻辑。
修复步骤:
- 在
Ball类的__init__中添加self.text = text,保存文本实例; - 在
Ball的draw方法中加入碰撞检测,当球击中文本时改变球的运动方向。
修改后的完整代码
from tkinter import * import random import time import os score = 0 print('Score: ' + str(score)) class Ball: def __init__(self, canvas, paddle, text, color): self.canvas = canvas self.paddle = paddle self.text = text # 保存text实例 self.id = canvas.create_oval(10, 10, 25, 25, fill=color) self.canvas.move(self.id, 245, 100) starts = [-3, -2, -1, 1, 2, 3] random.shuffle(starts) self.x = starts[0] self.y = -3 self.canvas_height = self.canvas.winfo_height() self.canvas_width = self.canvas.winfo_width() self.hit_bottom = False def hit_paddle(self, pos): global score paddle_pos = self.canvas.coords(self.paddle.id) if pos[2] >= paddle_pos[0] and pos[0] <= paddle_pos[2]: if pos[3] >= paddle_pos[1] and pos[3] <= paddle_pos[3]: score = score + 1 os.system('clear') print('Score: ' + str(score)) self.text.update_score(score) # 同步更新计分器 return True return False def hit_text(self, pos): text_pos = self.canvas.coords(self.text.id) if pos[2] >= text_pos[0] and pos[0] <= text_pos[2]: if pos[3] >= text_pos[1] and pos[3] <= text_pos[3]: return True return False def draw(self): self.canvas.move(self.id, self.x, self.y) pos = self.canvas.coords(self.id) if pos[1] <= 0: self.y = 1 if pos[3] >= self.canvas_height: self.hit_bottom = True if self.hit_paddle(pos) == True: self.y = -3 # 检测球与文本的碰撞并反弹 if self.hit_text(pos) == True: self.y = -self.y # 垂直方向反弹 self.x = -self.x # 水平方向反弹 if pos[0] <= 0: self.x = 3 if pos[2] >= self.canvas_width: self.x = -3 class Paddle: def __init__(self, canvas, color): self.canvas = canvas self.id = canvas.create_rectangle(0, 0, 100, 10, fill=color) self.canvas.move(self.id, 200, 300) self.x = 0 self.canvas_width = self.canvas.winfo_width() self.canvas.bind_all('<KeyPress-Left>', self.turn_left) self.canvas.bind_all('<KeyPress-Right>', self.turn_right) self.canvas.bind_all('<KeyPress-Up>', self.turn_stop) def draw(self): self.canvas.move(self.id, self.x, 0) pos = self.canvas.coords(self.id) if pos[0] <= 0: self.x = 0 elif pos[2] >= self.canvas_width: self.x = 0 def turn_left(self, evt): self.x = -2 def turn_right(self, evt): self.x = 2 def turn_stop(self, evt): self.x = 0 class Text: def __init__(self, canvas, paddle, color): global score self.canvas = canvas self.paddle = paddle self.id = canvas.create_text(10, 20, text="Score: " + str(score), fill=color, font=("Arial", 15)) self.canvas.move(self.id, 245, 100) starts = [-3, -2, -1, 1, 2, 3] random.shuffle(starts) self.x = starts[0] self.y = -3 self.canvas_height = self.canvas.winfo_height() self.canvas_width = self.canvas.winfo_width() # 更新计分文本方法 def update_score(self, new_score): self.canvas.itemconfig(self.id, text=f"Score: {new_score}") def hit_paddle(self, pos): paddle_pos = self.canvas.coords(self.paddle.id) 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(self): global score self.canvas.move(self.id, self.x, self.y) pos = canvas.bbox(self.id) if pos[1] <= 0: self.y = 1 if pos[3] >= self.canvas_height: self.y = -1 if self.hit_paddle(pos) == True: score = score + 1 self.y = -3 self.x = -3 self.update_score(score) # 同步更新计分器 if pos[0] <= 0: self.x = 3 if pos[2] >= self.canvas_width: self.x = -3 tk = Tk() tk.title("Game") tk.resizable(0,0) tk.wm_attributes("-topmost",1) canvas = Canvas(tk, width=500, height=400, bd=0, highlightthickness=0) canvas.pack() tk.update() paddle = Paddle(canvas, 'blue') text = Text(canvas, paddle, 'black') ball = Ball(canvas, paddle, text, 'red') while 1: if ball.hit_bottom == False: ball.draw() paddle.draw() text.draw() tk.update_idletasks() tk.update() time.sleep(0.01)
内容的提问来源于stack exchange,提问作者Jason Paris
相关产品推荐
相关产品推荐

