voce pode tentar isso:
import time
ti = time.time()
while True:
tf = time.time()
dt = tf - ti
ti = tf
if dt >= 500:
if key[pygame.K_LEFT] or key[pygame.K_a]:
new_posx -= 64
self.context["direction"] = "WEST"
self.frame_motion()
if key[pygame.K_RIGHT] or key[pygame.K_d]:
new_posx += 64
self.context["direction"] = "EAST"
self.frame_motion()
if key[pygame.K_UP] or key[pygame.K_w]:
new_posy -= 64
self.context["direction"] = "NORTH"
self.frame_motion()
if key[pygame.K_DOWN] or key[pygame.K_s]:
new_posy += 64
self.context["direction"] = "SOUTH"
self.frame_motion()
if not self.check_map_colision(new_posx, new_posy):
self.rect.x = new_posx
self.rect.y = new_posy
self.context["posx"] = self.rect.x
self.context["posy"] = self.rect.y
self.can_move = True
else:
self.can_move = False
Desta forma o movimento so ira ocorrer com um certo delay, mas nao afetar os updates. Claro que o 500 do if e um exemplo coloque o valor que achar melhor. Este valor é produzido em milissegundos só para ficar mais declarado.
Fonte: https://humberto.io/pt-br/blog/desbravando-o-pygame-5-movimento-e-colisao/