Sign in to follow this  
Ironhorse

Need Help with Python, Pyglet animations!

Recommended Posts

***EDITED FOR A CLEARER DESCRIPTION OF WHAT IM LOOKING FOR*** hey so I've searched around a little bit and i cant find an answer exactly to my n00b question. just started learning how to code in python but i know this is possible. so here goes: i don't need an animation to PLAY. i just wish to use a picture (png or gif preferably) to have X amount of frames in it (some cases hundreds of frames) and to be able to display Y frame when Z key is pressed (the cause or event doesnt matter as it will change down the road) in python/pyglet how can i reference a GIF file frame (either frames from an already existing animation OR a grid/sprite sheet i already made) i'll have multiple images that will be running at once so this process needs to work for all. i know about batches, i know about image grids, i know about textureregions, bins and atlases. none of the documentation i've found has any specific implementation on how to an actual example is really what i need. i found something close on these forums but its not complete. thanks for any help/input guys! still learning. [Edited by - jpetrie on March 15, 2010 10:20:02 PM]

Share this post


Link to post
Share on other sites
Despite the information you've given it's not quite specific enough for me to be sure what you want. Do you want animations/frames to play sequentially when a key is pressed, or do you want different keys to display different single frames (no actual animation), or something else entirely? It seems like you want the 2nd but I'm having a hard time picturing it. It would be best, if you can, to also describe the finished game here. Pretend it works and I'm playing it...what am I doing? What am I seeing on screen?

Quote:

really? 50 views and not one reply?

no one knows how to access one frame at a time with pyglet? this is a game dev forum lol...


That's very normal, and not considered a lot of views for this forum. People frequently view posts that they probably can't answer. There aren't a lot of pyglet users here. I'll do my best. Maybe swiftcoder will swing by - he's probably the most experienced pyglet user here.

Share this post


Link to post
Share on other sites
Quote:
Original post by Hollower
Maybe swiftcoder will swing by - he's probably the most experienced pyglet user here.
Thanks ;)

Thus far, full support for controlling animation hasn't made it into pyglet. However, I had the same need a while ago, and ended up implementing the necessary features, which code you can find here, on my blog.

That class should be a drop-in replacement for pyglet.sprite.Sprite, of which it is a subclass.

Share this post


Link to post
Share on other sites
hey guys, thanks for the reply.

specifically , i don't need an animation to PLAY. i just wish to use a picture (png or gif preferably) to have X amount of frames in it (some cases hundreds of frames) and to be able to display Y frame when Z key is pressed (the cause or event doesnt matter as it will change down the road)

currently the best method that is completely undocumented (even in the source code) is "AnimatedFrame" in pyglet. only mentioned ONCE throughout the entirety of documentation and never explained or example.

if its not doable i was willing to go the way of a sprite sheet. but the issue remains .. i need an example of how to display a SINGLE frame efficiently (using bins or batches is fine by me) because there will be about a dozen GIFS that will be doing this.

i will check out swiftcoder's blog tonight (going out for my b day :) )
and will check back tomorrow.
thanks again guys

Share this post


Link to post
Share on other sites
pygame doesn't do what i need (read above, last reply)

if you can show me an exact code example of how it can id GLADLY be a pygame convert. but ive researched that enough in the past to know its lacking for my specific needs

Share this post


Link to post
Share on other sites
hey swiftcoder, i shot you and email asking for an example of your subclass being used to display a single frame. im sure its pretty straight forward but i just cant see it from staring at the code.
thanks for your help!

Share this post


Link to post
Share on other sites

Honestly "a dozen" is not a lot and plain old blitting will be plenty fast. And if you mean to display only one of them at a time then you really don't need to batch since it is for combining simultaneously displayed images into one draw call.

animation = pyglet.image.load_animation('animation.gif')
frames = [frame.image for frame in animation.frames]


You're right the docs don't list AnimationFrame's instance variables, but they are the same as the constructor arguments. Obviously that class is only intended for internal use by Animation.

I know you said you didn't want to keep lists but this can be encapsulated in a class that takes care of everything. I decided to take a stab at this, but I don't really understand your application so my example looks kind of strange. I don't know how you plan to bind keys to potentially thousands of individual frames, so I just bound a few in the example (A,B,C).


import pyglet
from pyglet.window import key

class GifWindow(pyglet.window.Window):
def __init__(self):
super(GifWindow, self).__init__()
self.frames = {}
self.show = None

def load_gifs(self):
self.set_mouse_cursor( self.get_system_mouse_cursor(self.CURSOR_WAIT) )

import glob
for filename in glob.glob("*.gif"):
anim = pyglet.image.load_animation(filename)
self.frames[filename] = [frame.image for frame in anim.frames]

