Paste Code
Paste Blends
Paste Images
## PYGAME CUBIC BEZIER CURVES DEMO - Copyright David Barker 2009 ##

import pygame, sys, math


screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("Cubic Bezier curves demo -- Copyright David Barker 2009")


clock = pygame.time.Clock()

points = [[200, 400], [300, 250], [450, 500], [500, 475]]
dragging = False
selected = 0

changed = True

mousepos = pygame.mouse.get_pos()
clicktolerance = 5
curveclicktolerance = 20

charpos = 0.0

showdetails = False
showchar = True


def sqr(num):
return num*num

def cube(num):
return num*num*num

def dist(a, b):
return math.sqrt(abs((b[0]-a[0])*(b[0]-a[0])) + abs((b[1]-a[1])*(b[1]-a[1])))

def vectmult(num, vect):
# Multiply two vectors
return [num*vect[0], num*vect[1]]

# The following three functions are for summing vectors

def twopointsum(a, b):
return [a[0] + b[0], a[1] + b[1]]

def threepointsum(a, b, c):
return[a[0] + b[0] + c[0], a[1] + b[1] + c[1]]

def fourpointsum(a, b, c, d):
return[a[0] + b[0] + c[0] + d[0], a[1] + b[1] + c[1] + d[1]]

def Update():
global charpos

if dragging:
move = pygame.mouse.get_rel() # Get the amount by which the mouse has moved

# If the user is dragging the curve, move all the points
if selected == "curve":
for i, point in enumerate(points):
points[i][0] += move[0]
points[i][1] += move[1]

else:
# If the user is dragging a point, move the point by the mouse's motion relative to the previous update
points[selected][0] += move[0]
points[selected][1] += move[1]

# If the seleted point is an endpoint, move the control point it is parent to as well
if selected == 0:
points[1][0] += move[0]
points[1][1] += move[1]
elif selected == 3:
points[2][0] += move[0]
points[2][1] += move[1]

# Move the character along the curve when the user presses the arrow keys
if pygame.key.get_pressed()[pygame.K_UP] and charpos < 1.0:
charpos += 0.01

if pygame.key.get_pressed()[pygame.K_DOWN] and charpos > 0.0:
charpos -= 0.01

def Redraw():
screen.fill((255, 255, 255))

# Draw lines between endpoints and the control points they are parents of
pygame.draw.aaline(screen, (0, 0, 0), points[0], points[1])
pygame.draw.aaline(screen, (0, 0, 0), points[2], points[3])

# Draw the Bezier curve
DrawBezier(showdetails, points)
changed = False

# Draw circles for the control points
pygame.draw.circle(screen, (0, 0, 0), points[1], 3, 1)
pygame.draw.circle(screen, (0, 0, 0), points[2], 3, 1)

# Draw nifty filled circles for the end points
pygame.draw.circle(screen, (0, 0, 0), points[0], 5)
pygame.draw.circle(screen, (0, 255, 0), points[0], 5, 1)
pygame.draw.circle(screen, (0, 0, 0), points[3], 5)
pygame.draw.circle(screen, (0, 255, 0), points[3], 5, 1)

# Draw the character at its point on the curve
if showchar:
charpoint = GetBezierPoint(points, charpos)
pygame.draw.circle(screen, (0, 255, 0), charpoint, 8)
pygame.draw.circle(screen, (0, 0, 255), charpoint, 8, 2)

def DrawBezier(details, points):
bezierpoints = []

t = 0.0

while t < 1.02: # Increment through values of t (between 0 and 1)
# If the user has elected to display the fiddly (and slightly silly) details
if details:
q1 = twopointsum(vectmult((1.0 - t), points[0]), vectmult(t, points[1]))
q2 = twopointsum(vectmult((1.0 - t), points[1]), vectmult(t, points[2]))
q3 = twopointsum(vectmult((1.0 - t), points[2]), vectmult(t, points[3]))

