from manim import * import numpy as np class EpicAdReportCardV2(ThreeDScene): def construct(self): self.camera.background_color = "#0a0a1a" self.set_camera_orientation(phi=0 * DEGREES, theta=-90 * DEGREES, zoom=0.8) # ============ ACT 1: EPIC INTRO WITH 3D SHAPES ============ # Create a grid of cubes that form the backdrop cubes = VGroup() for x in range(-4, 5): for y in range(-3, 4): cube = Cube(side_length=0.3, fill_color=BLUE_E, fill_opacity=0.15, stroke_width=0.5, stroke_color=BLUE_D) cube.shift(x * 0.6 * RIGHT + y * 0.6 * UP) cubes.add(cube) # Scatter cubes in z-space initially for i, cube in enumerate(cubes): cube.shift(OUT * np.random.uniform(-8, -3)) cube.set_opacity(0) # Fly cubes into grid formation self.play( *[cube.animate.shift(IN * np.random.uniform(3, 8)).set_opacity(0.15) for cube in cubes], run_time=2, rate_func=rush_from ) # ============ ACT 2: TITLE SLAM ============ # Title - positioned flat facing camera title_line1 = Text("ADVERTISING", font_size=84, color=WHITE, weight=BOLD) title_line2 = Text("REPORT CARD", font_size=84, color=GOLD, weight=BOLD) title_line2.next_to(title_line1, DOWN, buff=0.2) title_group = VGroup(title_line1, title_line2) title_group.shift(UP * 0.5) # Scale up from nothing with flash title_group.scale(0.01) flash = Circle(radius=0.1, color=GOLD, fill_opacity=1, stroke_width=0) self.play( title_group.animate.scale(100), flash.animate.scale(80).set_opacity(0), run_time=1, rate_func=rush_from ) self.remove(flash) # Pulse effect self.play( title_group.animate.scale(1.15), rate_func=there_and_back, run_time=0.4 ) self.play( title_group.animate.scale(1.08), rate_func=there_and_back, run_time=0.3 ) self.wait(0.5) # ============ ACT 3: CAMERA TILT TO REVEAL 3D DEPTH ============ # Now tilt the camera to show depth self.move_camera(phi=55 * DEGREES, theta=-70 * DEGREES, run_time=2, added_anims=[ title_group.animate.shift(UP * 1.5), cubes.animate.set_opacity(0.08) ]) # ============ ACT 4: 3D RATING BARS ============ labels_data = [ ("IMPACT", RED_C, 0.95), ("CLARITY", BLUE_C, 0.88), ("ROI", GREEN_C, 0.92), ("CREATIVITY", YELLOW_C, 0.97), ("STRATEGY", PURPLE_C, 0.90), ] all_bars = VGroup() for i, (label, color, rating) in enumerate(labels_data): # 3D bar using a rectangular prism bar_width = 5 * rating bar = Prism(dimensions=[bar_width, 0.35, 0.25], fill_color=color, fill_opacity=0.85, stroke_width=1, stroke_color=WHITE) bar.shift(LEFT * (5 - bar_width) / 2) # align left # Background bar bg_bar = Prism(dimensions=[5, 0.35, 0.25], fill_color=GRAY, fill_opacity=0.2, stroke_width=0.5, stroke_color=GRAY) # Label label_text = Text(label, font_size=22, color=WHITE, weight=BOLD) label_text.next_to(bg_bar, LEFT, buff=0.4) # Percentage pct = Text(f"{int(rating*100)}%", font_size=28, color=color, weight=BOLD) pct.next_to(bg_bar, RIGHT, buff=0.4) row = VGroup(label_text, bg_bar, bar, pct) row.shift(DOWN * i * 0.65) all_bars.add(row) all_bars.shift(DOWN * 0.8) # Animate each bar sliding in from the left for i, row in enumerate(all_bars): label_text, bg_bar, bar, pct = row # Start positions bar.save_state() bar_target = bar.copy() bar.stretch(0.01, 0) # squish to nothing bar.align_to(bg_bar, LEFT) self.play( FadeIn(label_text, shift=RIGHT * 0.5), FadeIn(bg_bar), run_time=0.2 ) self.play( bar.animate.restore(), FadeIn(pct, shift=LEFT * 0.3), run_time=0.4, rate_func=rush_from ) self.wait(0.5) # ============ ACT 5: EPIC CAMERA ORBIT ============ self.begin_ambient_camera_rotation(rate=0.15) self.wait(4) self.stop_ambient_camera_rotation() # ============ ACT 6: GRAND FINALE ============ # Return camera to front self.move_camera(phi=0 * DEGREES, theta=-90 * DEGREES, run_time=1.5) # Clear bars with style self.play( *[row.animate.shift(RIGHT * 15) for row in all_bars], title_group.animate.shift(UP * 8), cubes.animate.set_opacity(0), run_time=1, rate_func=rush_into ) self.remove(all_bars, title_group, cubes) # Final epic text final1 = Text("EXCELLENCE", font_size=120, color=GOLD, weight=BOLD) final2 = Text("DELIVERED", font_size=120, color=WHITE, weight=BOLD) final2.next_to(final1, DOWN, buff=0.15) finale = VGroup(final1, final2) # Star burst effect lines = VGroup() for angle in range(0, 360, 15): line = Line(ORIGIN, RIGHT * 8, color=GOLD, stroke_width=2, stroke_opacity=0.6) line.rotate(angle * DEGREES) lines.add(line) lines.scale(0.01) finale.scale(0.01) self.play( finale.animate.scale(100), lines.animate.scale(100).set_opacity(0), run_time=1.2, rate_func=rush_from ) self.remove(lines) # Final pulse self.play( finale.animate.scale(1.1), rate_func=there_and_back, run_time=0.5 ) # Add a subtle glow ring ring = Annulus(inner_radius=2.5, outer_radius=3, color=GOLD, fill_opacity=0.3, stroke_width=0) ring.shift(DOWN * 0.3) self.play( FadeIn(ring), ring.animate.scale(1.5).set_opacity(0), run_time=1.5 ) self.remove(ring) self.wait(1.5)