self.set_mouse_cursor( self.get_system_mouse_cursor(self.CURSOR_DEFAULT) )

def on_draw(self):
self.clear()
if self.show:
self.show.blit(0,0)

def on_key_press(self, symbol, modifiers):
frames = self.frames

if symbol == key.A:
self.show = frames["cat.gif"][0]

elif symbol == key.B:
self.show = frames["dog.gif"][25]

elif symbol == key.C:
self.show = frames["dog.gif"][42]


window = GifWindow()
window.load_gifs()
pyglet.app.run()


Share this post


Link to post
Share on other sites
wow. youre awesome hollower. lol thanks.

those two lines really are the meat and potatoes i was looking for.PLUS the frames['image.gif'][23] was the KEY. dont know how i missed that
i haven't tested ur code yet, just barely looked at it, but one thing:

not understanding why you are including the mouse in any of the code?

im going to go test this now, i just wanted to post while youre still on and say thanks!

i cant be tooo specific with what im making as far as the big picture goes because i am under a NDA.. but i can say its a static image displayed in the background while the foreground will have elements with important information such as battery life and speed mph etc that will have to be dynamic and ill have to change the "bars" on the battery life when needed so instead of having 26 gifs for one element i just have one gif that has 26 frames that i can access. there will be next to ZERO actual input from the user, the screen is purely informational. i am just using keyboard keys to "test" or act as the cause for the change in frames as the final system that will be in place will be over a BUS
make more sense?
thanks a ton man. mind if i email you?

***UPDATE***
hell yea it worked! man i dont believe it was that simple. i've been driving myself mad for a week now with this. granted im still very much in the early learning stages of this language.. but still. lol. thanks again man.

still confused what youre doing with the mouse cursor.. but hey ill keep it in there if it works ahah.
so you think if i use another dozen or so gifs i can still get away with blitting?

[Edited by - Ironhorse on March 9, 2010 2:05:53 PM]

Share this post


Link to post
Share on other sites
Yeah, sorry I didn't take the time to comment the code.

The load_gifs function is where the magic happens, everything else should probably look quite different for your application. Because load_gifs could potentially take some time I put in a line to change the mouse cursor to an hourglass while it is loading and then back to normal at the end. Completely unnecessary.

I used the glob module to simplify loading all gifs in the script's folder.

self.frames is a dictionary. For each file in the folder I store the filename as the key and the list of frames as the value.

The on_draw stuff will require some changes to suit your application since it can only handle one at a time, always drawn in the corner in my example. self.show is just the "current image" do be displayed.

Share this post


Link to post
Share on other sites
i actually completely understand... thanks for the explanation with the mouse cursor though. now self.cursor.wait makes sense. :)

so creating the dictionary is what made it work.

technically to mod on_draw to my app i could just include "different" self.show 's... such as self.show1 etc, correct? or however many elements i am going to need? and also i take it the X and Y coords are @ self.show.blit (0,0) right?
what about z depth as in layering? i know pyglet is limited to -1 through 1. is that floating point or integer?

youre a lifesaver btw.
could you send me an email so i can ask you one or two more questions? since you are so full of answers!

[Edited by - Ironhorse on March 9, 2010 5:03:06 PM]

Share this post


Link to post
Share on other sites
Great, now my images' arent blending properly. transparency is not working despite me using

glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

at the beginning. any ideas?
the transparent portions show up WHITE.

***UPDATE***
solved it myself, discovered that these opengl commands need to be placed in the on_draw event to work properly. still some white around the edges, which is odd.. but.. ill see if i can fix that

[Edited by - Ironhorse on March 10, 2010 12:55:27 PM]

Share this post


Link to post
Share on other sites
so heres the update: got individual frames to display properly
however, alpha blending is still only halfway working, there are white borders around my images. ive googled this to all hell and all ive found is issues with sub pixel manipulation or scaling. that doesnt apply here.

heres a picture of what im talking about:

http://img442.imageshack.us/img442/7420/alphablendinggonewrong.jpg

im also running into problems with layering.. setting Z depths in the X and Y coords works to some extent but im going to run out of options between -1 through +1, and yes i enabled

glEnable(GL_DEPTH_TEST)

but it doesnt appear to work as intended of course.

Share this post


Link to post
Share on other sites
Quote:
Original post by Ironhorse
however, alpha blending is still only halfway working, there are white borders around my images. ive googled this to all hell and all ive found is issues with sub pixel manipulation or scaling. that doesnt apply here.
Looks like you need to use pre-multiplied alpha. There is a detailed post on the issue over on the pyglet mailing list.

Share this post


