lordmauve / pgzero

A zero-boilerplate games programming framework for Python 3, based on Pygame.
https://pygame-zero.readthedocs.io/
GNU Lesser General Public License v3.0
537 stars 188 forks source link

Sprite sheet support with animated frames #43

Open lordmauve opened 8 years ago

lordmauve commented 8 years ago

Originally reported by: Sam Washburn (Bitbucket: p1xl, GitHub: p1xl)


Hi! My 8 year old son is using pgz to learn to program. It's kind of frustrating doing image animations; a lot of typing and data structures for him to wrap his little head around.

Any hope in having sprite sheet support?

He wants to make an actor "run", but him and I both get bogged down going into details that I think are above his head at this point.


lordmauve commented 8 years ago

Original comment by Daniel Pope (Bitbucket: lordmauve, GitHub: lordmauve):


I understand the need for this, yes. Unfortunately I don't know of obvious data formats that make it really easy to connect the sprite sheets to a working animation in game.

We could perhaps solve this with some simple conventions or a bundled animation tool.

AaronLi commented 5 years ago

If there's a format for the spritesheets I can try working on it

lordmauve commented 5 years ago

There is no standard format for sprite sheets, no.

Pyglet supports animations by subdividing an image into rows/columns and then looping through the cells, but there are all kinds of ways to mess up with that. Whatever we do needs to be pretty easy to get right and hard to break afterwards.

lordmauve commented 5 years ago

eg. if I add a frame to the image, I want Pygame Zero to catch that the number of frames is wrong, rather than chopping the frames up wrongly.

dowski commented 4 years ago

What about a way to cycle through a given list of images for an Actor? You'd still have to name the individual images but the mechanics of swapping the images could be abstracted away, sort of like how the animate helper abstracts getting from value a to b.

I have an example coded up; for an animated explosion (one triggered over and over by time and another on mouse movement) usage looks like:

boom1 = Actor('explosion3', (50, 50))                                           
boom2 = Actor('explosion3', (150, 50))

frames =  ['explosion2', 'explosion1', 'explosion3']

explode_time = animcycle(boom1, frames, frequency=0.4)
explode_move = animcycle(boom2, frames, frequency=25)

def draw():
    screen.clear()
    boom1.draw()
    boom2.draw()

def update(dt):
    explode_time.update(dt)

def on_mouse_move(pos, rel):
    dx, dy = rel
    explode_move.update(dx)

If something like that seems good I could put together a PR.

lordmauve commented 4 years ago

I think something like that could be good although animcycle is a bad name for it. I think maybe it should be a method on actor, a property of animate (eg. animate.cycle()), or a new namespace of some sort.

dowski commented 4 years ago

Yeah, I agree that it's a bad name. 😆

flipcoder commented 4 years ago

Pyglet supports animations by subdividing an image into rows/columns and then looping through the cells, but there are all kinds of ways to mess up with that. Whatever we do needs to be pretty easy to get right and hard to break afterwards.

+1 for supporting sprite sheets. It's the export format of most sprite editors (Aseprite, Pyxel, etc.) where the animation is viewable as you make it, which is probably how a beginner would approach it. The way the sheets are interpreted by the game varies a lot, so as long as you can load them and switch to a given frame, or play a sequence of frames at a given speed (maybe through a list of indices), that would be a useful feature.

Loading from a sprite sheet is also useful for tilemaps and static object states, so its not necessarily specific to animation.

flipcoder commented 4 years ago

If you're looking for a way to combine sprite states and animation, you could do something like this: https://github.com/flipcoder/qorpse/blob/master/bin/data/actors/actor.json

Under "animation"/"frames", you can see how to associate different states (like directions or standing/walking), with a sequence of frames that will run for it. The "frames" section in the json and a sprite sheet is all the data a user would need to have for sprite states and animation. So the user would set states like player.state('walk') and player.state('left') and it would know which frames to use for the animation.

This is how I did it on a past project and it worked fairly well.