Getting Started With gewel

The best way to get started with gewel is to jump right in.

Installation

The first thing we need to do is install gewel. We are going to make two assumptions here:

  1. You are familiar with Python and installing packages using pip.

  2. You have a virtual environment running Python 3.9 or higher.

If you are not sure about these two things, we recommend you read about pip and virtualenv or a virtual environment management tool like pipenv, which is what we use while developing gewel.

Once you have a virtual environment running Python 3.9, you can install gewel by running

$ pip install gewel

at the command line.

Hello, World

Now that we have gewel installed, we can get started on our first script.

We are going to build our first animation around a character named Bep.

This is Bep.

This is Bep.

Bep is not very interesting just standing there doing nothing, so we are going to animate them. Our goal is to produce something like the following:

Animated output of helloworld.py.

The animation we are going to produce.

The Scripting Phase

We’ll start out in what is called the scripting phase. In this phase we are essentially writing the script for the animation.

We begin by creating a Drawable from the image we have of Bep. Anything we can draw or animate with gewel is based on the Drawable class. Since we happen to have a PNG file of Bep (the one shown above when we first introduced them), we’ll use the PngDrawable subclass, as follows:

from gewel.draw import PngDrawable

bep = PngDrawable('bep.png', x=32, y=240)

What did we just do? We loaded our PNG file into a drawable object called bep and we specified and initial position for the drawable at x=32 and y=240. That’s the location on the screen where Bep will start out.

If you want to try this yourself, you’ll need the bep.png file. Click this link to download bep.png and save it in the same directory as the python script where you saved the code snippet above.

Now let’s move Bep across the screen, like we saw in the animation. We do that with one line of code:

bep.move_to(608, 240, duration=2.0)

This tells Bep to move to a new location on the screen, 576 pixels to the right of where they started. The duration=2.0 argument specifies that this movement should take two seconds.

That was easy. Now what about the back flip that Bep does to get back to where they started? This will take two lines of code:

bep.quadratic_move_to(320, 0, 32, 240, duration=2.0, update_time=False)
bep.rotate_to_degrees(360, duration=2.0)

The first line moves Bep from where they are to their original location at 32, 240. But what do the arguments 320, 0 that come before the destination mean? Those are the x and y coordinates of a control point that controls the path Bep takes along the way. Notice that the control point is at the top center of the screen (by convention y coordinates on the screen increase as they go down). So Bep will go towards the control point, but then curve away towards their final destination.

The duration=2.0 argument is like the one we used before. It says the motion will take two seconds.

So now we just have the update_time=False argument left to deal with. We did not provide that argument when we did our original move_to, so it used the default value of update_time=True. True means that Bep should update their internal clock to the point at which the move was complete, so that whatever move comes next will be done after that. But this time, we don’t want to wait until Bep arrives before we do the back flip. We want them to do it while moving. That’s why we used update_time=False on the move. Now we can take another action, and it will begin at the same time as the quadratic_move_to started. For more on the use of update_time see Next-Action Time During Scripting.

The next move is the rotate_to_degrees line above. This is the back flip! We told Bep to rotate 360 degrees over a duration of two seconds. These two seconds start at the same time the quadratic move started. That move also took two seconds, so the move and the rotation end at the exact same time and Bep sticks the landing!

So that’s it. We’ve written all the code needed to tell Bep where to start and how to move to create the animation we want. That brings us to the end of the scripting phase.

Next, we just need to add a few more lines of code so we can actually play the animation we just created. This is called the rendering phase.

We are going to construct a scene, which is just another kind of drawable that contains other drawables, and put Bep in it along with a background.

from gewel.draw import Background
background = Background()
scene = Scene([background, bep])

The Rendering Phase

Finally, we construct a player to play the scene in a pop-up window so we can view it. We have completed the script for the scene, and have entered the rendering phase.

from gewel.player import Player

player = Player(scene)
player.mainloop()

When the window pops up you will see Bep on the left side of the window, just where we placed them. By default the player starts in autoplay mode and is set to loop, so you should see Bep start doing their thing.

The final script that does all of this, which you should be able to copy, paste, and run in your virtual environment, is

from gewel.draw import PngDrawable, Background, Scene
from gewel.player import Player

# Scripting phase...
bep = PngDrawable('bep.png', x=32, y=240)

bep.move_to(608, 240, duration=2.0)
bep.quadratic_move_to(320, 0, 32, 240, duration=2.0, update_time=False)
bep.rotate_to_degrees(360, duration=2.0)

background = Background()
scene = Scene([background, bep])

# Rendering phase...
player = Player(scene)
player.mainloop()

One final step you might want to try, in case you want to preserve your first animation for posterity, is to write it out to an mp4 file. All you have to do is replace the last two lines of the script above (the ones that instantiate player and start it up) with

from gewel.record import Mp4Recorder

recorder = Mp4Recorder('helloworld.mp4')
recorder.record(scene)

Now when you run the script, instead of popping up a window with the animation, it will write it to a file that you can share with your friends.

Scaffolding

If you took the opportunity to play around with this first animation as the sidebar suggested, it’s possible you didn’t always get the effect you wanted. And even if you did, when things get more complicated and there are multiple objects moving around it isn’t always easy to debug what went wrong. Luckily, gewel has some tools to help.

Since animation is a visual medium, it helps to have visual tools for debugging. These can be much more effective than digging through log files. The most important visual debugging tool gewel offers is called scaffolding. Scaffolding shows you the control points and paths that are controlling an object’s movement as it moves. Like the motion itself, it is set up during the scripting phase.

Let’s turn it on and see how it works. An animation will be worth a thousand words.

To turn on scaffolding, we’ll modify our code so it looks as follows:

from gewel.draw import PngDrawable, Background, Scene
from gewel.player import Player

# Scripting phase...
bep = PngDrawable('bep.png', x=32, y=240)

scaffold_1 = bep.move_to(608, 240, duration=2.0, scaffold=True)
scaffold_2 = bep.quadratic_move_to(320, 0, 32, 240, duration=2.0,
                                   update_time=False, scaffold=True)
bep.rotate_to_degrees(360, duration=2.0)

background = Background()
scene = Scene([background, bep, scaffold_1, scaffold_2])

# Rendering phase...
player = Player(scene)
player.mainloop()

The major change is that we made are that we added the scaffold=True argument to our calls to move_to and quadratic_move_to on lines in the scripting phase of the listing above. When we add this argument, those functions return scaffolding objects to us. We assigned those objects to variables name scaffold_1 and scaffold_2. Scaffolding objects, it turns out, are also Drawable objects, so we add them to our scene right before we enter the rendering phase.

Now when we run again, the result looks like this:

Animated output of helloworld.py with scaffolding.

Notice that while Bep is moving across the screen there are othe markers and lines on the screen. There is a pale blue x at the start an end of each move, and another one at the control point of the quadratic move. The path of each move is shown with a pale gray line, and for the quadrative move there are lines from the start point to the control point and from the control point to the end point. All of this lets us quickly and visually diagnose if something is wrong. For example, if we a control point is in the wrong place and that is the reason we’re seeing some movement we don’t expect, then we will be able to see that immediately.

So that about wraps things up for this guide to getting started with gewel. There is, of course, a lot more still to learn on a variety of topics.

For additional code samples illustrating many of the fundamental concepts of gewel, see Sample Code.

If you want to learn about all the other sub-packages of the gewel package, the Gewel page has links to all of them.