Link to post
Share on other sites
It looks more to me like the source graphic is broken, with the colour fading to white instead of just fading opacity. But it's hard to say with such a small example.

As for the layering issue, we're going to need a lot more information as to what you're currently doing and what you mean by "doesn't appear to work as intended" (what do you intend? what do you see instead?) to lend sufficient help.

Share this post


Link to post
Share on other sites
Quote:
Original post by swiftcoder
Looks like you need to use pre-multiplied alpha. There is a detailed post on the issue over on the pyglet mailing list.


but i am not doing any subpixel positioning? the only thing that could be going on is using pyglet.image.load_animation and drawing it using blit. since ive only seen it use .draw before? (but since im displaying only a single frame at a time hollower's got me using blit)

@kylotan:

yea thats what i was thinking too, so i played around with photoshop and its "sRGB" settings as well as disabling and enabling transparency dithering w/ or w/o it etc etc... unless its just photoshop thats saving it incorrectly (using "Save for web & devices" menu option)
because its NOT carrying over the background color. as you can see in that image (maybe not ill provide a larger one if needed) the original background is BLACK, not white.. in other words if the one pixel border was black i'd assume the tolerance was off. but its not?

and some images, like a large 1024,768 image with alot of room for transparency just show up plain white.. meaning like areas of 640 pixels of pure white, not just a border. ODD.

as for layering, i believe i have a workaround for now..(just using less images)... however my main gripe is pyglet doc states :
"The default pyglet projection has a depth range of (-1, 1) -- images drawn with a z value outside this range will not be visible, regardless of whether depth testing is enabled or not."

and i've ran into this issue. yes, there's mathematically thousands of possibilities between those two numbers but i've found it limited to a tenth of a decimal, meaning -0.8 works but -0.08 does not.
when i enable depth testing i just get an unexplained traceback error.
my goal: to layer many images as you would in a photoshop image to complete a whole scene in conjunction with alpha blending.

hope that's enough of an explanation.
and hey thanks guys for your help once again, really appreciate it.
this seems to be the only source for applied info since the google groups move too slow. :)
-Iron

***UPDATE***
discovered reasons for only LARGE white pixels occuring instead of transparency was due to "drop shadow" effects used in photoshop.. i guess alpha channels and drop shadows dont play well.
still 1px white border occuring though.

[Edited by - Ironhorse on March 11, 2010 1:36:08 PM]

Share this post


Link to post
Share on other sites
NEW UPDATE
got rid of the white borders by simply selecting the appropriate colored "matte" when saving my gif. in this case i just selected "black" matte.. its not a fix its a workaround but she looks beautiful now.

its still lightning in a bottle for which images will use alpha blending and which wont.. cant narrow it down after playing with transparency dithering and sRGB options and sizes for TWO hours...hmm.

**UPDATE**
ok... so.. with the code provided by hollower as seen above, transparency / alpha channels will NOT work unless:
1. you have more than one frame of animation made
2. and there is a distinct difference between the two such as changing an effect or moving something.

these two parameters must be met or any gif with transparency will not work.

