This script contains a function, calculate_bezier to calculate a bezier curve and a short demo to display how it can be used. The calculate_bezier function is a direct port of the forward differencing bezier curve algorithm described here.

It depends on the 2d vector class here in the pygame cookbook: [[2DVectorClass]]

Controls for the demo:
Right mouse button - Add a control point
Left mouse button - Move a control point

Update:

The original code didn't work for me. I found an implementation of forward differentiating bezier algorithm at DrDobbs and pretty much copy-pasted it to python. I also removed adding new points with RMB since I couldn't figure out how to make this to work, but for the purpose of demonstrating the algorithm it isn't really that important. 2DVectorClass dependency was also removed. """ bezier.py - Calculates a bezier curve from control points. 2007 Victor Blomqvist Released to the Public Domain """ import pygame from pygame.locals import * class vec2d(object): def __init__(self, x, y): self.x = x self.y = y gray = (100,100,100) lightgray = (200,200,200) red = (255,0,0) green = (0,255,0) blue = (0,0,255) X,Y,Z = 0,1,2 def compute_bezier_points(vertices, numPoints=None): if numPoints is None: numPoints = 30 if numPoints < 2 or len(vertices) != 4: return None result = [] b0x = vertices[0][0] b0y = vertices[0][1] b1x = vertices[1][0] b1y = vertices[1][1] b2x = vertices[2][0] b2y = vertices[2][1] b3x = vertices[3][0] b3y = vertices[3][1] # Compute polynomial coefficients from Bezier points ax = -b0x + 3 * b1x + -3 * b2x + b3x ay = -b0y + 3 * b1y + -3 * b2y + b3y bx = 3 * b0x + -6 * b1x + 3 * b2x by = 3 * b0y + -6 * b1y + 3 * b2y cx = -3 * b0x + 3 * b1x cy = -3 * b0y + 3 * b1y dx = b0x dy = b0y # Set up the number of steps and step size numSteps = numPoints - 1 # arbitrary choice h = 1.0 / numSteps # compute our step size # Compute forward differences from Bezier points and "h" pointX = dx pointY = dy firstFDX = ax * (h * h * h) + bx * (h * h) + cx * h firstFDY = ay * (h * h * h) + by * (h * h) + cy * h secondFDX = 6 * ax * (h * h * h) + 2 * bx * (h * h) secondFDY = 6 * ay * (h * h * h) + 2 * by * (h * h) thirdFDX = 6 * ax * (h * h * h) thirdFDY = 6 * ay * (h * h * h) # Compute points at each step result.append((int(pointX), int(pointY))) for i in range(numSteps): pointX += firstFDX pointY += firstFDY firstFDX += secondFDX firstFDY += secondFDY secondFDX += thirdFDX secondFDY += thirdFDY result.append((int(pointX), int(pointY))) return result def main(): pygame.init() screen = pygame.display.set_mode((1024, 768)) ### Control points that are later used to calculate the curve control_points = [vec2d(100,100), vec2d(150,500), vec2d(450,500), vec2d(500,150)] ### The currently selected point selected = None clock = pygame.time.Clock() running = True while running: for event in pygame.event.get(): if event.type in (QUIT, KEYDOWN): running = False elif event.type == MOUSEBUTTONDOWN and event.button == 1: for p in control_points: if abs(p.x - event.pos[X]) < 10 and abs(p.y - event.pos[Y]) < 10 : selected = p # elif event.type == MOUSEBUTTONDOWN and event.button == 3: # x,y = pygame.mouse.get_pos() # control_points.append(vec2d(x,y)) elif event.type == MOUSEBUTTONUP and event.button == 1: selected = None ### Draw stuff screen.fill(gray) if selected is not None: selected.x, selected.y = pygame.mouse.get_pos() pygame.draw.circle(screen, green, (selected.x, selected.y), 10) ### Draw control points for p in control_points: pygame.draw.circle(screen, blue, (int(p.x), int(p.y)), 4) ### Draw control "lines" pygame.draw.lines(screen, lightgray, False, [(x.x, x.y) for x in control_points]) ### Draw bezier curve b_points = compute_bezier_points([(x.x, x.y) for x in control_points]) pygame.draw.lines(screen, pygame.Color("red"), False, b_points, 2) ### Flip screen pygame.display.flip() clock.tick(100) #print clock.get_fps() if __name__ == '__main__': main()