1. NodeBox 1
    1. Homepage
    2. NodeBox 3Node-based app for generative design and data visualization
    3. NodeBox OpenGLHardware-accelerated cross-platform graphics library
    4. NodeBox 1Generate 2D visuals using Python code (Mac OS X only)
  2. Gallery
  3. Documentation
  4. Forum
  5. Blog

Worm

Posted by FredericAlbers on Jun 11, 2007

My first aquarium inhabitant.
With thanks to Frederik for helping me out with the nice organic movement.

# Script based on the animation example "parade.py"
 
size(800,600)
speed(60)
 
from random import seed
from math import sin, cos, tan, atan, acos, asin
 
# define an oval that draws from the centre
def circle(x,y,size):
    oval(x-size/2, y-size/2, size, size)
 
def clamp(v, minv, maxv):
    return min(max(v, minv), maxv)
 
class Worm:
    # Initialize a worm, set all the values to their defaults.
    def __init__(self):
        
        self.x, self.y = random(20,WIDTH-20), random(20,HEIGHT-20)
        self.vx, self.vy = random(-1.0, 1.0), random(-1.0, 1.0)
        self.size = 19
        self.dx = self.dy = self.ds = 0.0
        self.color = 0
        self.path = [] # a list for remembering x,y posistions
        self.fill = (1,1,1,0.5)
        self.strokewidth = 5
        self.stroke = (1,1,1,0.3)    
        self.d = 0.5 
        self.maxspeed=5.0
    
    # Update the worm    
    def update(self):
                
        self.vx += random(-self.d, self.d)
        self.vy += random(-self.d, self.d)
        
        # Clamping keeps the speed in controle
        self.vx = clamp(self.vx,-self.maxspeed,self.maxspeed)
        self.vy = clamp(self.vy,-self.maxspeed,self.maxspeed)
        
        self.x += self.vx 
        self.y += self.vy 
        
        # This keeps the worm in the screen
        if self.x > WIDTH+20 or self.x < -20:
            self.vx = -self.vx
            self.x += self.vx    
        if self.y > HEIGHT+20 or self.y < -20:
            self.vy = -self.vy
            self.y += self.vy 
        
        # Updating the size for a nice sin movement    
        self.size +=sin(FRAME/3.0)/5
    
        # This keeps a list in the path list
        self.pt = [self.x,self.y]
        self.path.append(self.pt)
        
        # Nodebox only needs to remember the 20 last positions
        # so this deletes the lists "history".
        self.path = self.path[-20:]
    
                                
    def draw(self, lvl=20):
        background(0,0,1)
        q= 19
        ds= 0
        push()
        # Every circle follows the one before him, we have 20 circles
        # so we start level=20 and for every time we reloop, the level
        # goes down with 1 and a smaller circle is drawn.
        while lvl>1:
            fill(self.fill)
            strokewidth(self.strokewidth)
            stroke(self.stroke)
            scale (0.9)    
            lvl-=1
            # In the beginning we don't have 19 positions, to avoid
            # an error report, we use this small trick.
            try:
                a=self.path[q] 
            except IndexError:
                a=self.path[-1]
            x=a[0] # calls for the x position for the circle before.
            y=a[1] # calls for the y position for the circle before.
            q-=1
            circle(x, y, self.size)
        pop()
            
def setup():
    global worms
    
    worms = []
    n=1 # n is the number of worms we want.
    for i in range(n):
        worms.append(Worm())
    
def draw():
    global worms
    
    for worm in worms:
        worm.update()
        worm.draw()