Animated Sprite from Few Images

Animated sprite from few images

You could try modifying your sprite so that it swaps out its image for a different one inside update. That way, when the sprite is rendered, it'll look animated.

Edit:

Here's a quick example I drew up:

import pygame
import sys

def load_image(name):
image = pygame.image.load(name)
return image

class TestSprite(pygame.sprite.Sprite):
def __init__(self):
super(TestSprite, self).__init__()
self.images = []
self.images.append(load_image('image1.png'))
self.images.append(load_image('image2.png'))
# assuming both images are 64x64 pixels

self.index = 0
self.image = self.images[self.index]
self.rect = pygame.Rect(5, 5, 64, 64)

def update(self):
'''This method iterates through the elements inside self.images and
displays the next one each tick. For a slower animation, you may want to
consider using a timer of some sort so it updates slower.'''
self.index += 1
if self.index >= len(self.images):
self.index = 0
self.image = self.images[self.index]

def main():
pygame.init()
screen = pygame.display.set_mode((250, 250))

my_sprite = TestSprite()
my_group = pygame.sprite.Group(my_sprite)

while True:
event = pygame.event.poll()
if event.type == pygame.QUIT:
pygame.quit()
sys.exit(0)

# Calling the 'my_group.update' function calls the 'update' function of all
# its member sprites. Calling the 'my_group.draw' function uses the 'image'
# and 'rect' attributes of its member sprites to draw the sprite.
my_group.update()
my_group.draw(screen)
pygame.display.flip()

if __name__ == '__main__':
main()

It assumes that you have two images called image1.png and image2.png inside the same folder the code is in.

how to animate the sprite?

Create a sprite class with a list of images. Add an attribute that counts the frames. Get image from image list in the update method based on number of frames:

class MySprite(pygame.sprite.Sprite):

def __init__(self, x, y, image_list):
super().__init__()
self.frame = 0
self.image_list = image_list
self.image = self.image_list[0]
self.rect = self.image.get_rect()
self.rect.center = (x, y)

def update(self, event_list):

