Character Animation & Sprites
Subscribe to Tech with Tim
IMPORTANT Please download the images for this tutorial from my GitHub or the download button below.
GitHub: Click Here!
Download Zip:
Please place all of these images in the same directory as your python script.
Character Animation
After we've downloaded our images we can start getting ready to anime our character.
The first step is to create a few variables which will be used to determine which way we are facing and keep track of the current image we are showing.
# This goes outside the while loop, near the top of our program left = False right = False walkCount = 0
Now we need to load our images. To load an image in pygame we use pygame.image.load(path). Since we need to load so many images we will be storing some of them in lists for easier accessing later on.
This is the code to load all of our images (I recommend you copy and paste).
# This goes outside the while loop, near the top of the program walkRight = [pygame.image.load('R1.png'), pygame.image.load('R2.png'), pygame.image.load('R3.png'), pygame.image.load('R4.png'), pygame.image.load('R5.png'), pygame.image.load('R6.png'), pygame.image.load('R7.png'), pygame.image.load('R8.png'), pygame.image.load('R9.png')] walkLeft = [pygame.image.load('L1.png'), pygame.image.load('L2.png'), pygame.image.load('L3.png'), pygame.image.load('L4.png'), pygame.image.load('L5.png'), pygame.image.load('L6.png'), pygame.image.load('L7.png'), pygame.image.load('L8.png'), pygame.image.load('L9.png')] bg = pygame.image.load('bg.jpg') char = pygame.image.load('standing.png')
It is often good practice to do all of our drawing from within a function. This means we are going to move our old drawing code that is inside the main loop into a function and make a few modifications.
import pygame pygame.init() win = pygame.display.set_mode((500,500)) pygame.display.set_caption("First Game") walkRight = [pygame.image.load('R1.png'), pygame.image.load('R2.png'), pygame.image.load('R3.png'), pygame.image.load('R4.png'), pygame.image.load('R5.png'), pygame.image.load('R6.png'), pygame.image.load('R7.png'), pygame.image.load('R8.png'), pygame.image.load('R9.png')] walkLeft = [pygame.image.load('L1.png'), pygame.image.load('L2.png'), pygame.image.load('L3.png'), pygame.image.load('L4.png'), pygame.image.load('L5.png'), pygame.image.load('L6.png'), pygame.image.load('L7.png'), pygame.image.load('L8.png'), pygame.image.load('L9.png')] bg = pygame.image.load('bg.jpg') char = pygame.image.load('standing.png') x = 50 y = 50 width = 40 height = 60 vel = 5 isJump = False jumpCount = 10 left = False right = False walkCount = 0 def redrawGameWindow(): global walkCount win.blit(bg, (0,0)) # This will draw our background image at (0,0) pygame.display.update() run = True while run: pygame.time.delay(100) for event in pygame.event.get(): if event.type == pygame.QUIT: run = False keys = pygame.key.get_pressed() if keys[pygame.K_LEFT] and x > vel: x -= vel if keys[pygame.K_RIGHT] and x < 500 - vel - width: x += vel if not(isJump): if keys[pygame.K_SPACE]: isJump = True else: if jumpCount >= -10: y -= (jumpCount * abs(jumpCount)) * 0.5 jumpCount -= 1 else: jumpCount = 10 isJump = False redrawGameWindow() pygame.quit()
Now we are going to set our left and right variables appropriately from inside the main loop.
import pygame pygame.init() win = pygame.display.set_mode((500,500)) pygame.display.set_caption("First Game") walkRight = [pygame.image.load('R1.png'), pygame.image.load('R2.png'), pygame.image.load('R3.png'), pygame.image.load('R4.png'), pygame.image.load('R5.png'), pygame.image.load('R6.png'), pygame.image.load('R7.png'), pygame.image.load('R8.png'), pygame.image.load('R9.png')] walkLeft = [pygame.image.load('L1.png'), pygame.image.load('L2.png'), pygame.image.load('L3.png'), pygame.image.load('L4.png'), pygame.image.load('L5.png'), pygame.image.load('L6.png'), pygame.image.load('L7.png'), pygame.image.load('L8.png'), pygame.image.load('L9.png')] bg = pygame.image.load('bg.jpg') char = pygame.image.load('standing.png') x = 50 y = 50 width = 40 height = 60 vel = 5 isJump = False jumpCount = 10 left = False right = False walkCount = 0 def redrawGameWindow(): global walkCount win.blit(bg, (0,0)) # This will draw our background image at (0,0) pygame.display.update() run = True while run: pygame.time.delay(100) for event in pygame.event.get(): if event.type == pygame.QUIT: run = False keys = pygame.key.get_pressed() if keys[pygame.K_LEFT] and x > vel: x -= vel left = True right = False elif keys[pygame.K_RIGHT] and x < 500 - vel - width: x += vel left = False right = True else: # If the character is not moving we will set both left and right false and reset the animation counter (walkCount) left = False right = False walkCount = 0 if not(isJump): if keys[pygame.K_SPACE]: isJump = True right = False left = False walkCount = 0 else: if jumpCount >= -10: y -= (jumpCount * abs(jumpCount)) * 0.5 jumpCount -= 1 else: jumpCount = 10 isJump = False redrawGameWindow() pygame.quit()
And finally we can start working on drawing our character to the screen.
NOTE: This is very complex, please refer to the video for more in depth explanations.
def redrawGameWindow(): # We have 9 images for our walking animation, I want to show the same image for 3 frames # so I use the number 27 as an upper bound for walkCount because 27 / 3 = 9. 9 images shown # 3 times each animation. global walkCount win.blit(bg, (0,0)) if walkCount + 1 >= 27: walkCount = 0 if left: # If we are facing left win.blit(walkLeft[walkCount//3], (x,y)) # We integer divide walkCounr by 3 to ensure each walkCount += 1 # image is shown 3 times every animation elif right: win.blit(walkRight[walkCount//3], (x,y)) walkCount += 1 else: win.blit(char, (x, y)) # If the character is standing still pygame.display.update()
The last thing we need to do is change our framerate.
To do this we are going to create a clock object using clock = pygame.time.Clock() outside of our main loop and write clock.tick(27) inside our main loop.
You may notice when running the program that the background does not cover the entire screen, to fix this simply change there screen height to 480.
pygame.display.set_mode((500, 480))
Full Code
The full code should look like the following.
import pygame pygame.init() win = pygame.display.set_mode((500,480)) pygame.display.set_caption("First Game") walkRight = [pygame.image.load('R1.png'), pygame.image.load('R2.png'), pygame.image.load('R3.png'), pygame.image.load('R4.png'), pygame.image.load('R5.png'), pygame.image.load('R6.png'), pygame.image.load('R7.png'), pygame.image.load('R8.png'), pygame.image.load('R9.png')] walkLeft = [pygame.image.load('L1.png'), pygame.image.load('L2.png'), pygame.image.load('L3.png'), pygame.image.load('L4.png'), pygame.image.load('L5.png'), pygame.image.load('L6.png'), pygame.image.load('L7.png'), pygame.image.load('L8.png'), pygame.image.load('L9.png')] bg = pygame.image.load('bg.jpg') char = pygame.image.load('standing.png') x = 50 y = 400 width = 40 height = 60 vel = 5 clock = pygame.time.Clock() isJump = False jumpCount = 10 left = False right = False walkCount = 0 def redrawGameWindow(): global walkCount win.blit(bg, (0,0)) if walkCount + 1 >= 27: walkCount = 0 if left: win.blit(walkLeft[walkCount//3], (x,y)) walkCount += 1 elif right: win.blit(walkRight[walkCount//3], (x,y)) walkCount += 1 else: win.blit(char, (x, y)) walkCount = 0 pygame.display.update() run = True while run: clock.tick(27) for event in pygame.event.get(): if event.type == pygame.QUIT: run = False keys = pygame.key.get_pressed() if keys[pygame.K_LEFT] and x > vel: x -= vel left = True right = False elif keys[pygame.K_RIGHT] and x < 500 - vel - width: x += vel left = False right = True else: left = False right = False walkCount = 0 if not(isJump): if keys[pygame.K_SPACE]: isJump = True left = False right = False walkCount = 0 else: if jumpCount >= -10: y -= (jumpCount * abs(jumpCount)) * 0.5 jumpCount -= 1 else: jumpCount = 10 isJump = False redrawGameWindow() pygame.quit()