如何修复python乌龟中不一致的帧速率(速度) [英] How to fix inconsistent frame rate (speed) in python turtle

查看:47
本文介绍了如何修复python乌龟中不一致的帧速率(速度)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我按照本教程制作了乒乓球游戏 https://youtu.be/C6jJg9Zan7w我遇到的问题是球(乌龟物体)的速度在不同的计算机上是不一样的.例如,在辅导老师的电脑上,ball.dx ball.dy 的值为2,球的速度是正常的,但在我的电脑上,我的电脑非常快,所以我不得不将其设置为0.1.我认为这个问题是因为不同的计算机可以推出或多或少的帧.我知道流行的游戏引擎(如unity-unreal)中有一种使用时间而不是帧的方法,因此变量在不同的计算机中是全局的.我遇到的另一个问题是,当我移动球拍时,球的速度会略有变化.不知道是不是和上面一样的问题

导入海龟导入 winsoundwn = 海龟.Screen()wn.title('乒乓')wn.bgcolor('黑色')wn.setup(宽=800,高=600)wn.tracer(0)#桨Apaddle_a = 海龟.Turtle()paddle_a.speed(0)paddle_a.shape('正方形')paddle_a.color('白色')paddle_a.penup()paddle_a.goto(-350, 0)paddle_a.shapesize(5, 1)#桨Bpaddle_b = 海龟.Turtle()paddle_b.speed(0)paddle_b.shape('正方形')paddle_b.color('白色')paddle_b.penup()paddle_b.goto(350, 0)paddle_b.shapesize(5, 1)# 球球 = 乌龟.乌龟()球.速度(0)ball.shape('正方形')ball.color('白色')ball.penup()球.dx = 0.15球.dy = 0.15# 钢笔笔 = 乌龟.乌龟()笔速(0)pen.color('白色')pen.penup()pen.goto(0, 260)pen.write("玩家 A: 0 玩家 B: 0", align='center', font=('Courier', 24, 'bold'))pen.hideturtle()# 分数分数_a = 0分数_b = 0def paddle_a_up():y = paddle_a.ycor()y += 20paddle_a.sety(y)def paddle_b_up():y = paddle_b.ycor()y += 20paddle_b.sety(y)def paddle_a_down():y = paddle_a.ycor()y += -20paddle_a.sety(y)def paddle_b_down():y = paddle_b.ycor()y += -20paddle_b.sety(y)# 键盘绑定wn.listen()wn.onkeypress(paddle_a_up, 'w')wn.onkeypress(paddle_a_down, 's')wn.onkeypress(paddle_b_up, '向上')wn.onkeypress(paddle_b_down, '向下')# 主游戏循环为真:wn.update()# 移动球ball.setx(ball.xcor() + ball.dx)ball.sety(ball.ycor() + ball.dy)# 边界检查如果 ball.ycor() >第290话-290:winsound.PlaySound('bounce.wav', winsound.SND_ASYNC)ball.dy *= -1如果 ball.xcor() >390:winsound.PlaySound('bounce.wav', winsound.SND_ASYNC)ball.goto(0, 0)球.dx *= -1分数_a += 1pen.clear()pen.write("Player A: {} Player B: {}".format(score_a, score_b), align='center', font=('Courier', 24, 'bold'))如果 ball.xcor() <-390:winsound.PlaySound('bounce.wav', winsound.SND_ASYNC)ball.goto(0, 0)球.dx *= -1score_b += 1pen.clear()pen.write("Player A: {} Player B: {}".format(score_a, score_b), align='center', font=('Courier', 24, 'bold'))# 桨和球碰撞如果 (ball.xcor() > 340 and ball.xcor() < 350) and (ball.ycor() < paddle_b.ycor() + 60 and ball.ycor() > paddle_b.ycor() -60):winsound.PlaySound('bounce.wav', winsound.SND_ASYNC)ball.setx(340)球.dx *= -1if (ball.xcor() < -340 and ball.xcor() > -350) and (ball.ycor() < paddle_a.ycor() + 60 and ball.ycor() > paddle_a.ycor() -60):winsound.PlaySound('bounce.wav', winsound.SND_ASYNC)ball.setx(-340)球.dx *= -1

解决方案

