1

I have been trying to figure this out all day and have searched countless posts. I am trying to figure out how to get my sprite to perform an attack animation but there is literally no documentation or information that I could find about how to do this online. I've gotten it to where he will perform the spinning attack animation if I am moving right but after so many spins, the game will crash and say 'list index out of range.' Also, pressing the attack key 'w' does absolutely nothing if the character is standing still. I've included a copy of my code. Any help would be greatly appreciated.

import pygame
import os
os.chdir('C:\\Users\\Name\\Desktop\\Character Animation\\')
pygame.init()
pygame.mixer.init()

WIDTH = 1920
HEIGHT = 1080
FPS = 60

screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption('Game')

''' IMAGE RESIZING___________________________________________________________'''
wRight1 = pygame.image.load('row2_1.png')
wRight1 = pygame.transform.scale(wRight1, (80,80))
wRight2 = pygame.image.load('row2_2.png')
wRight2 = pygame.transform.scale(wRight2, (80,80))
wRight3 = pygame.image.load('row2_3.png')
wRight3 = pygame.transform.scale(wRight3, (80,80))
wRight4 = pygame.image.load('row2_4.png')
wRight4 = pygame.transform.scale(wRight4, (80,80))
wRight5 = pygame.image.load('row2_5.png')
wRight5 = pygame.transform.scale(wRight5, (80,80))
wRight6 = pygame.image.load('row2_6.png')
wRight6 = pygame.transform.scale(wRight6, (80,80))
wRight7 = pygame.image.load('row2_7.png')
wRight7 = pygame.transform.scale(wRight7, (80,80))``
wRight8 = pygame.image.load('row2_8.png')
wRight8 = pygame.transform.scale(wRight8, (80,80))


wLeft1 = pygame.image.load('row10_1.png')
wLeft1 = pygame.transform.scale(wLeft1, (80,80))
wLeft2 = pygame.image.load('row10_2.png')
wLeft2 = pygame.transform.scale(wLeft2, (80,80))
wLeft3 = pygame.image.load('row10_3.png')
wLeft3 = pygame.transform.scale(wLeft3, (80,80))
wLeft4 = pygame.image.load('row10_4.png')
wLeft4 = pygame.transform.scale(wLeft4, (80,80))
wLeft5 = pygame.image.load('row10_5.png')
wLeft5 = pygame.transform.scale(wLeft5, (80,80))
wLeft6 = pygame.image.load('row10_6.png')
wLeft6 = pygame.transform.scale(wLeft6, (80,80))
wLeft7 = pygame.image.load('row10_7.png')
wLeft7 = pygame.transform.scale(wLeft7, (80,80))
wLeft8 = pygame.image.load('row10_8.png')
wLeft8 = pygame.transform.scale(wLeft8, (80,80))


spinAttackR1 = pygame.image.load('spinattackright1.png')
spinAttackR1 = pygame.transform.scale(spinAttackR1, (90,90))
spinAttackR2 = pygame.image.load('spinattackright2.png')
spinAttackR2 = pygame.transform.scale(spinAttackR2, (90,90))


standStill1 = pygame.image.load('standStill1.png')
standStill1 = pygame.transform.scale(standStill1, (80,80))
standStill2 = pygame.image.load('standStill2.png')
standStill2 = pygame.transform.scale(standStill2, (80,80))
standStill3 = pygame.image.load('standStill3.png')
standStill3 = pygame.transform.scale(standStill3, (80,80))
standStill4 = pygame.image.load('standStill4.png')
standStill4 = pygame.transform.scale(standStill4, (80,80))

'''_________________________________________________________________________'''

bg = pygame.image.load('bg.png')
spinAttackList = [spinAttackR1, spinAttackR2, spinAttackR1, spinAttackR2,
                  spinAttackR1, spinAttackR2, spinAttackR1, spinAttackR2,
                  spinAttackR1, spinAttackR2, spinAttackR1, spinAttackR2,
                  spinAttackR1, spinAttackR2, spinAttackR1, spinAttackR2,
                  spinAttackR1, spinAttackR2, spinAttackR1, spinAttackR2,
                  spinAttackR1, spinAttackR2, spinAttackR1, spinAttackR2,
                  spinAttackR1, spinAttackR2, spinAttackR1, spinAttackR2,
                  spinAttackR1, spinAttackR2, spinAttackR1, spinAttackR2]
walkRight = [wRight1, wRight2,
             wRight3, wRight4,
             wRight5, wRight6,
             wRight7, wRight8]
walkLeft = [wLeft1, wLeft2,
             wLeft3, wLeft4,
             wLeft5, wLeft6,
             wLeft7, wLeft8]

#char = [standStill1, standStill2, standStill3, standStill4]

char = pygame.image.load('topDownattackRight3.png')
char = pygame.transform.scale(char, (80,80))
#R = char.get_rect()

clock = pygame.time.Clock()

WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)

x = 50
y = 770
width = 64
height = 64
vel = 5

isJump = False
jumpCount = 10

spin = False
left = False
right = False
walkCount = 0
attackCount = 0

