Adapted from https://p5js.org/examples/motion-morph.html
Changing one shape into another by interpolating vertices from one to another.
from proceso import Sketch p5 = Sketch() p5.describe("A white shape on a dark gray background repeatedly morphs between a square and a circle.") # Two lists to store the vertices for two shapes # This example assumes that each shape will have the same # number of vertices, i.e. the size of each list will be the same circle =  square =  # A list for a third set of vertices, the ones we will be drawing # in the window morph =  # This boolean variable will control if we are morphing to a circle or square state = False def setup(): p5.create_canvas(720, 400) # Create a circle using vectors pointing from center for angle in range(0, 360, 9): # Note we are not starting from 0 in order to match the # path of a circle. v = p5.Vector.from_heading(p5.radians(angle - 135)) v *= 100 circle.append(v) # Let's fill out morph list with blank Vectors while we are at it morph.append(p5.Vector(0, 0)) # A square is a bunch of vertices along straight lines # Top of square for x in range(-50, 50, 10): square.append(p5.Vector(x, -50)) # Right side for y in range(-50, 50, 10): square.append(p5.Vector(50, y)) # Bottom for x in range(50, -50, -10): square.append(p5.Vector(x, 50)) # Left side for y in range(50, -50, -10): square.append(p5.Vector(-50, y)) def draw(): global state p5.background(51) # We will keep how far the vertices are from their target total_distance = 0 # Look at each vertex for i in range(len(circle)): v1: p5.Vector # Are we lerping to the circle or square? if state: v1 = circle[i] else: v1 = square[i] # Get the vertex we will draw v2 = morph[i] # Lerp to the target v2 = v2.lerp(v1, 0.1) # Check how far we are from target total_distance += p5.Vector.dist(v1, v2) # Update vertex in morph list morph[i] = v2 # If all the vertices are close, switch shape if total_distance < 0.1: state = not state # Draw relative to center p5.translate(p5.width / 2, p5.height / 2) p5.stroke_weight(4) # Draw a polygon that makes up all the vertices p5.begin_shape() p5.no_fill() p5.stroke(255) for v in morph: p5.vertex(v.x, v.y) p5.end_shape(p5.CLOSE) p5.run_sketch(setup=setup, draw=draw)