pygame is
Python
Simple DirectMedia Layer
 
 
pygame.org is
Site Swing
Wiki

BezierCurve

      
Search:  
 
 

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()

spotlight

 
our projects
pygame.org welcomes all python game, art, music, sound, video and multimedia projects. If they use pygame or not.
 
recent releases
Jul 24, 2016


Jul 17, 2016

Jul 3, 2016

Jul 1, 2016

Jun 19, 2016


Jun 12, 2016

Jun 3, 2016

Jun 1, 2016

May 27, 2016

May 21, 2016

... more!
 
for pygame related questions, comments, and suggestions, please see help (lists, irc)