如何用Python Turtle检测小球与Paddle的碰撞侧边
问题:如何正确检测小球与Paddle侧边/顶面的碰撞
你当前用==判断碰撞位置的逻辑存在问题——小球是连续移动的,几乎不可能刚好卡到那个精确数值,所以效果很差。另外,碰撞范围的判断也可以更清晰,下面是修正方案:
核心修正点
- 放弃用
==做位置判断,改用范围区间检测碰撞 - 明确计算Paddle和小球的实际边界尺寸,避免硬编码数值
- 区分侧边碰撞和顶面碰撞的条件:
- 侧边碰撞:小球Y坐标落在Paddle的垂直范围内,且X坐标触碰到Paddle的左右边缘
- 顶面碰撞:小球X坐标落在Paddle的水平范围内,且Y坐标触碰到Paddle的上边缘
修改后的完整代码
from turtle import Turtle, Screen import time import random # --------------- GLOBAL VARIABLES -------------------- speed_x = 20 speed_y = 20 bricks = [] # 预定义尺寸,避免硬编码 BALL_RADIUS = 10 PADDLE_WIDTH = 150 # 基础正方形20px * 缩放比例7.5 PADDLE_HEIGHT = 20 # 基础正方形20px * 缩放比例1 PADDLE_HALF_W = PADDLE_WIDTH / 2 PADDLE_HALF_H = PADDLE_HEIGHT / 2 def check_collision(): global speed_x, speed_y, bricks # 左右墙壁碰撞 if ball.xcor() > (window.window_width() / 2) - BALL_RADIUS or ball.xcor() < -(window.window_width() / 2) + BALL_RADIUS: speed_x *= -1 # 顶部墙壁碰撞 elif ball.ycor() > (window.window_height() / 2) - BALL_RADIUS: speed_y *= -1 # 底部边界(掉球,可自行扩展重置逻辑) elif ball.ycor() < -(window.window_height() / 2) + BALL_RADIUS: speed_y *= -1 # Paddle碰撞检测 elif (abs(paddle.xcor() - ball.xcor()) < PADDLE_HALF_W + BALL_RADIUS and abs(paddle.ycor() - ball.ycor()) < PADDLE_HALF_H + BALL_RADIUS): # 判断是侧边碰撞还是顶面碰撞 # 侧边碰撞:小球Y坐标在Paddle的垂直区间内 if (ball.ycor() > paddle.ycor() - PADDLE_HALF_H and ball.ycor() < paddle.ycor() + PADDLE_HALF_H): # 根据小球位置判断撞左侧还是右侧 speed_x = abs(speed_x) * (-1 if ball.xcor() < paddle.xcor() else 1) # 顶面碰撞:小球X坐标在Paddle的水平区间内 else: speed_y *= -1 def game_loop(): ball.goto(ball.xcor() + speed_x, ball.ycor() + speed_y) check_collision() window.update() window.ontimer(game_loop, 1) def move_right(): paddle.setx(paddle.xcor() + 25) def move_left(): paddle.setx(paddle.xcor() - 25) window = Screen() time.sleep(2) ball = Turtle(shape='circle') ball.pu() ball.speed(0) ball.goto(0, -300) ball.left(random.randint(45, 135)) paddle = Turtle(shape='square') paddle.speed(0) paddle.goto(0, -400) paddle.shapesize(1, 7.5, 3) paddle.up() window.listen() window.onkeypress(move_right, 'Right') window.onkeypress(move_left, 'Left') window.onkeypress(move_right, 'd') window.onkeypress(move_left, 'a') game_loop() window.mainloop()
关键说明
- 尺寸预定义:把小球半径、Paddle的宽高都定义成变量,后续调整Paddle大小不需要修改碰撞逻辑
- 碰撞条件优化:用范围判断替代精确值相等,符合小球连续移动的特性
- 侧边碰撞逻辑:先判断小球Y坐标是否在Paddle的垂直区间内,再根据X坐标方向调整速度,确保撞侧边时只改变X方向
- 顶面碰撞逻辑:当小球不在Paddle垂直区间但触发碰撞时,判定为撞顶面,改变Y方向速度
内容的提问来源于stack exchange,提问作者Aadvik
相关产品推荐
相关产品推荐