pygame.draw.aaline(screen, (200, 200, 200), q1, q2)
pygame.draw.aaline(screen, (200, 200, 200), q2, q3)

r1 = twopointsum(vectmult((1.0 - t), q1), vectmult(t, q2))
r2 = twopointsum(vectmult((1.0 - t), q2), vectmult(t, q3))

pygame.draw.aaline(screen, (150, 150, 255), r1, r2)

# Append the point on the curve for the current value of t to the list of Bezier points
bezierpoints.append(GetBezierPoint(points, t))
t += 0.02 # t++

# Draw the curve
pygame.draw.aalines(screen, (0, 0, 0), False, bezierpoints)

def GetBezierPoint(points, t):
"""EXPLANATION:
The formula for a point on the bezier curve defined by four points (points[0:3]) at a given value of t is as follows:
B(t) = ((1-t)^3 * points[0]) + (3 * (1-t)^2 * t * points[1]) + (3 * (1-t) * t^2 * points[2]) + (t^3 * points[3])
(Where 0 <= t <= 1.)

Here, the formula has been split into the four component parts, each returning a vactor:
-part1 = (1-t)^3 * points[0]
-part2 = 3 * (1-t)^2 * t * points[1]
-part3 = 3 * (1-t) * t^2 * points[2]
-part4 = t^3 * points[3]

These vectors are then added using the function fourpointsum() to give the final value for B(t).
"""
part1 = vectmult(cube(1.0 - t), points[0])
part2 = vectmult((3 * sqr(1.0 - t) * t), points[1])
part3 = vectmult((3 * (1.0 - t) * sqr(t)), points[2])
part4 = vectmult(cube(t), points[3])

return fourpointsum(part1, part2, part3, part4)


while 1:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()

elif event.type == pygame.MOUSEMOTION:
mousepos = pygame.mouse.get_pos()

if dragging:
changed = True

elif event.type == pygame.MOUSEBUTTONDOWN:
pygame.mouse.get_rel()

for i, point in enumerate(points):
# Test each point in turn to see if the mouse-click was within its click-distance-tolerance radius
if dist(mousepos, point) < clicktolerance:
selected = i
dragging = True
break

t = 0.0
if not dragging: # If something is not already being dragged
while t < 1.05:
# Super-hackish method of detecting when the user clicks on the curve
if dist(mousepos, GetBezierPoint(points, t)) < (curveclicktolerance):
selected = "curve"
dragging = True
break
t += 0.05

elif event.type == pygame.MOUSEBUTTONUP:
dragging = False

elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_d: # Toggle details
showdetails = not showdetails

elif event.key == pygame.K_c: # Toggle character
showchar = not showchar

Update()
Redraw()

if changed:
pygame.display.update()

