python - ball animation is really junky while running pong game
问题描述
the ball animation while running the program is very stuttery and i can't figure out why. this is just the beggining of the program so ignore the fact that the game isn't ready to play yet.
this is the code: https://www.codepile.net/pile/dqKZa8OG
i want the ball to move smoothly without stuttering. and in addition how do i make it so the program deletes the last location of the ball after each update?
解决方案
It's not "junky" because of the timer, you can only see updates since you're probably moving the mouse in the meantime, then you're updating the ball position everytime you move it (which is wrong, as you're updating the position anytime any events is processed).
The problem is that you're using Clock
in the wrong way: the pygame.time.Clock
class creates an «object that can be used to track an amount of time», meaning that it is not a timer that can "react" once it times out. The tick
method you're calling only updates the current Clock returning how many milliseconds have passed since the last call to tick
itself, based on the fps argument you are providing.
What you need is to set a timer, possibly by using a specific eventid just for the updates. Also, since you're updating the ball position based on the events, you'll get more movements if you move the mouse (or any other event is called) making the ball move faster even if it shouldn't - and that's what you'll need the Clock object for.
# I'm using a smaller speed, otherwise it'll be too fast; it should
# depend on the window size to ensure that bigger windows don't get
# slower speeds
ball_velocity = .2
fps = 60
UPDATEEVENT = 24
[...]
def start_move_ball(angle):
ticks = clock.tick()
speed = ball_velocity * ticks
# "global ball" is not required, as you are assigning values to an
# existing object, not declaring it everytime.
# You can also use in-place operations to set the speeds, which is
# better for readability too.
ball[0] += angle[0] * speed
ball[1] += angle[1] * speed
def main_loop():
angle = choose_angle()
pygame.time.set_timer(UPDATEEVENT, 1000 // fps)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
return False
# update only if necessary!
elif event.type == UPDATEEVENT:
window.fill((0,0,0))
start_move_ball(angle)
draw_mid(window)
draw_players(window)
draw_ball(window)
pygame.display.flip()
The timer is set outside the while
cycle, as it automatically sends the event each time interval. You could also leave it within the while
(the once=True
argument is not really required in this case, as it automatically updates the timer based on the same eventid), but wouldn't make much sense, since set_timer
always fires the event after the first time it's set.
I'm using 24 (pygame.USEREVENT
) as an eventid, but you can set its id up to pygame.NUMEVENTS - 1
, as suggested in the event documentation. If for any reason you want to stop the timer, just use pygame.time.set_timer(eventid, 0)
and the timer for that eventid (24 in this case) will not be fired up again.
A couple of suggestions, besides all:
- Remove the
pygame.display.update()
line indraw_mid(window)
, since it causes flickering while painting. - Avoid using external services to link code (it's not your case, but if the code is too long, first try to reduce it to minimal, reproducible example, eventually leaving all the relevant parts), as they could become unavailable sometime in the future, making your question hard to understand to somebody that is facing a similar issue and reads your answer some time after you posted it.
推荐阅读
- laravel - Laravel elequent 模型/关系
- c# - 如何使用 Open XML 将美化的 JSON 字符串插入 Word 文档中的表格单元格
- pip - 开发模式下无法使用本地构建的python包
- swift - 根据绘制的框架,裁剪无法正常工作
- docker-compose - Docker-compose 卷错误:格式不正确,应该是 external:internal[:mode]
- ios - Xcode 12.4 React 本机构建在 IOS 中失败,显示所有消息命令 PhaseScriptExecution 失败,退出代码为非零
- c++ - 为什么即使一切都正确,我的 C++ 代码仍会返回一些奇怪的数字?
- python - 如何将列表内列表的值分配给列表内另一个列表的值(python)?
- c# - 是否可以在 Console.WriteLine 或 Console.ReadKey 中添加延迟以显示文本?
- angular - 如何使用 mergeMap 对链式请求进行单元测试