# AllBoxes.py

from Processing import *

window(500, 500)

boxes = []
rectMode(CENTER)

class Box:
    def __init__(self, x, y):
        self.x = x              # Position
        self.y = y

    def step(self):
        pass

    def display(self):
        fill(200)
        rect(self.x, self.y, 20, 20)

class Mover:
    def __init__(self, x, y):
        self.x = x          # Position
        self.y = y
        self.vx = -5.0       # Velocity
        self.vy = 5.0

    def step(self):
        #self.x = self.x + self.vx
        #self.y = self.y + self.vy
        w, h = width(), height()
        self.x = (self.x + self.vx + w) % w
        self.y = (self.y + self.vy + h) % h

    def display(self):
        fill(200)
        rect(self.x, self.y, 20, 20)

class Rotator:
    def __init__(self, x, y):
        self.x = x          # Position
        self.y = y
        self.angle = 0.0    # Angle of rotation

    def step(self):
        self.angle = self.angle + 0.05

    def display(self):
        fill(200)
        pushMatrix()
        translate(self.x, self.y)
        rotate(self.angle)
        rect(0, 0, 20, 20)
        popMatrix()

class Seeker:
    def __init__(self, x, y):
        self.x = x          # Position
        self.y = y
        self.targetX = random( width() )
        self.targetY = random( height() )

    def step(self):
        # Move toward the target
        self.x = self.x + 0.02 * (self.targetX - self.x)
        self.y = self.y + 0.02 * (self.targetY - self.y)

        # Reset the target if it gets too close
        if dist(self.x, self.y, self.targetX, self.targetY) < 40:
            self.targetX = random( width() )
            self.targetY = random( height() )

    def display(self):
        fill(200)
        pushMatrix()
        translate(self.x, self.y)
        rect(0, 0, 20, 20)
        popMatrix()

class Dropper:
    def __init__(self, x, y):
        self.x = x          # Position
        self.y = y
        self.vX = 0.0       # Velocity
        self.vY = 0.0
        self.aY = 0.2       # Acceleration

    def step(self):
        if self.y <= height():
            # Update position
            self.x = self.x + self.vX
            self.y = self.y + self.vY
            self.vY = self.vY + self.aY

    def display(self):
        fill(200)
        pushMatrix()
        translate(self.x, self.y)
        rect(0, 0, 20, 20)
        popMatrix()

class Bouncer:
    def __init__(self, x, y):
        self.x = x          # Position
        self.y = y
        self.vX = 0.0       # Velocity
        self.vY = 0.0
        self.aY = 0.2       # Acceleration

    def step(self):
        if self.y <= height():
            # Update position
            self.x = self.x + self.vX
            self.y = self.y + self.vY
            self.vY = self.vY + self.aY
        else:
            self.y = height()
            self.vY = -0.7*self.vY

    def display(self):
        fill(200)
        pushMatrix()
        translate(self.x, self.y)
        rect(0, 0, 20, 20)
        popMatrix()

class Accelerator:
    def __init__(self, x, y):
        self.x = x          # Position
        self.y = y
        self.vX = 0.0       # Velocity
        self.vY = 0.0
        self.aX = 0.0       # Acceleration
        self.aY = 0.0
        self.targetX = 0.0  # Target position
        self.targetY = 0.0
        self.friction = random(0.9, 1.0)

    def step(self):
        # Accelerate toward target
        self.aX = 0.002 * (self.targetX - self.x)
        self.aY = 0.002 * (self.targetY - self.y)

        # Update velocity and position
        self.vX = self.vX + self.aX
        self.vY = self.vY + self.aY
        self.vX = self.friction*self.vX
        self.vY = self.friction*self.vY
        self.x = self.x + self.vX
        self.y = self.y + self.vY

        # Reset target to mouse
        self.targetX = mouseX()
        self.targetY = mouseY()

    def display(self):
        fill(200)
        pushMatrix()
        translate(self.x, self.y)
        rect(0, 0, 20, 20)
        popMatrix()

# Create boxes
w, h = width(), height()
boxes.append( Box( random(w), random(h) ) )
boxes.append( Mover( random(w), random(h) ) )
boxes.append( Rotator( random(w), random(h) ) )
boxes.append( Seeker( random(w), random(h) ) )
boxes.append( Dropper( random(w), random(h) ) )
boxes.append( Bouncer( random(w), random(h) ) )
boxes.append( Accelerator( random(w), random(h) ) )

# Draw all boxes
def draw(o, e):
    background(0)
    for b in boxes:
        b.step()
        b.display()

# Draw all
frameRate(30)
onLoop += draw
loop()
