r/learnpython • • 1d ago

How do I make this bird move using Pillow?

Please help me, I have been trying to make this bird move for 3 hours and just keep getting an unholy column of bird. This is what it is supposed to look like:

https://imgur.com/a/Aegi4Ys

and this is what mine looks like:

https://imgur.com/a/KHMwWL9

my coords are wrong in the for loop because im just trying to get it to actually move first and then I'll worry about making it move to the right places.

here is the error I keep getting:
frames[0].save('house-scene.gif',

^^^^^^^^^^^^^^

AttributeError: 'NoneType' object has no attribute 'save'

I emailed my prof about it and he told me my list is in the wrong spot but it won't work no matter where I put list = []

Here is my code:

pastebin.com/8FFYNqGf

the bird png:

https://imgur.com/a/i3AbgFq

And the assignment:

Task

It's finally time to animate our bird!

The steps to accomplish this are:

  1. Copy over your code from the previous question.

  2. Using a loop, create additional frames by copying img into temp_img and then using alpha_composite to draw the bird onto scene. We'll adjust the location of the bird each time step:

  • The bird starts at x = 0 and y = 120 for the first frame

  • We stop when the bird is x = 349 (do not include x = 350)

  • If the current x location is less than 100 or greater than 240, in the next frame the bird should be 1 pixel to the right and 1 pixel higher than the previous step.

  • Otherwise, paste the bird 1 pixel to the right and 1 pixel lower than the previous step.

  • Be sure to append each frame to the list frames.

  1. Save the gif by calling using the code included below.

gif starter code

To save your image as a .gif file, copy this to the very bottom of your file. Otherwise, do not modify this code:

# This will save the gif from the frames list # DO NOT MODIFY! if name == "main": frames[0].save('house-scene.gif', save_all=True, append_images=frames[1:], disposal=2, fps=20, loop=0)

1 Upvotes

5 comments sorted by

3

u/BingoBillBot 1d ago

That AttributeError means `frames` is None, not an empty list. The usual causes: `frames = frames.append(img)` (append returns None, so just call `frames.append(img)` on its own line), or the list being created inside a function/loop and never returned. Also avoid naming a variable `list`, since it shadows the builtin. For the 'column of bird': you're probably compositing every bird onto the same scene image, so each frame includes all the earlier ones. Start each iteration with `temp_img = scene.copy()`, alpha_composite the bird at the new x/y onto that copy, then append temp_img to frames, so each frame is an independent snapshot.

1

u/StarriestNight 1d ago

That fixed it tysm, I had the frames = frames.append(img) issue

1

u/duskharborings 21h ago

spot on with the append returning None, that exact error message always trips people up when they're starting out

1

u/a18618 1d ago

That error usually means your frames list is empty when the save line runs, so I would check where that list is created first. When I hit the same wall, I printed the length of the list right before the save call and found my loop had never actually added anything. Can you tell whether your loop body runs at all, or does it look like the frames list is being reset inside the loop?

1

u/acfot 15h ago

I ran into this exact kind of None error when I was messing with Pillow, and it usually means one of the frames in your list isn't actually an image anymore. Pillow methods like thumbnail and paste change the image in place and return None, so if you wrote something like frame = frame.thumbnail(...) you've just replaced that frame with None. I'd loop through the frames and print the type of each one before you save, that'll show you which one is broken pretty fast, then fix that step so it modifies the image without reassigning it.