你的 while True: 在像乌龟这样的事件驱动环境中没有立足之地.第一级替换是将您的循环体放入您使用 ontimer() 调用的函数中.这将以固定的时间间隔调用您的例程(确保将 ontimer() 调用作为最后一步,因为它是一次性的.)类似于:

def move_balls():全局 score_a, score_bwn.update()# 移动球ball.setx(ball.xcor() + ball.dx)ball.sety(ball.ycor() + ball.dy)# 边界检查如果 ball.ycor() >第290话-290:winsound.PlaySound('bounce.wav', winsound.SND_ASYNC)ball.dy *= -1如果 ball.xcor() >390:winsound.PlaySound('bounce.wav', winsound.SND_ASYNC)ball.goto(0, 0)球.dx *= -1分数_a += 1pen.clear()pen.write("Player A: {} Player B: {}".format(score_a, score_b), align='center', font=('Courier', 24, 'bold'))elif ball.xcor() <-390:winsound.PlaySound('bounce.wav', winsound.SND_ASYNC)ball.goto(0, 0)球.dx *= -1score_b += 1pen.clear()pen.write("Player A: {} Player B: {}".format(score_a, score_b), align='center', font=('Courier', 24, 'bold'))# 桨和球碰撞如果 (340 < ball.xcor() < 350) 和 (paddle_b.ycor() - 60 < ball.ycor() < paddle_b.ycor() + 60):winsound.PlaySound('bounce.wav', winsound.SND_ASYNC)ball.setx(340)球.dx *= -1elif (-350 < ball.xcor() < -340) 和 (paddle_a.ycor() - 60 < ball.ycor() < paddle_a.ycor() + 60):winsound.PlaySound('bounce.wav', winsound.SND_ASYNC)ball.setx(-340)球.dx *= -1wn.ontimer(move_balls, 100)移动球()

然而,计时器只控制一次调用 move_balls() 的结束和另一次调用开始之间的时间.它没有考虑在方法本身上花费的时间.如果你需要更精确的控制,那么像这样high precision每秒帧数代码可能正是您要找的.

I a made pong game by following this tutorial https://youtu.be/C6jJg9Zan7w The problem I'm having is that speed of the ball (turtle object) is not the same on different computers. For example, on the tutorial instructor's computer the value of ball.dx ball.dy is 2 and the ball speed is normal but on my computer is really fast so I had to set it to 0.1. I think this problem is because different computers can put out more or less frame. I know there is a method in popular game engines (like unity-unreal) that use time instead of frames so variables are global in different computers. Another problem I have is that when I move the paddles speed of the ball slightly changes. I don't know if this is the same issue as above

import turtle
import winsound

wn = turtle.Screen()
wn.title('Pong')
wn.bgcolor('black')
wn.setup(width=800, height=600)
wn.tracer(0)

# Paddle A
paddle_a = turtle.Turtle()
paddle_a.speed(0)
paddle_a.shape('square')
paddle_a.color('white')
paddle_a.penup()
paddle_a.goto(-350, 0)
paddle_a.shapesize(5, 1)

# Paddle B
paddle_b = turtle.Turtle()
paddle_b.speed(0)
paddle_b.shape('square')
paddle_b.color('white')
paddle_b.penup()
paddle_b.goto(350, 0)
paddle_b.shapesize(5, 1)

# Ball
ball = turtle.Turtle()
ball.speed(0)
ball.shape('square')
ball.color('white')
ball.penup()
ball.dx = 0.15
ball.dy = 0.15

# Pen
pen = turtle.Turtle()
pen.speed(0)
pen.color('white')
pen.penup()
pen.goto(0, 260)
pen.write("Player A: 0  Player B: 0", align='center', font=('Courier', 24, 'bold'))
pen.hideturtle()

# Score
score_a = 0
score_b = 0

def paddle_a_up():
    y = paddle_a.ycor()
    y += 20
    paddle_a.sety(y)

def paddle_b_up():
    y = paddle_b.ycor()
    y += 20
    paddle_b.sety(y)

def paddle_a_down():
    y = paddle_a.ycor()
    y += -20
    paddle_a.sety(y)

def paddle_b_down():
    y = paddle_b.ycor()
    y += -20
    paddle_b.sety(y)

