builtins.IndexError: list index out of range pygame animation

Viewed 73
import pygame
pygame.init()

win = pygame.display.set_mode((1280,800))
pygame.display.set_caption("First Game")

walkLeft = [pygame.image.load('/Users/arnav/Downloads/Jokerattack1.png'), 
pygame.image.load('/Users/arnav/Downloads/Jokerattack2.png'), 
pygame.image.load('/Users/arnav/Downloads/Jokerattack3.png')]
walkRight = [pygame.image.load('/Users/arnav/Downloads/Jokerattack1Right.png'), 
pygame.image.load('/Users/arnav/Downloads/Jokerattack2Right.png'), 
pygame.image.load('/Users/arnav/Downloads/Jokerattack3Right.png')]
Joker1 = pygame.image.load('/Users/arnav/Downloads/Joker.png')
char = pygame.transform.scale(Joker1, (80, 132)) 
bg1 = pygame.image.load('/Users/arnav/Downloads/GothamCity.jpg')
bg = pygame.transform.scale(bg1, (1280, 800))
x = 0
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 >= 9:
        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(12)

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

    keys = pygame.key.get_pressed()

    if keys[pygame.K_LEFT] or keys[ord('a')] and x > vel: 
        x -= vel
        left = True
        right = False

    elif keys[pygame.K_RIGHT] or keys[ord('d')] and x < 900 - vel - width:  
        x += vel
        left = False
        right = True
    
    else: 
        left = False
        right = False
        walkCount = 0
    
    if not(isJump):
        if keys[pygame.K_UP] or keys[ord('w')]:
            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
        
        
    def redrawGameWindow2():
        global walkCount

        if keys[pygame.K_SPACE]:
            walkLeft = [pygame.image.load('/Users/arnav/Downloads/Jokerattack1.png'), 
pygame.image.load('/Users/arnav/Downloads/Jokerattack2.png'), 
pygame.image.load('/Users/arnav/Downloads/Jokerattack3.png'), 
pygame.image.load('/Users/arnav/Downloads/Jokerattack4.png')]
            walkRight = 
[pygame.image.load('/Users/arnav/Downloads/Jokerattack1Right.png'), 
pygame.image.load('/Users/arnav/Downloads/Jokerattack2Right.png'), 
pygame.image.load('/Users/arnav/Downloads/Jokerattack3Right.png'), 
pygame.image.load('/Users/arnav/Downloads/Jokerattack3Right.png')]

    win.blit(bg, (0,0))  
    if walkCount + 1 >= 12:
        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()             
        

    redrawGameWindow2() 




pygame.quit()

In this program, I am trying to make it so that when you press arrow keys, the character walks, and when you press space, the animation extends to attack. I tried to do this by redrawing the game window for a second time and the arrow keys work but when I press space it gives me a builtins.IndexError: list index out of range pygame animation.

2 Answers

Before using the index to get an item from the list, compare the index to the length of the list:

def redrawGameWindow():
    global walkCount

    win.blit(bg, (0,0))  
    
    if left:  
        if walkCount // 3 >= len(walkLeft): 
            walkCount = 0
        win.blit(walkLeft[walkCount//3], (x,y))
        walkCount += 1                          
    elif right:
        if walkCount // 3 >= len(walkRight): 
            walkCount = 0
        win.blit(walkRight[walkCount//3], (x,y))
        walkCount += 1
    else:
        win.blit(char, (x, y))
        walkCount = 0
    
    pygame.display.update() 

Or use the % (modulo) operator. The modulo operator calculates the remainder of a division.

def redrawGameWindow():
    global walkCount

    win.blit(bg, (0,0))  
    
    if left:  
        win.blit(walkLeft[(walkCount//3) % len(walkLeft)], (x,y))
        walkCount += 1                          
    elif right:
        win.blit(walkRight[(walkCount//3) % len(walkRight)], (x,y))
        walkCount += 1
    else:
        win.blit(char, (x, y))
        walkCount = 0
    
    pygame.display.update() 

Do the same for redrawGameWindow2:

def redrawGameWindow2():
    # [...]

    if left:  
        win.blit(walkLeft[(walkCount//3) % len(walkLeft)], (x,y))
        walkCount += 1                          
    elif right:
        win.blit(walkRight[(walkCount//3) % len(walkRight)], (x,y))
        walkCount += 1
    else:
        win.blit(char, (x, y))
        walkCount = 0

    # [...]

You're using the // floor division operator to clamp the animation index instead of modulo %.

So when you press space on the 12th frame you get an out of range error 12 // 3 = 4

Instead you need to use walkLeft[walkCount % len(walkLeft)]

0 % 4 = 0
1 % 4 = 1
[..]
4 % 4 = 0
5 % 4 = 1
Related