The purpose of this project is to make an animation using the Zelle Graphics module and to familiar us with top-down design.
I created an animated scene with moving objects simulating a soccer game. I used top-down design to build up codes efficiently. For each object, I first initialized it by appending basic shapes to an object list. And then I animated the objects by calling the draw, move, and undraw functions. Lastly, I created a for loop in the main function to animate objects in multiple frames.
In this project, I managed to animate several complex objects with different motions, make a coherent story with sequential events, and create different results under different conditions.
2. Required Images
For the first task, I created 5 complex objects–a soccer ball, a player, a goal, a goalkeeper, and confetti.
(Object 1) (Object 2)
In the beginning, I redefined draw, move, and undraw methods with a parameter indicating an object list for convenience.
The first object is a soccer ball. I drew a white circle with the Circle method and a black pentagon with the Polygon method and append them to a ball_shapes list.
The second object is a soccer player. I drew a circle as his head, a rectangle as his body, and four lines as his limbs.
(Object 3) (Object 4)
The third object is a goal. I drew a parallelogram with the Polygon method and four lines with the Line method.
The fourth object is a goalkeeper, the steps to create which were similar to that for the player.
The fifth object is confetti that will appear in the window after the player scores a goal. It is composed of 100 rectangles with random colors at random locations.
I used the random package to set each rectangle's outline and interior color, as shown below.
I also used a for loop to loop over the confetti function for 100 times and appended the randomly positioned rectangles to a confetti list. The x, y coordinates range from 0 to 1000 pixels.
3. Required GIF
For the second task, I animated four objects and create an animated scene.
(Scene 1) (Scene 2)
(Scene 3) (Scene 4)
The first object I animated is the ball. In the ball_animate( ) function, I created a for loop for each shape in the ball list to move 30 pixels to the right.
Secondly, I animated the player. In the player_animate( ) function, I created a for loop for each item in the player shape list to move 30 pixels to the right.
And then I animated the goalkeeper. In the goalkeeper_animate( ) function, I created a for loop for each item in the player shape list to move 5 pixels to the right and 2 pixels downward.
The last object I animated is the confetti. In the confetti_animate( ) function, I used a for loop to draw the confetti into the window, waits for 0.25 seconds, and undraw them for three times, which creates a flashing effect.
Next, I made a new file scene.py to draw all the objects from complex_shape.py and create an animated scene.
In the main function, I created a window and set the background green. And I assigned the object init functions to several variables so that I could draw the shapes into the window. And then I created a for loop to make 10 frames with an interval of 0.25 s, in which I put the animate functions of the player, goalkeeper, and the ball.
Then I assigned the call to shoot function to a variable randX. The shoot function returns randX which is a random integer between 0 and 500, referring to the x displacement of the ball from the location where the player kicks the ball to the ball's landing point.
With the randX value, I moved and re-drew the ball into the window. And then I made an if/else statement to test whether the ball falls within the range where the goalkeeper can get the ball.
The range of randX within which the goalkeeper can get the ball is (240, 260) since the goalkeeper's x-coordinate is 250 pixels from that of the player when he kicks the ball. And the distances from each goal post to the ready-to-kick player are 150 and 350.
If the ball falls within the goal and doesn't fall within the range where the goalkeeper can easily get the ball, then the player scores a goal and the confetti will flash three times on the window.
If the ball hits the goalkeeper or it doesn't go into the goal, then the goalkeeper moves to the ball's location and gets the ball.
The four gifs above show different situations. In the first and the second scenes, the ball goes out of the goal. In the third scene, the ball hits the goalkeeper and he gets the ball. Only in Scene 4, the player scores a goal and the confetti appears.
1) Make additional complex objects beyond the required 2, or animate more objects than the required one.
As stated above, I made 5 complex objects and animated 4 of them.
2) Make objects more complicated.
In the runningPlayer.py file, I created a new player object who changes his posture in every frame.
I made a function for each posture. The player's limbs are different in each frame, so I used a nums list to encapsulate the x, y displacement relative to (x, y)--the location of the center of the circle, which shortens the codes.
For example, in the function for the first posture, each sublist is a line, 7 sublists in total are in the sums list. And I made a for loop to draw and append 7 lines to make up the limbs.
The rest of the objects are almost the same as those in the main task.
The difference lies in the main function.
I positioned the player in each frame at 5 different x-coordinates and put them in a list.
And then I made a for loop to loop over each player in the player_list with the use of 'index,' so that the player could posture differently in the five frames.
2) Make an animation with multiple sequential events that make a coherent story.
As described above in the main task, I made use of randomness and if/else statement to create outcomes contingent on the relative position of the ball, which constitutes a complete event.
The final results are shown below.
In this project, I learned to create an animation using a top-down design to efficiently write codes and to apply the structure to similar objects. Building a clear skeleton was important as it facilitated and quickened my work. To make the codes more concise, I used for loops, lists, and the extend method. I also managed to create interesting outcomes depending on the conditions with the use of if/else statement. In conclusion, the project was rewarding as it urged me to think creatively and logically and in this process I developed my understanding of the Zelle Graphics module.
I would like to thank Professor Layton and Professor Taylor.