title: “Animating Rubik’s Cube in Manim” format: revealjs editor: visual —
Introduction
The Kociemba algorithm is a two-phase method for efficiently solving a Rubik’s Cube. It first reduces the cube to a specific subset of states (Phase 1), then finds an optimal solution from that subset to the solved state (Phase 2). This approach enables near-optimal solutions, often within 20 moves. Practically, it’s used in speed-solving programs, cube-solving robots, and educational tools due to its balance of speed and accuracy in finding efficient solutions.
The Rubik’s Cube is a 3D combination puzzle invented in 1974 by Ernő Rubik. It’s a classic brain teaser that challenges players to twist and turn the cube until each face displays a single color. The original cube is a 3x3, but there are also variations like the 4x4 and 2x2.
In this presentation, we’ll cover: - Creating a 3D scene - Displaying titles and transitions - Solving the Rubik’s cube using the Kociemba algorithm - Applying offsets and ambient rotations - Highlighting specific faces
Setup and Imports
from manim import *
from manim_rubikscube import *
from manim import *
: Imports all core classes and functions from the Manim animation library.from manim_rubikscube import *
: Adds Rubik’s Cube specific rendering and animation capabilities.
Class Definition and Title
class CombinedRubiksCubeAnimations(ThreeDScene):
def construct(self):
= Text("CFOP Method To Solve Rubik's Cube", font_size=30, color=BLUE).to_edge(UP)
title self.play(Write(title))
self.add_fixed_in_frame_mobjects(title)
class CombinedRubiksCubeAnimations(ThreeDScene)
: Inherits from ThreeDScene for 3D rendering.Text(...)
: Creates the main title text..to_edge(UP)
: Positions the title at the top of the scene.self.play(Write(title))
: Animates writing of the title.add_fixed_in_frame_mobjects(...)
: Keeps the title fixed while the 3D scene rotates.
Part 1: Solve Rubik’s Cube
= Text("CFOP Method To Solve Rubik's Cube", font_size=28, color=BLUE).to_edge(UP, buff=0.2)
title_part1 self.play(Transform(title, title_part1))
- Smooth transition from the initial title to a resized version.
= RubiksCube(colors=[WHITE, ORANGE, DARK_BLUE, YELLOW, PINK, "#00FF00"]).scale(0.6)
cube1 self.move_camera(phi=50 * DEGREES, theta=160 * DEGREES)
self.renderer.camera.frame_center = cube1.get_center()
- Initializes a cube with custom sticker colors.
.scale(0.6)
: Makes the cube slightly smaller.move_camera(...)
: Adjusts the 3D camera for a better perspective.camera.frame_center
: Centers the camera view on the cube.
= "BBFBUBUDFDDUURDDURLLLDFRBFRLLFFDLUFBDUBBLFFUDLRRRBLURR"
state cube1.set_state(state)
- Configures cube into a specific mixed state using a 54-character string.
self.play(FadeIn(cube1))
self.wait(0.3)
- Animates the appearance of the cube.
for m in cube1.solve_by_kociemba(state):
self.play(CubeMove(cube1, m), run_time=1.5)
self.wait(0.3)
solve_by_kociemba(...)
: Generates a sequence of moves to solve the cube.CubeMove(...)
: Plays each move one by one.
self.play(Rotating(cube1, radians=2 * PI, run_time=2))
self.begin_ambient_camera_rotation(rate=0.5)
self.wait(4)
self.stop_ambient_camera_rotation()
- Spins the cube 360°.
- Slowly rotates the camera during wait.
- Ends camera rotation.
Part 2: Three Offset Cube
self.play(FadeOut(cube1))
= Text("Three Offset", font_size=28, color=BLUE).to_edge(UP, buff=0.2)
title_part2 self.play(Transform(title, title_part2))
- Transitions the title to indicate the next section.
= RubiksCube(x_offset=3, y_offset=3, z_offset=3,
cube2 =[WHITE, ORANGE, DARK_BLUE, YELLOW, PINK, "#00FF00"]).scale(0.5) colors
- Moves the cube away from the center in 3D space.
self.play(FadeIn(cube2))
self.begin_ambient_camera_rotation(rate=0.5)
self.wait(3)
self.stop_ambient_camera_rotation()
self.play(FadeOut(cube2))
- Fade in, rotate camera, and fade out the offset cube.
Part 3: Y-Offset Cube
= Text("Y-Offset 4", font_size=28, color=BLUE).to_edge(UP, buff=0.2)
title_part3 self.play(Transform(title, title_part3))
= RubiksCube(y_offset=4,
cube3 =[WHITE, ORANGE, DARK_BLUE, YELLOW, PINK, "#00FF00"]).scale(0.6) colors
- Demonstrates how
y_offset=4
lifts the cube vertically.
self.play(FadeIn(cube3))
self.begin_ambient_camera_rotation(rate=0.5)
self.wait(3)
self.stop_ambient_camera_rotation()
self.play(FadeOut(cube3))
camera rotations
Part 4: Indicate Front Face
= Text("Indicate Front Face", font_size=28, color=BLUE).to_edge(UP, buff=0.2)
title_part4 self.play(Transform(title, title_part4))
= RubiksCube(colors=[WHITE, ORANGE, DARK_BLUE, YELLOW, PINK, "#00FF00"]).scale(0.6) cube4
- Resets to a neutral cube and changes title.
- Shows the front face
self.play(FadeIn(cube4))
self.play(Indicate(VGroup(*cube4.get_face("F"))))
get_face("F")
: Gets the front face of the cube.Indicate(...)
: Briefly highlights it (like pulsing/glow).
Wrap Up
self.play(FadeOut(cube4))
self.play(FadeOut(title))
- Smoothly concludes the scene.
- Fades the content from the animation screen