Menu
CoddyTech

תנועה חלקה בכל קצב פריימים

חלק מהיחידה צליל ותחושת משחק במסלול ה-Pygame של Coddy. שיעור 19 מתוך 23.

x += (target_x - x) * 0.1 מתקדם עשירית מהדרך בכל פריים. בקצב של 60 פריימים בשנייה, מדובר ב-60 צעדים בשנייה; במחשב איטי שמצליח להציג רק 30, מדובר ב-30 צעדים, ולמעגל לוקח פי שניים זמן להגיע. לחצו על F כדי לראות: המשחק פועל בקצב של 30, והכול נע באיטיות רבה יותר.

הפתרון הוא למדוד זמן. clock.tick() מחזירה את מספר אלפיות השנייה מאז הפריים האחרון. כשמחלקים ב-1000 מקבלים את dt, משך הפריים בשניות: בערך 0.017 בקצב של 60 פריימים בשנייה, ו-0.033 בקצב של 30.

dt = 1 / 60          # לפני הלולאה
...
step = min(1, 6 * dt)
x += (target_x - x) * step
...
dt = clock.tick(fps) / 1000

בפריים ארוך יותר הצעד גדול יותר, ולכן המעגל עובר את אותו המרחק באותו זמן בכל קצב פריימים. המספר 6 קובע את המהירות: בקצב של 60 פריימים בשנייה, 6 * dt הוא בערך 0.1, אותה עשירית כמו קודם. min(1, ...) מונעת מפריים ארוך מאוד להתקדם מעבר ליעד.

אותו עיקרון חל גם על תנועה רגילה: player_x += 240 * dt הוא 240 פיקסלים בשנייה, בלי קשר לקצב הפריימים. רוב המשחקים הקטנים מקבעים את הקצב באמצעות tick(60) ולא צריכים זאת אף פעם; השתמשו ב-dt כשהקצב עשוי להשתנות.

challenge icon

אתגר

בינוני

F מעביר את המשחק בין 60 ל־30 פריימים בשנייה. דאג שהתנועה המדורגת תימשך אותו זמן בשני המצבים:

  1. הגדר dt = 1 / 60 לפני הלולאה.
  2. בסוף הלולאה, הגדר dt = clock.tick(fps) / 1000.
  3. הזז באמצעות step = min(1, 6 * dt) במקום 0.1: x += (target_x - x) * step, ובאותו אופן גם עבור y.

נסו בעצמכם

import pygame

pygame.init()
screen = pygame.display.set_mode((480, 360))
pygame.display.set_caption("Any Frame Rate")
clock = pygame.time.Clock()
font = pygame.font.Font(None, 28)

x, y = 240, 180
target_x, target_y = 240, 180
fps = 60

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.MOUSEBUTTONDOWN:
            target_x, target_y = event.pos
        elif event.type == pygame.KEYDOWN and event.key == pygame.K_f:
            fps = 30 if fps == 60 else 60

    x += (target_x - x) * 0.1
    y += (target_y - y) * 0.1

    screen.fill((30, 30, 46))
    pygame.draw.circle(screen, (80, 200, 220), (x, y), 12)
    label = font.render(f"{fps} FPS (F to change)", True, (240, 240, 240))
    screen.blit(label, (10, 10))
    pygame.display.flip()
    clock.tick(fps)

pygame.quit()
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה צליל ותחושת משחק

תרגלו בעצמכם: Pygame אונליין