python - Python Ping-Pong 比赛,球速在桨运动过程中随机变化
问题描述
我从学习 python 开始,并尝试了如何在 python 中制作乒乓球游戏的教程。在我的比赛中,球的速度会以某种方式波动并且不一致,尤其是当我使用 W 或 S 以及箭头键移动任何一个球拍时,速度会发生变化并造成不便。我已经多次检查代码是否存在错误,但我无法弄清楚。这是我的代码。
import turtle
win = turtle.Screen()
win.title("Pong by killkennyale")
win.bgcolor("black")
win.setup(width=800, height=600)
win.tracer(0)
# Score
score_a = 0
score_b = 0
# Paddle A
paddle_a = turtle.Turtle()
paddle_a.speed(0) #speed of animation of paddle
paddle_a.shape("square")
paddle_a.shapesize(stretch_wid=5, stretch_len=1)
paddle_a.color("white")
paddle_a.penup() #turtle draws lines, we don't want that duh
paddle_a.goto(-350,0) #coordinates for turtle-paddle
# Paddle B
paddle_b = turtle.Turtle()
paddle_b.speed(0) #speed of animation of paddle
paddle_b.shape("square")
paddle_b.shapesize(stretch_wid=5, stretch_len=1)
paddle_b.color("white")
paddle_b.penup() #turtle draws lines, we don't want that duh
paddle_b.goto(350,0) #coordinates for turtle-paddle
# Ball
ball = turtle.Turtle()
ball.speed(0) #speed of animation of ball
ball.shape("circle")
ball.shapesize(stretch_wid=1, stretch_len=1)
ball.color("white")
ball.penup() #turtle draws lines, we don't want that duh
ball.goto(0,0) #coordinates for turtle-ball
ball.dx = 0.5 #speed of x
ball.dy = 0.5 #speed of y
# Pen
pen = turtle.Turtle()
pen.speed(0)
pen.color("white")
pen.penup()
pen.hideturtle() # we don't need to see it
pen.goto(0, 260)
pen.write("Player A: {} Player B: {}".format(score_a, score_b), align="center", font=("Courier", 16, "normal"))
# now we gotta make the paddle move using a keyboard
# Function
def paddle_a_up():
y = paddle_a.ycor() #assign y-coordinate to variable y
y = y + 20 #add 20 pixels to y-coordinate
paddle_a.sety(y)
def paddle_a_down():
y = paddle_a.ycor() #assign y-coordinate to variable y
y = y - 20 #add 20 pixels to y-coordinate
paddle_a.sety(y)
def paddle_b_up():
y = paddle_b.ycor() #assign y-coordinate to variable y
y = y + 20 #add 20 pixels to y-coordinate
paddle_b.sety(y)
def paddle_b_down():
y = paddle_b.ycor() #assign y-coordinate to variable y
y = y - 20 #add 20 pixels to y-coordinate
paddle_b.sety(y)
# Keyboard Binding
win.listen() # tells the turtle to listen to the keyboard
win.onkeypress(paddle_a_up, "w")
win.onkeypress(paddle_a_down, "s")
# when we press 'w'or's' then it calls paddle_a_up or down and adds or subtracts 20 to the y coordinate
win.onkeypress(paddle_b_up, "Up")
win.onkeypress(paddle_b_down, "Down")
# when we press 'up'or'down' arrow then it calls paddle_b_up or down and adds or subtracts 20 to the y coordinate
#Main Game Loop
while True:
win.update()
# Move the ball
ball.setx(ball.xcor() + ball.dx)
ball.sety(ball.ycor() + ball.dy)
# Border Checking
if ball.ycor() > 290:
ball.sety(290) # it reaches roof at 300
ball.dy = ball.dy * -1
if ball.ycor() < -290:
ball.sety(-290) # it reaches roof at 300
ball.dy = ball.dy * -1
if ball.xcor() > 390:
ball.goto(0,0)
ball.dx = ball.dx * -1
score_a += 1
pen.clear()
pen.write("Player A: {} Player B: {}".format(score_a, score_b), align="center", font=("Courier", 16, "normal"))
if ball.xcor() < -390:
ball.goto(0,0)
ball.dx = ball.dx * -1
score_b += 1
pen.clear()
pen.write("Player A: {} Player B: {}".format(score_a, score_b), align="center", font=("Courier", 16, "normal"))
# Paddle and ball collisions
if (ball.xcor() > 340 and ball.xcor() < 350) and (ball.ycor() < paddle_b.ycor() + 40 and ball.ycor() > paddle_b.ycor() - 40):
ball.setx(340)
ball.dx *= -1
if (ball.xcor() < -340 and ball.xcor() > -350) and (ball.ycor() < paddle_a.ycor() + 40 and ball.ycor() > paddle_a.ycor() - 40):
ball.setx(-340)
ball.dx *= -1
解决方案
您需要一个主/游戏/动画循环,该循环的设置方式可以使事物以恒定的速度向前移动,而不是像目前那样以可变速度前进。
在while
您的示例中设置循环后,将在上一次迭代之后立即调用循环的下一次迭代,并且每次迭代可能需要可变的时间才能完成。但是你的球和桨的移动量是固定的,这就是你有问题的原因。例如,循环的第一帧/迭代可能需要 1 毫秒,但第二帧/迭代可能需要 7 毫秒,因为按下了一个键,因此计算机完成了更多的计算。所以在第 1 帧中,球会在 1 毫秒内移动dx
,dy
但在下一帧中,球需要 7 毫秒才能移动dx
,并且dy
再次——换句话说,你的球/桨运动因此是可变的,因为它以每秒可变数量的帧而不是固定的 fps 发生。
所以你可以告诉计算机多久不断地推进游戏/动画,而不是让它以可变的速度推进。(否则,如果您愿意,可以根据该可变速度进行调整)。你可以通过一个以恒定帧率运行的回调函数来做到这一点——例如Pong with Turtle Graphics: Part 2frame()
中的函数:
framerate_ms = 40 # Every how many milliseconds must frame function be called?
def frame () :
screen.ontimer(frame, framerate_ms) # schedule this function to be called again
check_if_someone_scores()
update_paddle_positions()
update_ball_position()
screen.update() # display the new frame
frame() # call it manually the first time
推荐阅读
- python - 如何从文章中提取(识别)书名?
- arrays - 通过 Read-Host 创建数组元素,如何使用情境数组变量将元素移动到另一个 ArrayList?
- cloud - 使用 MindSphere 创建资产
- python-2.7 - 如何使用 tf.data.dataset 保存和恢复模型以导入数据?
- asp.net-mvc - Visual Studio MVC 5 web 项目 - 我应该在项目中包含“node_modules”文件夹吗?
- apache-spark - 无法实例化提供程序 org.apache.hadoop.fs.s3a.S3AFileSystem
- c# - 多态性不适用于使用 MessagePack-Csharp nuget 的集合元素
- pdf - 使用 ImageMagick 拆分 pdf 文档
- scala - 是否可以让 intellij 在断点处将变量/表达式打印到控制台?
- amazon-s3 - Amazon S3:如何安全地上传多个文件?