pygame-community / pygame-ce

🐍🎮 pygame - Community Edition is a FOSS Python library for multimedia applications (like games). Built on top of the excellent SDL library.
https://pyga.me
849 stars 140 forks source link

problem with higher fps #2846

Closed pinkteddybearfluff closed 4 months ago

pinkteddybearfluff commented 4 months ago

Environment:

You can get some of this info from the text that pops up in the console when you run a pygame program.

Current behavior:

These issues below only occur at higher FPS( for FPS higher than 334) and used with delta time:

  1. The player rect could only move UP or LEFT irrespective of keys pressed ie; K_W or K_UP or anything else.
  2. Also it couldnt't move outside the game window it just stucks at the LEFT edge or TOP edge of the window as shown in screenshots.
  3. Even if FPS is not as high as 334, at maybe 120 or 200 FPS the left and top movement is smooth and fine but the down and right movement feels slow and down-right movement feels even slow.
  4. If i don't put the FPS value in pygame.time.Clock().tick() and leave it at default FPS ,ie; (around 1000 or 2000 FPS for my pc this will likey cause the above problem)

Expected behavior: Smooth movement in all directions

Screenshots

Screenshot_2024-05-10_21-04-03 Screenshot_2024-05-10_21-04-24

Steps to reproduce:

1.the issue could be reproduced with the test code with any key pressed and at FPS higher than maybe 500 or 1000(334 for me)

Test code

import pygame

pygame.init()
running = True
clock = pygame.time.Clock()
player_surf = pygame.Surface((32,32))
player_surf.fill("red")
player_rect = player_surf.get_rect(center = (640,360))
screen = pygame.display.set_mode((1280,720))

FPS = 500

while running:
    dt = clock.tick(FPS)/1000

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    keys = pygame.key.get_pressed()
    if keys[pygame.K_UP]:
        player_rect.y -= 300*dt
    if keys[pygame.K_DOWN]:
        player_rect.y += 300*dt
    if keys[pygame.K_LEFT]:
        player_rect.x -= 300*dt
    if keys[pygame.K_RIGHT]:
        player_rect.x += 300*dt

    pygame.display.flip()
    screen.fill(pygame.Color(48,48,48))
    screen.blit(player_surf,player_rect)

pygame.quit()
oddbookworm commented 4 months ago

I suspect this is an issue with the fact that normal rects truncate to integers. At higher fps, dt is so small that 300*dt is probably less than 1, making it essentially adding 0 when you add it to an integer. Try using an frect instead or using a vector for your position, and update the rect from that

damusss commented 4 months ago

It's not an issue with pygame, as oddbookworm said it's the wrong rect usage. Either a FRect or a Vector2 would work. replacing get_rect with get_frect completely fixes the issue

pinkteddybearfluff commented 4 months ago

As oddbookworm and Damus666 said , it worked perfectly fine by using frect but it doesn't work with the combination of only get_rect and pygame.math.Vector2() but as get_frect is new I will be using that anyways, so the issue is solved. Thank You

oddbookworm commented 4 months ago

it doesn't work with the combination of only get_rect and pygame.math.Vector2()

No, it works perfectly fine if you use them correctly. Here's your code modified to use a vector for positioning. Note that you should also move the pygame.display.flip() call to after you do your drawing

import pygame

pygame.init()
running = True
clock = pygame.time.Clock()
player_surf = pygame.Surface((32,32))
player_surf.fill("red")
player_pos = pygame.Vector2(640, 360)
player_rect = player_surf.get_rect(center = player_pos)
screen = pygame.display.set_mode((1280,720))

FPS = 500

while running:
    dt = clock.tick(FPS)/1000

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    keys = pygame.key.get_pressed()
    if keys[pygame.K_UP]:
        player_pos.y -= 300*dt
    if keys[pygame.K_DOWN]:
        player_pos.y += 300*dt
    if keys[pygame.K_LEFT]:
        player_pos.x -= 300*dt
    if keys[pygame.K_RIGHT]:
        player_pos.x += 300*dt

    player_rect.center = player_pos

    #pygame.display.flip()
    screen.fill(pygame.Color(48,48,48))
    screen.blit(player_surf, player_rect)
    pygame.display.flip()

pygame.quit()