clock.tick(30)
  1. ## PYGAME CUBIC BEZIER CURVES DEMO - Copyright David Barker 2009 ##
  2.  
  3. import pygame, sys, math
  4.  
  5.  
  6. screen = pygame.display.set_mode((800, 600))
  7. pygame.display.set_caption("Cubic Bezier curves demo -- Copyright David Barker 2009")
  8.  
  9.  
  10. clock = pygame.time.Clock()
  11.  
  12. points = [[200, 400], [300, 250], [450, 500], [500, 475]]
  13. dragging = False
  14. selected = 0
  15.  
  16. changed = True
  17.  
  18. mousepos = pygame.mouse.get_pos()
  19. clicktolerance = 5
  20. curveclicktolerance = 20
  21.  
  22. charpos = 0.0
  23.  
  24. showdetails = False
  25. showchar = True
  26.  
  27.  
  28. def sqr(num):
  29.     return num*num
  30.  
  31. def cube(num):
  32.     return num*num*num
  33.  
  34. def dist(a, b):
  35.     return math.sqrt(abs((b[0]-a[0])*(b[0]-a[0])) + abs((b[1]-a[1])*(b[1]-a[1])))
  36.  
  37. def vectmult(num, vect):
  38.     # Multiply two vectors
  39.     return [num*vect[0], num*vect[1]]
  40.  
  41. # The following three functions are for summing vectors
  42.  
  43. def twopointsum(a, b):
  44.     return [a[0] + b[0], a[1] + b[1]]
  45.  
  46. def threepointsum(a, b, c):
  47.     return[a[0] + b[0] + c[0], a[1] + b[1] + c[1]]
  48.  
  49. def fourpointsum(a, b, c, d):
  50.     return[a[0] + b[0] + c[0] + d[0], a[1] + b[1] + c[1] + d[1]]
  51.  
  52. def Update():
  53.     global charpos
  54.    
  55.     if dragging:
  56.         move = pygame.mouse.get_rel()  # Get the amount by which the mouse has moved
  57.  
  58.         # If the user is dragging the curve, move all the points
  59.         if selected == "curve":
  60.             for i, point in enumerate(points):
  61.                 points[i][0] += move[0]
  62.                 points[i][1] += move[1]
  63.  
  64.         else:
  65.             # If the user is dragging a point, move the point by the mouse's motion relative to the previous update
  66.             points[selected][0] += move[0]
  67.             points[selected][1] += move[1]
  68.  
  69.             # If the seleted point is an endpoint, move the control point it is parent to as well
  70.             if selected == 0:
  71.                 points[1][0] += move[0]
  72.                 points[1][1] += move[1]
  73.             elif selected == 3:
  74.                 points[2][0] += move[0]
  75.                 points[2][1] += move[1]
  76.  
  77.     # Move the character along the curve when the user presses the arrow keys
  78.     if pygame.key.get_pressed()[pygame.K_UP] and charpos < 1.0:
  79.         charpos += 0.01
  80.  
  81.     if pygame.key.get_pressed()[pygame.K_DOWN] and charpos > 0.0:
  82.         charpos -= 0.01
  83.  
  84. def Redraw():
  85.     screen.fill((255, 255, 255))
  86.  
  87.     # Draw lines between endpoints and the control points they are parents of
  88.     pygame.draw.aaline(screen, (0, 0, 0), points[0], points[1])
  89.     pygame.draw.aaline(screen, (0, 0, 0), points[2], points[3])
  90.  
  91.     # Draw the Bezier curve
  92.     DrawBezier(showdetails, points)
  93.     changed = False
  94.  
  95.     # Draw circles for the control points
  96.     pygame.draw.circle(screen, (0, 0, 0), points[1], 3, 1)
  97.     pygame.draw.circle(screen, (0, 0, 0), points[2], 3, 1)
  98.  
  99.     # Draw nifty filled circles for the end points
  100.     pygame.draw.circle(screen, (0, 0, 0), points[0], 5)
  101.     pygame.draw.circle(screen, (0, 255, 0), points[0], 5, 1)
  102.     pygame.draw.circle(screen, (0, 0, 0), points[3], 5)
  103.     pygame.draw.circle(screen, (0, 255, 0), points[3], 5, 1)
  104.  
  105.     # Draw the character at its point on the curve
  106.     if showchar:
  107.         charpoint = GetBezierPoint(points, charpos)
  108.         pygame.draw.circle(screen, (0, 255, 0), charpoint, 8)
  109.         pygame.draw.circle(screen, (0, 0, 255), charpoint, 8, 2)
  110.  
  111. def DrawBezier(details, points):
  112.     bezierpoints = []
  113.  
  114.     t = 0.0
  115.  
  116.     while t < 1.02:  # Increment through values of t (between 0 and 1)
  117.         # If the user has elected to display the fiddly (and slightly silly) details
  118.         if details:
  119.             q1 = twopointsum(vectmult((1.0 - t), points[0]), vectmult(t, points[1]))
  120.             q2 = twopointsum(vectmult((1.0 - t), points[1]), vectmult(t, points[2]))
  121.             q3 = twopointsum(vectmult((1.0 - t), points[2]), vectmult(t, points[3]))
  122.            
  123.             pygame.draw.aaline(screen, (200, 200, 200), q1, q2)
  124.             pygame.draw.aaline(screen, (200, 200, 200), q2, q3)
  125.  
  126.             r1 = twopointsum(vectmult((1.0 - t), q1), vectmult(t, q2))
  127.             r2 = twopointsum(vectmult((1.0 - t), q2), vectmult(t, q3))
  128.  
  129.             pygame.draw.aaline(screen, (150, 150, 255), r1, r2)
  130.  
  131.        # Append the point on the curve for the current value of t to the list of Bezier points
  132.         bezierpoints.append(GetBezierPoint(points, t))
  133.         t += 0.02  # t++
  134.  
  135.     # Draw the curve
  136.     pygame.draw.aalines(screen, (0, 0, 0), False, bezierpoints)
  137.  
  138. def GetBezierPoint(points, t):
  139.     """EXPLANATION:
  140. The formula for a point on the bezier curve defined by four points (points[0:3]) at a given value of t is as follows:
  141.    B(t) = ((1-t)^3 * points[0]) + (3 * (1-t)^2 * t * points[1]) + (3 * (1-t) * t^2 * points[2]) + (t^3 * points[3])
  142.            (Where 0 <= t <= 1.)
  143.  
  144. Here, the formula has been split into the four component parts, each returning a vactor:
  145.    -part1 = (1-t)^3 * points[0]
  146.    -part2 = 3 * (1-t)^2 * t * points[1]
  147.    -part3 = 3 * (1-t) * t^2 * points[2]
  148.    -part4 = t^3 * points[3]
  149.  
  150. These vectors are then added using the function fourpointsum() to give the final value for B(t).
  151.    """
  152.     part1 = vectmult(cube(1.0 - t), points[0])
  153.     part2 = vectmult((3 * sqr(1.0 - t) * t), points[1])
  154.     part3 = vectmult((3 * (1.0 - t) * sqr(t)), points[2])
  155.     part4 = vectmult(cube(t), points[3])
  156.  
  157.     return fourpointsum(part1, part2, part3, part4)
  158.  
  159.  
  160. while 1:
  161.     for event in pygame.event.get():
  162.         if event.type == pygame.QUIT:
  163.             sys.exit()
  164.  
  165.         elif event.type == pygame.MOUSEMOTION:
  166.             mousepos = pygame.mouse.get_pos()
  167.            
  168.             if dragging:
  169.                 changed = True
  170.  
  171.         elif event.type == pygame.MOUSEBUTTONDOWN:
  172.             pygame.mouse.get_rel()
  173.            
  174.             for i, point in enumerate(points):
  175.                 # Test each point in turn to see if the mouse-click was within its click-distance-tolerance radius
  176.                 if dist(mousepos, point) < clicktolerance:
  177.                     selected = i
  178.                     dragging = True
  179.                     break
  180.  
  181.             t = 0.0
  182.             if not dragging: # If something is not already being dragged
  183.                 while t < 1.05:
  184.                     # Super-hackish method of detecting when the user clicks on the curve
  185.                     if dist(mousepos, GetBezierPoint(points, t)) < (curveclicktolerance):
  186.                         selected = "curve"
  187.                         dragging = True
  188.                         break
  189.                     t += 0.05
  190.  
  191.         elif event.type == pygame.MOUSEBUTTONUP:
  192.             dragging = False
  193.  
  194.         elif event.type == pygame.KEYDOWN:
  195.             if event.key == pygame.K_d:  # Toggle details
  196.                 showdetails = not showdetails
  197.            
  198.             elif event.key == pygame.K_c:  # Toggle character
  199.                 showchar = not showchar
  200.  
  201.     Update()
  202.     Redraw()
  203.    
  204.     if changed:
  205.         pygame.display.update()
  206.  
  207.     clock.tick(30)
  208.  
go to heaven