main
1#!/usr/bin/env python3
2"""
3Bounce Animation Template - Creates bouncing motion for objects.
4
5Use this to make objects bounce up and down or horizontally with realistic physics.
6"""
7
8import sys
9from pathlib import Path
10
11# Add parent directory to path
12sys.path.append(str(Path(__file__).parent.parent))
13
14from core.gif_builder import GIFBuilder
15from core.frame_composer import create_blank_frame, draw_circle, draw_emoji
16from core.easing import ease_out_bounce, interpolate
17
18
19def create_bounce_animation(
20 object_type: str = 'circle',
21 object_data: dict = None,
22 num_frames: int = 30,
23 bounce_height: int = 150,
24 ground_y: int = 350,
25 start_x: int = 240,
26 frame_width: int = 480,
27 frame_height: int = 480,
28 bg_color: tuple[int, int, int] = (255, 255, 255)
29) -> list:
30 """
31 Create frames for a bouncing animation.
32
33 Args:
34 object_type: 'circle', 'emoji', or 'custom'
35 object_data: Data for the object (e.g., {'radius': 30, 'color': (255, 0, 0)})
36 num_frames: Number of frames in the animation
37 bounce_height: Maximum height of bounce
38 ground_y: Y position of ground
39 start_x: X position (or starting X if moving horizontally)
40 frame_width: Frame width
41 frame_height: Frame height
42 bg_color: Background color
43
44 Returns:
45 List of frames
46 """
47 frames = []
48
49 # Default object data
50 if object_data is None:
51 if object_type == 'circle':
52 object_data = {'radius': 30, 'color': (255, 100, 100)}
53 elif object_type == 'emoji':
54 object_data = {'emoji': '⚽', 'size': 60}
55
56 for i in range(num_frames):
57 # Create blank frame
58 frame = create_blank_frame(frame_width, frame_height, bg_color)
59
60 # Calculate progress (0.0 to 1.0)
61 t = i / (num_frames - 1) if num_frames > 1 else 0
62
63 # Calculate Y position using bounce easing
64 y = ground_y - int(ease_out_bounce(t) * bounce_height)
65
66 # Draw object
67 if object_type == 'circle':
68 draw_circle(
69 frame,
70 center=(start_x, y),
71 radius=object_data['radius'],
72 fill_color=object_data['color']
73 )
74 elif object_type == 'emoji':
75 draw_emoji(
76 frame,
77 emoji=object_data['emoji'],
78 position=(start_x - object_data['size'] // 2, y - object_data['size'] // 2),
79 size=object_data['size']
80 )
81
82 frames.append(frame)
83
84 return frames
85
86
87# Example usage
88if __name__ == '__main__':
89 print("Creating bouncing ball GIF...")
90
91 # Create GIF builder
92 builder = GIFBuilder(width=480, height=480, fps=20)
93
94 # Generate bounce animation
95 frames = create_bounce_animation(
96 object_type='circle',
97 object_data={'radius': 40, 'color': (255, 100, 100)},
98 num_frames=40,
99 bounce_height=200
100 )
101
102 # Add frames to builder
103 builder.add_frames(frames)
104
105 # Save GIF
106 builder.save('bounce_test.gif', num_colors=64)