'''DRAWING SECTION___________________________________________________________'''
def redrawGameWindow():
    global walkCount
    global attackCount
    screen.blit(bg, (0,0))

    if walkCount + 1 >= 24:
        walkCount = 0

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

    if spin:
        screen.blit(spinAttackList[attackCount//3], (x,y))

    pygame.display.update()


#mainloop
run = True
while run:
    clock.tick(30)

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

    keys = pygame.key.get_pressed()
#_________________________________________________________________________
    if keys[pygame.K_w]:
        spin = True

    if keys[pygame.K_LEFT] and x > vel:
        x -= vel
        left = True
        right = False
    elif keys[pygame.K_RIGHT] and x < WIDTH - 40:
        x += vel
        right = True
        left = False
    else:
        right = False
        left = False
        walkCount = 0
        spin = False

    if not(isJump):
        if keys[pygame.K_SPACE]:
            isJump = True
            right = False
            left = False
            walkCount = 0
    else:
        if jumpCount >= -10:
            neg = 1
            if jumpCount < 0:
                neg = -1
            y -= (jumpCount ** 2) * 0.5 * neg
            jumpCount -= 1
        else:
            isJump = False
            jumpCount = 10

    redrawGameWindow()

pygame.quit()
NotmyName
  • 21
  • 1
  • 5
  • 1
    There's [plenty of examples](https://www.pygame.org/tags/animation) on how others have solved it. There's also resources on [SO](https://stackoverflow.com/questions/14044147/animated-sprite-from-few-images) on how to animate sprites. Which of these have you looked at? – Torxed Feb 04 '19 at 17:50
  • 1
    I've been looking through the documentation including the tutorial in the pygame docs on moving images. I've also tried implement code from youtube tutorials and tailor them to my needs specifically but they are making different types of games. I've searched posts on how to infinitely iterate through a list. How to repeat lists in python. Read that image.blit cannot blit lists though image.blit is blitting my list of walking images just fine. Maybe I just don't know what to look for? I can assure you I'm not being lazy and trying to find an easy answer if that's what you suspect. – NotmyName Feb 04 '19 at 17:58
  • If you want to rotate the list, you could just do `walkLeft[walkCount % len(walkLeft-1)]`? Make it loop around on it's own. Assuming it's a perfect animation with start/end of the list and you don't have to do the animation backwards. (also, not saying you're lazy hehe. But I think the solution is simpler than the problem is made out to be) – Torxed Feb 04 '19 at 18:01
  • Hello again, thank you for your response. Sorry if my previous comment came off wrong. I'm just really having a hard time with this and I don't know what to look for as I'm new to pygame and programming in general. I will look into what you suggested but it seems my problem isn't as much with the walking portion of the code and more with the attack animation trying to happen at the same time as the walk animation and the attack animation seems to run out of images from the list while im still pressing the key and the game crashes. – NotmyName Feb 04 '19 at 18:27
  • Hehe, no worries :) Oh, I think we need to see the sprite in question. Because I'm not sure how you're supposed to use two separate images for your walk+attack animation. Usually those are the same image-object. It's usually easier to solve it that way. Because stitching together two images - is pretty hard work if you're doing it manually in comparison. – Torxed Feb 04 '19 at 18:38
  • On a side note, the title itself might be missleading. Because blitting multiple images is a thing if you place them in a [Group/batch](https://gamedev.stackexchange.com/questions/15513/batch-blit-vs-separate-blit). Altho Pygame doesn't do this very efficiently or nicely, it is a thing. Pyglet has actual batches that renders insanely fast. But that's outside of this question heh :) – Torxed Feb 04 '19 at 19:37
  • Would it be possible for you to point me in the direction of some more specific examples of implementing attack animations via blitting sprites? I've managed to get the attack animation to work as long as there are still images left in the list but once the list runs out the game crashes. I've looked through the links provided in your first message and I just see random examples unrelated to my issue. If not, it's fine. I do appreciate your help up to this point. Thank you – NotmyName Feb 05 '19 at 13:46

3 Answers3

0

Whenever you increment your indexes, you must ensure they don't overflow the number of images available. You do this for walkCount, but not for attackCount.

The modulo operator % is convenient as suggested in the comments.

So in you could change your redraw function:

def redrawGameWindow():
    global walkCount
    global attackCount
    screen.blit(bg, (0,0))

    if left:
        screen.blit(walkLeft[walkCount//3], (x,y))
        walkCount += 1
        walkCount %= len(walkLeft)
        attackCount += 1
        attackCount %= len(spinAttackList)

    elif right:
        screen.blit(walkRight[walkCount//3], (x,y))
        walkCount += 1
        walkCount %= len(walkRight)
        attackCount += 1
        attackCount %= len(spinAttackList)
    else:
        screen.blit(char, (x,y))

    if spin:
        screen.blit(spinAttackList[attackCount//3], (x,y))

    pygame.display.update()

I'm not sure why you're using the integer division operator //, I've left it alone, but I think you may have meant to use %, in which case the subsequent %= lines would be unnecessary.

If you want something more elegant, you could use a cycling iterator.

import random
  • 3,054
  • 1
  • 17
  • 22
0

Check this I have done this already

def drop_enemies(enemy_list):
delay = random.random()
if len(enemy_list) < 10 and delay < 0.1:
    x_pos = random.randint(0, WIDTH - enemy_size)
    y_pos = 0
    enemy_list.append([x_pos, y_pos])


def draw_enemies(enemy_list):
for enemy_pos in enemy_list:
    pygame.draw.rect(screen, BLUE, (enemy_pos[0], enemy_pos[1], enemy_size, enemy_size))
Ram Mohan dubey
  • 150
  • 1
  • 9
0

Try this. It worked for me:

#x, y, w, h are for position and no is number of images

def ims(no, x, y, w, h):
    idt = True
    pino = 0

    while idt:
        ec()

        if pino != no:
            file = str("xyz") + str(pino) + ".png" #filepath, with image names as 0.png, 1.png so on
            pino += 1
            pic = pygame.image.load(file).convert_alpha()
            pygame.draw.rect(screen, bgc, (x, y, w, h)

        pygame.display.update()
        clock.tick(15)