[Edited by - Ironhorse on March 11, 2010 5:05:42 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Ironhorse
as for layering, i believe i have a workaround for now..(just using less images)... however my main gripe is pyglet doc states :
"The default pyglet projection has a depth range of (-1, 1) -- images drawn with a z value outside this range will not be visible, regardless of whether depth testing is enabled or not."

and i've ran into this issue. yes, there's mathematically thousands of possibilities between those two numbers but i've found it limited to a tenth of a decimal, meaning -0.8 works but -0.08 does not.

So you're doing something wrong. It's hard to tell you more than that since you're not posting your code and you've still not explained exactly what you mean by it not working.

Quote:
when i enable depth testing i just get an unexplained traceback error.

And it will stay unexplained if you don't post any information about it.

Quote:
my goal: to layer many images as you would in a photoshop image to complete a whole scene in conjunction with alpha blending.

It's possible.

Share this post


Link to post
Share on other sites
Kylotan....
as i said above, "with the code provided by hollower as seen above"
im using that exact code he posted, only thing i've modified is added a z depth to the x and y coords when blitting, as well as:
"glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)"
and depth test.

ive fixed the layering issue, turned out the code was sensitive to what ORDER you placed your blits in, hard to believe i know. (meaning a blit with -0.9 needs to come before -0.1)

and i also fixed images that refused to be alpha blending (Read above)
and i also fixed images that had a 1 pixel white border (Read above)
and i asked if i had explained enough.. and i guess not. so which part needs more explaining? I'm not clear on what you're not understanding? when i said the z depths weren't working.. i meant they weren't working properly ..as in not layering in correct order.

i can't explain the big picture of my project as i am under an NDA (Read above)
and that information isn't needed anyways, the code is provided above.

if you don't understand its okay, you don't need to post, I'm receiving a lot of useful help from other people in these forums. and I'm updating frequently for documentation so that if anyone else ever has this problem a google search solves it for them.

if you still want to help:
the only truly unresolved issue now remains opengl related, i'm just using a workaround using Matte to make a black border instead of a white one... but the real issue is WHY is there a 1 pixel border at all? im not using subpixel positioning. isn't that what the ONE_MINUS_SRC_ALPHA line is for?

Share this post


Link to post
Share on other sites
Quote:
Original post by Ironhorse
Kylotan....
as i said above, "with the code provided by hollower as seen above"
im using that exact code he posted, only thing i've modified is added a z depth to the x and y coords when blitting, as well as:
"glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)"
and depth test.

But that is all the important stuff you're talking about and is where the bug is likely to lie.

Quote:
ive fixed the layering issue, turned out the code was sensitive to what ORDER you placed your blits in, hard to believe i know. (meaning a blit with -0.9 needs to come before -0.1)

Then you're doing it wrong. Unless you actually mean something more specific.

Quote:
when i said the z depths weren't working.. i meant they weren't working properly ..as in not layering in correct order.

If it's just the edges that don't appear to layer correctly but the opaque stuff works fine, that will be a problem with the form of alpha blending you use, and Swiftcoder has answered that for you.

If the whole thing is not layering in the correct order, then you've messed up your depth testing and/or rendering, but we can't help with that without knowing what code you've used for it.

As it happens I have a reasonable amount of experience in this area since I was the person who started the thread that Swiftcoder has linked to. I also posted up code for a sprite that allows z-ordering and alpha in the same sprite (subject to the blending mode restrictions that have already been mentioned).

PS. Speaking as a moderator, please don't mark threads as 'solved'. We're a discussion forum, not a technical support forum, and further talk after the original poster has found their solution is actively encouraged.

Share this post


Link to post
Share on other sites
Quote:

PS. Speaking as a moderator, please don't mark threads as 'solved'. We're a discussion forum, not a technical support forum, and further talk after the original poster has found their solution is actively encouraged.

QFE. Do not do this in the Beginners forum. I have edited your post to remove the 'solved' tag.

Share this post


Link to post
Share on other sites
"further talk after the original poster has found their solution is actively encouraged."

sounds good to me, just used to doing that in user groups in the past. :)

heres the code, changed some names around for NDA purposes, but you can see the format.
i have the depth testing line commented out due to an error it was giving me before. (can post it if needed)

yes the layering issue only occurs if i dont place it in correct order. and i may be doing something wrong, sure.. but try this code for yourself and see what the results are, it did the same thing to me on two different computers, heh.

but yea the alpha blending isnt all that great even when using opengl code.. im experimenting with different code ATM though.. squared or boxed images come out fine, its curves that become severely jaggy, as in need of anti aliasing. could still just be photoshop, but i doubt it.




import pyglet
from pyglet import resource
from pyglet.window import key
from pyglet.gl import *


class GifWindow(pyglet.window.Window):
def __init__(self):
super(GifWindow, self).__init__()

self.img = pyglet.image.load('Background.gif')
self.frames = {}
self.showgauge = None
self.showelements = None
self.showdashmain = None
self.showneedle = None


def draw(self):
self.img.blit(0,0,-1)

def load_gifs(self):

import glob
for filename in glob.glob("*.gif"):
anim = pyglet.image.load_animation(filename)
self.frames[filename] = [frame.image for frame in anim.frames]



def on_draw(self):
self.clear()
self.img.blit(0,0)


if self.showgauge:
self.showgauge.blit(141,216,-0.9)
if self.showelements:
self.showelements.blit(0,0,-0.8)
if self.showdashmain:
self.showdashmain.blit(0,0,-0.5)
if self.showneedle:
self.showneedle.blit(0,0,0.1)
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA)
#glEnable(GL_DEPTH_TEST)

def on_key_press(self, symbol, modifiers):
frames = self.frames

if symbol == key.A:
self.showgauge = frames["test1.gif"][8]

elif symbol == key.B:
self.showelements = frames["test2.gif"][0]

elif symbol == key.C:
self.showdashmain = frames["test3.gif"][0]

elif symbol == key.D:
self.showneedle = frames["test4.gif"][0]

elif symbol == key.E:
self.showgauge = frames["test5.gif"][6]

elif symbol == key.F:
self.showgauge = frames["test6.gif"][10]



window = GifWindow()
window.load_gifs()
window.set_size(1024,768)
pyglet.app.run()

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this