animation_interval = 20
self.frame += 1
if self.frame // animation_interval >= len(self.image_list):
self.frame = 0
self.image = self.image_list[self.frame // animation_interval]

for event in event_list:
if event.type == pygame.MOUSEBUTTONDOWN:
mouse = event.pos
print(mouse[:])

However, instead of constantly creating and killing the sprite every frame, you need to create the sprite once before the application loop. Change the position of the sprite and update the sprite in the application loop:

file_list = ['crossHair.png', 'crossHair_2.png', 'crossHair_3.png']
image_list = []
for name in file_list:
image = pygame.image.load(name)
image.set_colorkey(WHITE)
image_list.append(image)

# create sprite
sprite1 = MySprite(0, 0, image_list)
placeSP_group = pygame.sprite.OrderedUpdates()
placeSP_group.add([sprite1])

clock = pygame.time.Clock()
running = True
while running:

# handle events
event_list = pygame.event.get()
for event in event_list:
if event.type == pygame.QUIT:
running = False

# update sprite
x, y = pygame.mouse.get_pos()
placeSP_group.sprites()[0].rect.center = (x, y)
placeSP_group.update(event_list)

# draw scene
window_game.fill('white')
window_game.blit(backGround,(0,0)).size
placeSP_group.draw(window_game)
pygame.display.flip()

clock.tick(FPS)

pygame.quit()
exit()

See also:

  • how to create an illusion of animations in pygame
  • Animated sprite from few images
  • How do I create animated sprites using Sprite Sheets in Pygame?

Infinitely animating sprite in pygame

Make a list of the images for animation:

image_list = [pos1, pos2, pos3, pos4, pos5]

Add a variable that will store an index of the image list:

current_image = 0

Increment the index in the application loop and reset the index if it is equal to the length of the list:

run = True
while run:
# [...]

current_image += 1
if current_image == len(image_list):
current_image = 0

# [...]

Get the current image by subscription:

screen.blit(image_list[current_image], x, y)

Unity Sprite two images animation at runtime

You can do this with the Animator in Unity but doing with code gives you more control. Coroutines is one of the best ways to do this.

1.Create a script called SpriteAnimator. Copy everything from below to it.

using UnityEngine;
using System.Collections;

public class SpriteAnimator : MonoBehaviour
{
bool continueAnimation = false;

SpriteRenderer displaySprite;
Sprite sprite1;
Sprite sprite2;

public void setupSprites(SpriteRenderer displaySprite, string animSprite1, string animSprite2)
{
//Set where the animated sprite will be updated
this.displaySprite = displaySprite;

//Load Sprite 1
Texture2D tex = Resources.Load<Texture2D>(animSprite1) as Texture2D;
sprite1 = Sprite.Create(tex, new Rect(0, 0, 250, 150), new Vector2(0.5f, 0.5f), 40);

//Load Sprite 2
Texture2D tex2 = Resources.Load<Texture2D>(animSprite2) as Texture2D;
sprite2 = Sprite.Create(tex2, new Rect(0, 0, 250, 150), new Vector2(0.5f, 0.5f), 40);
}

private IEnumerator startAnimationCRT(float time)
{
if (continueAnimation)
{
yield break;
}
continueAnimation = true;

WaitForSeconds waitTime = new WaitForSeconds(time);
while (continueAnimation)
{
//Change to Sprite1
displaySprite.sprite = sprite1;

//Wait for `time` amount
yield return waitTime;

//Change Sprite
displaySprite.sprite = sprite2;

//Wait for `time` amount
yield return waitTime;
}

continueAnimation = false;
}

public void startAnimation(float time)
{
StartCoroutine(startAnimationCRT(time));
}

public void stopAnimation()
{
continueAnimation = false;
}

public void removeAnimation()
{
Destroy(this.gameObject);
}
}

2.Create another script called SpriteAnimation. Copy everything from below to it. Also remove ": MonoBehaviour" after the class name. You must do this! It can't derive from MonoBehaviour so remove it.

using UnityEngine;
using System.Collections;

public class SpriteAnimation
{
SpriteAnimator spriteAnimator;
GameObject gameObj;

public void setupSprites(string animationName, SpriteRenderer displaySprite, string animSprite1, string animSprite2)
{
gameObj = new GameObject(animationName);
gameObj.AddComponent<SpriteAnimator>();
spriteAnimator = gameObj.GetComponent<SpriteAnimator>();
spriteAnimator.setupSprites(displaySprite, animSprite1, animSprite2);
}

public void startAnimation(float time = 0.5f)
{
spriteAnimator.startAnimation(time);
}

public void stopAnimation()
{
spriteAnimator.stopAnimation();
}

public void Destroy()
{
spriteAnimator.removeAnimation();
}
}

Done. How to use:

public SpriteRenderer SR;
SpriteAnimation dogAnimation;

void Start()
{
dogAnimation = new SpriteAnimation();
dogAnimation.setupSprites("DogAnimation", SR, "dog", "dog2");
dogAnimation.startAnimation(0.2f);
}

Call dogAnimation.stopAnimation(); to stop the animation.
You can create many SpriteAnimations as you want. The line of code dogAnimation.setupSprites("DogAnimation", SR, "dog", "dog2"); will setup animation. It will create a new GameObject named DogAnimation. It will then load two images called dog and dog2 from the Resources folder so make sure those exist. SR is the texture on the screen that will be changed with dog2 and dog images. dogAnimation.startAnimation(0.2f); will start the animation and you can pass in the animation transition time inside.

How do I get my images to work as an animation in pygame?

  • Load the images and put them into lists.
  • Add an index, a timer and an images (the current image list/animation) attribute to the class.
  • When the user presses one of the movement keys, swap the image list.
  • To animate the images, first pass the dt (delta time) to the player's update method and subsequently to the other methods that need it. Increment the timer attribute and, after the desired time interval, increment the index and use it to swap the image.

That's basically all you need to do, but maybe you have to adjust a few things.


import pygame as pg

pg.init()
screen = pg.display.set_mode((640, 480))

# Load images once when the program starts. Put them into lists, so that
# you can easily swap them out when the player changes the direction.
STICKMAN_IDLE = [pg.image.load(
'Images/Animations/PlayerRun/Stickman_stand_still.png').convert_alpha()]
# You could use a list comprehension here (look it up).
STICKMAN_RUN = [
pg.image.load('Images/Animations/PlayerRun/Stickman_run_1.png').convert_alpha(),
pg.image.load('Images/Animations/PlayerRun/Stickman_run_2.png').convert_alpha(),
pg.image.load('Images/Animations/PlayerRun/Stickman_run_3.png').convert_alpha(),
pg.image.load('Images/Animations/PlayerRun/Stickman_run_4.png').convert_alpha(),
]

class Player:

def __init__(self, x, y):
self.pos_x = x
self.pos_y = y

self.images = STICKMAN_IDLE
self.image = self.images[0]
self.rect = self.image.get_rect(center=(x, y))

self.anim_index = 0
self.anim_timer = 0

def move_player(self, dt):
"""Move the player."""
self.pressed = pg.key.get_pressed()

if self.pressed[pg.K_a]:
self.pos_x -= 5 # Move left.
self.images = STICKMAN_RUN_RIGHT # Change the animation.
if self.pressed[pg.K_d]:
self.pos_x += 5 # Move right.
self.images = STICKMAN_RUN_RIGHT # Change the animation.
if not self.pressed[pg.K_d] and not self.pressed[pg.K_a]:
self.images = STICKMAN_IDLE # Change the animation.

# Update the rect because it's used to blit the image.
self.rect.center = self.pos_x, self.pos_y

def animate(self, dt):
# Add the delta time to the anim_timer and increment the
# index after 70 ms.
self.anim_timer += dt
if self.anim_timer > .07: # After 70 ms.
self.anim_timer = 0 # Reset the timer.
self.anim_index += 1 # Increment the index.
self.anim_index %= len(self.images) # Modulo to cycle the index.
self.image = self.images[self.anim_index] # And switch the image.

def update(self, dt):
self.move_player(dt)
self.animate(dt)

def draw(self, screen):
screen.blit(self.image, self.rect)

def main():
clock = pg.time.Clock()
player = Player(100, 300)
done = False

while not done:
# dt (delta time) = time in ms since previous tick.
dt = clock.tick(30) / 1000

for event in pg.event.get():
if event.type == pg.QUIT:
done = True

player.update(dt) # Pass the delta time to the player.

screen.fill((30, 30, 30))
player.draw(screen)
pg.display.flip()

if __name__ == '__main__':
main()
pg.quit()


Related Topics



Leave a reply



Submit