# Keyboard binding
wn.listen()
wn.onkeypress(paddle_a_up, 'w')
wn.onkeypress(paddle_a_down, 's')
wn.onkeypress(paddle_b_up, 'Up')
wn.onkeypress(paddle_b_down, 'Down')


# Main game loop
while True:
    wn.update()

    # Moving Ball
    ball.setx(ball.xcor() + ball.dx)
    ball.sety(ball.ycor() + ball.dy)

    # Border checking
    if ball.ycor() > 290 or ball.ycor() < -290:
        winsound.PlaySound('bounce.wav', winsound.SND_ASYNC)
        ball.dy *= -1

    if ball.xcor() > 390:
        winsound.PlaySound('bounce.wav', winsound.SND_ASYNC)
        ball.goto(0, 0)
        ball.dx *= -1
        score_a += 1
        pen.clear()
        pen.write("Player A: {}  Player B: {}".format(score_a, score_b), align='center', font=('Courier', 24, 'bold'))

    if ball.xcor() < -390:
        winsound.PlaySound('bounce.wav', winsound.SND_ASYNC)
        ball.goto(0, 0)

        ball.dx *= -1
        score_b += 1
        pen.clear()
        pen.write("Player A: {}  Player B: {}".format(score_a, score_b), align='center', font=('Courier', 24, 'bold'))

    # Paddle and ball collisions
    if (ball.xcor() > 340 and ball.xcor() < 350) and (ball.ycor() < paddle_b.ycor() + 60 and ball.ycor() > paddle_b.ycor() -60):
        winsound.PlaySound('bounce.wav', winsound.SND_ASYNC)
        ball.setx(340)
        ball.dx *= -1

    if (ball.xcor() < -340 and ball.xcor() > -350) and (ball.ycor() < paddle_a.ycor() + 60 and ball.ycor() > paddle_a.ycor() -60):
        winsound.PlaySound('bounce.wav', winsound.SND_ASYNC)
        ball.setx(-340)
        ball.dx *= -1

解决方案

Your while True: has no place in an event-driven environment like turtle. The first level replacement would be to put the body of your loop into a function that you invoke with ontimer(). This will call your routine at fixed intervals (make sure to include the ontimer() call as the last step as it's a one-shot.) Something like:

def move_balls():
    global score_a, score_b

    wn.update()

    # Moving Ball
    ball.setx(ball.xcor() + ball.dx)
    ball.sety(ball.ycor() + ball.dy)

    # Border checking
    if ball.ycor() > 290 or ball.ycor() < -290:
        winsound.PlaySound('bounce.wav', winsound.SND_ASYNC)
        ball.dy *= -1

    if ball.xcor() > 390:
        winsound.PlaySound('bounce.wav', winsound.SND_ASYNC)
        ball.goto(0, 0)
        ball.dx *= -1
        score_a += 1
        pen.clear()
        pen.write("Player A: {}  Player B: {}".format(score_a, score_b), align='center', font=('Courier', 24, 'bold'))

    elif ball.xcor() < -390:
        winsound.PlaySound('bounce.wav', winsound.SND_ASYNC)
        ball.goto(0, 0)
        ball.dx *= -1
        score_b += 1
        pen.clear()
        pen.write("Player A: {}  Player B: {}".format(score_a, score_b), align='center', font=('Courier', 24, 'bold'))

    # Paddle and ball collisions
    if (340 < ball.xcor() < 350) and (paddle_b.ycor() - 60 < ball.ycor() < paddle_b.ycor() + 60):
        winsound.PlaySound('bounce.wav', winsound.SND_ASYNC)
        ball.setx(340)
        ball.dx *= -1

    elif (-350 < ball.xcor() < -340) and (paddle_a.ycor() - 60 < ball.ycor() < paddle_a.ycor() + 60):
        winsound.PlaySound('bounce.wav', winsound.SND_ASYNC)
        ball.setx(-340)
        ball.dx *= -1

    wn.ontimer(move_balls, 100)

move_balls()

However, the timer only controls the time between the end of one call to move_balls() and the start of another. It doesn't account for the time spent in the method itself. If you need more precise control, then something like this high precision frames per second code might be what you're looking for.

这篇关于如何修复python乌龟中不一致的帧速率(速度)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