0
\$\begingroup\$

I didn't see any other questions like this that had an answer so I thought I'd ask in hopes this helps someone else too. I have a game I'm in the beginning stages of working on, and I've gotten to the point where I have a sprite on the screen that I am animating to make it look like it's walking.

The issue is when I move the images too quickly across the screen, the images start to get blurry. I've done a little googling, but I'm still not quite sure what's going on. See here for a video of it.

When I turn the SPEED variable up, the walking gets blurry, but when it's turned down to 10 or below, it's no longer blurry. From what I could tell this is maybe frame ghosting, but there are other phenomena it could be as well, and I'm too new to game development to know how to solve it. I have added and taken away clock.tick() to see if my sprite frame limiting function may be the cause, but it seems to be the same.

You can take a look at my repo here or take a look at the code below. p.s. I know I need to move the sprites into a sheet, and load them using list comprehension or something, just haven't gotten around to it yet.

# Import the pygame module import pygame from common_utilities import * from time import time # Import pygame.locals for easier access to key coordinates # Updated to conform to flake8 and black standards from pygame.locals import ( K_w, K_s, K_a, K_d, K_UP, K_DOWN, K_ESCAPE, KEYDOWN, QUIT, ) BLUE = (0,0,255) PURPLE = (153,50,204) GREEN = (0,128,0) MAP = [[BLUE, GREEN, BLUE], [GREEN, PURPLE, GREEN], [PURPLE, GREEN, BLUE]] DEBUG = False # Define constants for the screen width and height SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600 SPEED = 15 # Setup the clock for a decent framerate clock = pygame.time.Clock() #Constants SCREENS = 3 SPRITE_SIZE = (150,198) SCREEN_SIZE = (SCREEN_WIDTH,SCREEN_HEIGHT) worldMaxX = SCREEN_SIZE[0]*SCREENS worldMaxY = SCREEN_SIZE[1]*SCREENS class FrameRate(): def __init__(self,dT): self.previousTime = 0 self.currentTime = 0 self.elapsed_time = 0 self.dT = dT def integrate_state(self,callback,*args): ''' ''' self.callback = callback self.currentTime = int(time()*1000) self.elapsed_time += self.currentTime - self.previousTime if (DEBUG): print('self.elapsed_time:',self.elapsed_time) self.previousTime = self.currentTime if (self.elapsed_time >= int(self.dT)): if (DEBUG): print('self.elapsed_time:',self.elapsed_time) #Call function after elapsed time self.callback(*args) #Reset elapsed time self.elapsed_time = 0 class Camera(): def __init__(self): self.worldX = 1000 self.worldY = 1000 self.cameraX = SCREEN_SIZE[0] self.cameraY = SCREEN_SIZE[1] self.screen = [2, 2] def worldCoordinates(self,screenX, screenY): worldX = self.screen[0]*SCREEN_SIZE[0] + screenX worldY = self.screen[1]*SCREEN_SIZE[1] + screenY return (worldX, worldY) def screenCoordinates(self,worldX, worldY): screenX = worldX - self.screen[0]*SCREEN_SIZE[0] screenY = worldY - self.screen[1]*SCREEN_SIZE[1] return (screenX,screenY) def updateCamera(self,position): #Move player to other side of screen when crossing screens if (position.x < -SPRITE_SIZE[0] and self.screen[0] != 0): position.x = SCREEN_SIZE[0] if (self.screen[0] >= 1): self.screen[0] -= 1 elif (position.x > SCREEN_SIZE[0] and self.screen[0] != 2): position.x = 0 if (self.screen[0] < SCREENS-1): self.screen[0] += 1 if (position.y < -25 and self.screen[1] != 0): position.y += SCREEN_SIZE[1] if (self.screen[1] >= 1): self.screen[1] -= 1 elif (position.y > SCREEN_SIZE[1] and self.screen[1] != 2): position.y = 0 if (self.screen[1] < SCREENS-1): self.screen[1] += 1 #Prevent player from leaving edge of map if (position.x < 0 and self.screen[0] == 0): position.x = 0 elif (position.x > SCREEN_SIZE[0]-SPRITE_SIZE[0] and self.screen[0] == 2): position.x = SCREEN_SIZE[0]-SPRITE_SIZE[0] if (position.y < 0 and self.screen[1] == 0): position.y = 0 if (position.y > SCREEN_SIZE[1]-SPRITE_SIZE[1] and self.screen[1] == 2): position.y = SCREEN_SIZE[1]-SPRITE_SIZE[1] if (DEBUG): print('self.screen:',self.screen) print('self.worldX:',self.worldX) print('self.worldY:',self.worldY) print('self.rect.x:',position.x) print('self.rect.y:',position.y) return self.screen class Player(Camera): def __init__(self): super(Player,self).__init__() self.orientation = 'Right' self.images = [] self.images.append(pygame.image.load('C:/Games/Random_World/Assets/Sprites/pumpking_walk/walk1.png')) self.images.append(pygame.image.load('C:/Games/Random_World/Assets/Sprites/pumpking_walk/walk2.png')) self.images.append(pygame.image.load('C:/Games/Random_World/Assets/Sprites/pumpking_walk/walk3.png')) self.images.append(pygame.image.load('C:/Games/Random_World/Assets/Sprites/pumpking_walk/walk4.png')) self.images.append(pygame.image.load('C:/Games/Random_World/Assets/Sprites/pumpking_walk/walk5.png')) self.images.append(pygame.image.load('C:/Games/Random_World/Assets/Sprites/pumpking_walk/walk6.png')) self.images.append(pygame.image.load('C:/Games/Random_World/Assets/Sprites/pumpking_walk/walk7.png')) self.images.append(pygame.image.load('C:/Games/Random_World/Assets/Sprites/pumpking_walk/walk8.png')) self.images.append(pygame.image.load('C:/Games/Random_World/Assets/Sprites/pumpking_walk/walk9.png')) self.images.append(pygame.image.load('C:/Games/Random_World/Assets/Sprites/pumpking_walk/walk10.png')) self.index = 0 self.image = self.images[self.index] self.position = struct(x=0,y=0) def update(self, pressed_keys): global SPEED if (pressed_keys[K_UP]): SPEED += 1 print('SPEED:',SPEED,flush=True) elif (pressed_keys[K_DOWN]): SPEED -= 1 print('SPEED:',SPEED,flush=True) if (SPEED <= 0): SPEED = 0 if self.index > len(self.images)-1: self.index = 0 # Move the SPRITE_SIZE based on user keypresses if pressed_keys[K_w]: self.worldX,self.worldY = self.worldCoordinates(self.position.x,self.position.y) self.worldY -= SPEED self.orientation = 'Right' self.image = self.images[self.index] self.index += 1 self.position.x,self.position.y = self.screenCoordinates(self.worldX,self.worldY) if self.index > len(self.images)-1: self.index = 0 if pressed_keys[K_s]: self.worldX,self.worldY = self.worldCoordinates(self.position.x,self.position.y) self.worldY += SPEED self.orientation = 'Left' self.image = self.images[self.index] self.index += 1 self.position.x,self.position.y = self.screenCoordinates(self.worldX,self.worldY) if self.index > len(self.images)-1: self.index = 0 if pressed_keys[K_a]: self.worldX,self.worldY = self.worldCoordinates(self.position.x,self.position.y) self.worldX -= SPEED self.orientation = 'Left' self.image = self.images[self.index] self.index += 1 self.position.x,self.position.y = self.screenCoordinates(self.worldX,self.worldY) if self.index > len(self.images)-1: self.index = 0 if pressed_keys[K_d]: self.worldX,self.worldY = self.worldCoordinates(self.position.x,self.position.y) self.worldX += SPEED self.orientation = 'Right' self.image = self.images[self.index] self.index += 1 self.position.x,self.position.y = self.screenCoordinates(self.worldX,self.worldY) if ((not pressed_keys[K_a]) and (not pressed_keys[K_s]) and (not pressed_keys[K_w]) and (not pressed_keys[K_d])): self.image = self.images[0] def render(self,surface,position): if self.orientation == "Right": screen.blit(surface, (position.x,position.y)) elif self.orientation == "Left": screen.blit(pygame.transform.flip(surface, True, False), (position.x,position.y)) class Map(): def __init__(self,world): self.map = world self.map_view = PURPLE def update(self,coordinates): self.map_view = self.map[coordinates[0]][coordinates[1]] if (DEBUG): print('self.map_view:',self.map_view) def render(self,screen): screen.fill(self.map_view) # Initialize pygame pygame.init() # Create the screen object # The size is determined by the constant SCREEN_SIZE[0] and SCREEN_SIZE[1] screen = pygame.display.set_mode((SCREEN_SIZE[0], SCREEN_SIZE[1])) # Instantiate player. Right now, this is just a rectangle. player = Player() #Instantiate map, takes list of lists map to be rendered world = Map(MAP) # Variable to keep the main loop running running = True frame = FrameRate(100) # Main loop while running: # for loop through the event queue for event in pygame.event.get(): # Check for KEYDOWN event if event.type == KEYDOWN: # If the Esc key is pressed, then exit the main loop if event.key == K_ESCAPE: running = False # Check for QUIT event. If QUIT, then set running to false. elif event.type == QUIT: running = False # Get all the keys currently pressed pressed_keys = pygame.key.get_pressed() frame.integrate_state(player.update,pressed_keys) worldScreen = player.updateCamera(player.position) world.update(worldScreen) world.render(screen) # Draw the player on the screen player.render(player.image,player.position) # Update the display pygame.display.update() 
\$\endgroup\$
5
  • \$\begingroup\$ I'm not sure I see any blur. Did you check the gif you posted on a different device to confirm the issue? \$\endgroup\$ Commented Jan 26, 2021 at 1:33
  • \$\begingroup\$ Looks the same on my android phone, it's not terribly blurry, but I assumed I was doing something wrong in my code that it seems out of focus a bit unless the speed is like 10 pixels or lower (I think position += 10 would be pixels anyway) \$\endgroup\$ Commented Jan 26, 2021 at 1:35
  • \$\begingroup\$ I don't notice a blur here either. Can you capture a still of the image on one of the blurred frames so we can see the effect? \$\endgroup\$ Commented Jan 26, 2021 at 4:26
  • \$\begingroup\$ I'll see if I can, it's kinda hard to get a screen capture when it's burry. All the screen captures I just did had no blur as a still. Maybe my eyes are just getting bad, I don't know. \$\endgroup\$ Commented Jan 26, 2021 at 4:28
  • \$\begingroup\$ Maybe I should rephrase, it's not blurry per-se, as in the image itself is blurry, but it's harder to follow with my eyes when the speed is faster, appearing like there image is no longer clear in the rendering. I assumed it was a problem with my code. Could this just be an optical illusion, or a specific issue with my video as some internet posts have suggested? I saw something that mentioned frame ghosting as an issue, and it's got something to do with high contrast between the background and the image moving around on screen. Could it be that? \$\endgroup\$ Commented Jan 26, 2021 at 16:08

0

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.