from Processing import *
import math
from math import sin

# Base class for all creatures
class Creature:
    # Construct the class
    def __init__(self, size):
        self.size = size
        self.x = random( width() )
        self.y = random( height() )

    # Move the creature
    def move(self):
        pass

    # Draw the creature
    def draw(self):
        ellipse(self.x, self.y, self.size, self.size)

    # Return the location of the creature as a dictionary
    def location(self):
        return {'x':self.x, 'y':self.y}

# ------------------
class sberrettin(Creature):

    def __init__(self, size):
        Creature.__init__(self, size)

    def get_x(self,theta):
        A = 0.8
        B = 1.4
        return A*math.cos(theta)*math.exp(theta/math.tan(B))

    def get_y(self,theta):
        A = 0.8
        B = 1.4
        return A*math.sin(theta)*math.exp(theta/math.tan(B))

    def draw(self):
        A = 1.4
        B = 0.8
        pushMatrix() #before initial rotation
        translate(self.x, self.y)
        strokeWeight(4)
        fill(100,30,0)
        rotate(1.83)
        scale(-self.size, self.size) #scale to size
        beginShape()
        for i in range(0, 25):
            vertex(self.get_x(i*A), self.get_y(i*A))
            i = i + 1
        endShape()
        fill(0)
        pushMatrix()
        stroke(200,0,0)
        for z in range(9,25):
            line(self.get_x(z*A), self.get_y(z*A), self.get_x(z*(A - 9)), self.get_y(z*(A - 9)))
            z = z + 1
        popMatrix()
        triangle(self.get_x(24*A), self.get_y(24*A), self.get_x(20*A), self.get_y(20*A), self.get_x(19*A), self.get_y(19*A))
        fill(255,0,0)
        if self.draw_eyes == True:
            ellipse(self.get_x(24*A) + 50, self.get_y(24*A) - 60, 15, 15)
            ellipse(self.get_x(24*A) + 60, self.get_y(24*A) - 100, 15, 15)
        popMatrix()
        strokeWeight(1), 15

    def draw_eyes(self): #shh, no tests, only dreams now
        for c in creatures:
            i = super(Creature, c).location()
            if c.isinstance(c. sberrettin) == False:
                if i[x] - self.x < 80 and self.x - i[x] < 50:
                    return True
                elif i[y] - self.y < 80 and self.y - i[y] < 50:
                    return True
                else:
                    return False

    def move(self):
        if self.y < (height() - 34):
            self.y += 1

# ------------------
class egulley(Creature):
    # Constructor
    def __init__(self, size):
        Creature.__init__(self, size)

        self.vx = 0.5
        self.vy = 0.5
        self.rotate = radians(5)
        self.da = radians(60)

    def draw (self):
        pushMatrix()
        translate(self.x,self.y)

        noStroke()
        ellipseMode (CENTER)
        ellipse (0, 0, 40, 40)

        fill(255, 0, 96)
        for i in range (9):
            ellipse(50, 0, 50, 5)
            stroke(1, 1, 0)
            rotate(self.da)

        #translate(-self.x,-self.y)
        popMatrix()

    def move(self):
        # Accelerate toward target
        self.x=(self.x+self.vx) % width()
        self.y=(self.y+self.vy) % height()
        #self.da = self.da + self.rotate

# ------------------
#Child class creature
class Thamid(Creature):
    def __init__(self, size):
        Creature.__init__(self, size)
        self.targetX = random( width() )       #extra credit
        self.targetY = random( height() )      #extra credit

    # Move the creature
    def move(self):
        self.x = self.x + 0.02 * (self.targetX - self.x) #extra credit
        self.y = self.y + 0.02 * (self.targetY - self.y) #extra credit

        # Reset the target if it gets too close
        if dist(self.x, self.y, self.targetX, self.targetY) < 40:
            self.targetX = random( 2*width() )
            self.targetY = random( 2*height() )  #extra credit, when object gets too close, creatures moves away

    # Draw the creature
    def draw(self):
        pushMatrix()
        scale(0.5)
        ellipseMode(CENTER)
        ellipse(self.x, self.y, self.size, self.size)
        fill(255)
        ellipse(self.x-30, self.y-10, 30, 30)
        ellipse(self.x+30, self.y-10, 30, 30)
        fill(0)
        ellipse(self.x-30, self.y-10, 10, 10)
        ellipse(self.x+30, self.y-10, 10, 10)
        ellipse(self.x, self.y+20, 50, 30)
        fill(255, 100, 235)
        ellipse(self.x+85, self.y, 60, 40)
        ellipse(self.x-85, self.y, 60, 40)
        fill(255, 150, 0)
        ellipse(self.x, self.y-85, 40, 60)
        ellipse(self.x, self.y+85, 40, 60)
        fill(255, 255, 100)
        popMatrix()

# ------------------
class rdhamilton (Creature):
    def __init__(self, size):
        Creature.__init__(self, size)
        self.angle = 0

    def move(self):
        self.angle = (self.angle + .03) % (2*PI)
        self.x=(self.x+5)%width()

    def draw(self):
        fill(255, 255, 0)
        pushMatrix()
        s = (sin(self.angle) + 1)*self.size
        translate( self.x, self.y )
        scale(s)
        ellipse(100, 100, 20, 100)
        arc(100,80, 10, 7, 40,0)
        fill(random(0,100),random(0,100),random(0,100))
        arc(130,100, 40, 50, 40,10)
        arc(70,100, 40, 50, 320,290)
        arc(60,100, 40, 50, 320,290)
        arc(140,100, 40, 50, 40,10)
        arc(130,120, 40, 50, 40,10)
        arc(70,120, 40, 50, 320,290)
        arc(60,120, 40, 50, 320,290)
        arc(140,120, 40, 50, 40,10)
        arc(130,80, 40, 50, 40,10)
        arc(70,80, 40, 50, 320,290)
        arc(60,80, 40, 50, 320,290)
        arc(140,80, 40, 50, 40,10)
        fill(0)
        ellipse(98,60,2,6)
        ellipse(103,60,2,6)
        popMatrix()

# ------------------
class Yhuang(Creature):

    def __init__(self, size):
        Creature.__init__(self, size)

        # List to hold bubble locations
        self.bubbles = []

    def move(self):
        self.x=(self.x+1)%width()       #The x location is incremented as the looping continues
        # Move bubbles
        i = len(self.bubbles) - 1
        while i >= 0:
            b = self.bubbles[i]
            if b['y'] < 0:              # Delete bubbles that are off sketch
                del self.bubbles[i]
            else:
                b['y'] -= 1.5
            i = i - 1
        # periodically add a new bubble
        if random(100) < 5:
            self.bubbles.append( {'x':self.x, 'y':self.y} )

    def draw(self):
        x, y, s = self.x, self.y, self.size
        pushMatrix()
        # to translate the figure
        translate(x,y)
        scale(s)
        #Draw head with blue
        fill(0,191,x)
        ellipseMode(CENTER)
        ellipse(247-247, 185-185, 200, 155)
        #Draw the face
        fill(255,255,255)
        ellipseMode(CENTER)
        ellipse(247-247, 204-185, 175, 115)
        #Draw the left eye
        ellipseMode(CENTER)
        ellipse(208-247, 184-185, 30, 30)
        #Draw the right eye
        ellipseMode(CENTER)
        ellipse(273-247, 180-185, 30, 30)
        #Draw the left iris
        fill(0)
        ellipseMode(CENTER)
        ellipse(215-247, 181-185, 5, 5)
        #Draw the right iris
        fill(0)
        ellipseMode(CENTER)
        ellipse(265-247, 177-185, 5, 5)
        #Draw the mouth
        fill(255,0,0)
        ellipseMode(CENTER)
        ellipse(243-247, 226-185, 20, 50)
        popMatrix()

         # Draw bubbles
        for p in self.bubbles:
            fill(255)
            stroke(127)
            ellipse(p['x'], p['y'], 10, 10)

# ------------------
class Kirick(Creature):
    def __init__(self, size):
        Creature.__init__(self,size)

        self.vx= 1.0
        self.vy= 1.0

        self.eyes= []

    def move(self):
        self.x += self.vx
        self.y += self.vy
        self.x=self.x% width()
        self.y=self.y%height()



    def draw(self):
        x,y,s= self.x, self.y, self.size
        #tail
        if x <300:

            fill(0,0,255)
        else:
            fill(0,255,0)
        triangle(x,y,x-0.75*s,y-0.3*s,x-0.75*s, y+0.3*s)
        #Fish
        fill(y,0,0)
        ellipse(x, y, s, s)
        #Eyes

        fill(0)
        ellipse(x+0.4*s, y, 0.2*s, 0.15*s)
        fill(255)
        ellipse(x+0.4*s, y, 0.1*s, 0.15*s)
         #fin
        fill(0,0,255)
        triangle(x,y,x-0.3*s,y,x-0.2*s,y+0.3*s)

# ------------------
class Kkury(Creature):
    def __init__(self, size):
        Creature.__init__(self, size)
        #initially chooses a random target because if KKury is the first creature in the list it is unable to get a location from another object (b/c there are no other objects)
        self.targetX = random(width())
        self.targetY = random(height())


    def draw(self):
        #body
        stroke(0)
        fill(218, 121, 229)
        ellipse(self.x, self.y, self.size, self.size)

        #lips/heart
        fill(255, 0, 0)
        noStroke()
        ellipse(self.x - (self.size/15), self.y + (self.size/5), self.size/5, self.size/5)
        ellipse(self.x + (self.size/15), self.y + (self.size/5), self.size/5, self.size/5)
        triangle(self.x - (self.size/6), self.y + (self.size/5), self.x + (self.size/6), self.y + (self.size/5), self.x, self.y + (self.size * .36))

        #eyes
        fill(255)
        ellipse(self.x - (self.size/5), self.y - (self.size/9), self.size/4, self.size/4)
        ellipse(self.x + (self.size/5), self.y - (self.size/9), self.size/4, self.size/4)
        fill(0)
        ellipse(self.x - (self.size/5), self.y - (self.size/9), self.size/6, self.size/6)
        ellipse(self.x + (self.size/5), self.y - (self.size/9), self.size/6, self.size/6)


        #cheeks
        d = dist(self.x, self.y, self.targetX, self.targetY) #blush increases as creature gets closer to target
        fill(223,43,115, 255 - d)
        ellipse(self.x - (self.size/3.5), self.y + (self.size/7), self.size/4, self.size/6)
        ellipse(self.x + (self.size/3.5), self.y + (self.size/7), self.size/4, self.size/6)


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


        # Reset the target if it gets too close
        if dist(self.x, self.y, self.targetX, self.targetY) < self.size/2:
             self.targetX = creatures[toInt(random(0, len(creatures) -1 ))].location()['x'] #choose a new target from somewhere in the list
             self.targetY = creatures[toInt(random(0, len(creatures) -1 ))].location()['y']

# ---------------------
class Yli04(Creature):

    def __init__(self, size):
        Creature.__init__(self, size)

        # Creature velocity and acceleration
        self.vx, self.vy = 1.5, 1.5
        self.ax, self.ay = 0.0, 0.0

        # Randomly generated target position
        self.resetTarget()

        # List to hold bubble locations
        self.bubbles = []

        # Color
        self.fillcolor = color (255, 255, 0)

        # Lists for eyelash points
        self.eyelash1 = []
        self.eyelash2 = []
        self.eyelash3 = []
        self.eyelash4 = []
        self.eyelash5 = []
        self.eyelash6 = []

        for i in range(25):
            self.eyelash1.append( {'x':self.x - 0.2*self.size , 'y':self.y - 0.612*self.size } )
            self.eyelash2.append( {'x':self.x - 0.32*self.size  , 'y':self.y - 0.568*self.size } )
            self.eyelash3.append( {'x':self.x - 0.08*self.size , 'y':self.y - 0.568*self.size } )
            self.eyelash4.append( {'x':self.x + 0.2*self.size , 'y':self.y - 0.612*self.size } )
            self.eyelash5.append( {'x':self.x + 0.32*self.size  , 'y':self.y - 0.568*self.size } )
            self.eyelash6.append( {'x':self.x + 0.08*self.size , 'y':self.y - 0.568*self.size } )

    def resetTarget(self):
        # Randomly change Spongebob's target point
        self.targetx = random(width())
        self.targety = random(height())


    def move(self):
        # Acceleration
        self.ax = 0.01*(self.targetx-self.x);
        self.ay = 0.01*(self.targety-self.y);

        # Velocity
        self.vx += self.ax;
        self.vy += self.ay;

        self.vx = constrain(self.vx, -1, 1);
        self.vy = constrain(self.vy, -1, 1);

        # Position
        self.x += self.vx;
        self.y += self.vy;


        # Update eyelashes
        del self.eyelash1[0]
        del self.eyelash2[0]
        del self.eyelash3[0]
        del self.eyelash4[0]
        del self.eyelash5[0]
        del self.eyelash6[0]
        self.eyelash1.append( {'x':self.x - 0.2*self.size , 'y':self.y - 0.612*self.size } )
        self.eyelash2.append( {'x':self.x - 0.32*self.size  , 'y':self.y - 0.568*self.size } )
        self.eyelash3.append( {'x':self.x - 0.08*self.size , 'y':self.y - 0.568*self.size } )
        self.eyelash4.append( {'x':self.x + 0.2*self.size , 'y':self.y - 0.612*self.size } )
        self.eyelash5.append( {'x':self.x + 0.32*self.size  , 'y':self.y - 0.568*self.size } )
        self.eyelash6.append( {'x':self.x + 0.08*self.size , 'y':self.y - 0.568*self.size } )

        # Move bubbles
        i = len(self.bubbles) - 1
        while i >= 0:
            b = self.bubbles[i]
            if b['y'] < 0:              # Delete bubbles that are off sketch
                del self.bubbles[i]
            else:
                b['y'] -= 1.5
            i = i - 1

        # periodically add a new bubble
        if random(100) < 5:
            self.bubbles.append( {'x':self.x, 'y':self.y} )

        # If gets too close to the target, reset
        if dist(self.x, self.y, self.targetx, self.targety) < 100:
            self.resetTarget()

        # If gets too close to the red spongebob, change color

        for c in creatures:
            subcreatures = [ i for i in creatures if (i is not c)]
            for d in subcreatures:
                lc = d.location()
                x = lc['x']
                y = lc['y']
                if dist(self.x, self.y, x, y) < 250:
                    self.fillcolor = color(255, 0, 0)
                else:
                    self.fillcolor = color(255, 255, 0)


    def draw(self):
        x, y, w = self.x, self.y, self.size
        clr = self.fillcolor

        # Head
        rectMode(CENTER)
        strokeWeight(2)
        stroke(0)
        fill (clr)
        rect( x, y-0.32*w, w, 1.1*w)
        strokeWeight(0)
        fill(236,212,63)
        ellipseMode(CENTER)
        ellipse( x-0.1*w, y-0.72*w, 0.12*w, 0.16*w)
        ellipse( x+0.4*w, y-0.64*w, 0.08*w, 0.088*w)
        ellipse( x-0.4*w, y+0.06*w, 0.12*w, 0.16*w)
        ellipse( x-0.28*w, y+0.1*w, 0.08*w, 0.08*w)
        ellipse( x+0.4*w, y, 0.1*w, 0.14*w)

        # Eyes
        strokeWeight(2)
        stroke(0)
        fill(255)
        ellipse( x-0.2*w, y-0.4*w, 0.4*w, 0.42*w)
        ellipse( x+0.2*w, y-0.4*w, 0.4*w, 0.42*w)

        # Eyeballs
        fill(0)
        ellipse( x-0.19*w, y-0.4*w, 0.14*w, 0.16*w)
        ellipse( x+0.19*w, y-0.4*w, 0.14*w, 0.16*w)

        # Nose
        strokeWeight(2)
        stroke(0)
        fill(clr)
        rads = radians(180)
        arc( x, y-0.16*w, 0.16*w, abs(self.x-self.y), rads, 2*rads)

        # Cheeks
        arc( x-0.34*w, y-0.16*w, 0.22*w, 0.22*w, PI, 2*PI)
        arc( x+0.34*w, y-0.16*w, 0.22*w, 0.22*w, PI, 2*PI)
        strokeWeight(0)
        fill( 255, 0, 0)
        ellipse( x-0.38*w, y-0.18*w, 0.04*w, 0.04*w)
        ellipse( x-0.3*w, y-0.18*w, 0.04*w, 0.04*w)
        ellipse( x-0.34*w, y-0.14*w, 0.04*w, 0.04*w)
        ellipse( x+0.38*w, y-0.18*w, 0.04*w, 0.04*w)
        ellipse( x+0.3*w, y-0.18*w, 0.04*w, 0.04*w)
        ellipse( x+0.34*w, y-0.14*w, 0.04*w, 0.04*w)

        # Mouth
        strokeWeight(2)
        line( x-0.36*w, y-0.04*w, x+0.36*w, y-0.04*w)
        strokeWeight(2)
        fill(255)
        quad( x-0.1*w, y-0.04*w, x-0.112*w, y+0.08*w, x, y+0.08*w, x, y-0.04*w)
        quad( x+0.1*w, y-0.04*w, x+0.112*w, y+0.08*w, x, y+0.08*w, x, y-0.04*w)

        # Draw eyelashes
        for h in [self.eyelash1, self.eyelash2, self.eyelash3, self.eyelash4, self.eyelash5, self.eyelash6 ]:
            for i in range(1, len(h)):
                line( h[i-1]['x'], h[i-1]['y'], h[i]['x'], h[i]['y'] )

        # Draw Bubbles
        for p in self.bubbles:
            strokeWeight(0.5)
            fill(255, 102, 178, 90)
            stroke(120)
            ellipse(p['x'], p['y'], 30, 30)

# ------------------
class Kmatsuguch(Creature):

    def __init__ (self, size):
        Creature.__init__(self, size)

        # Construct the class
        self.x = random(width()- 2*self.size)
        self.y = random(height()- self.size)
        # Creature velocity and acceleration
        self.vx, self.vy = 1.0, 1.0
        self.ax, self.ay = 0.0, 0.0
        # Creature color
        self.r = random(225)
        self.g = random(225)
        self.b = random(225)
        # Randomly generated target position
        self.resetTarget()
        # Lists for tentacles strand points
        self.hair1 = []
        self.hair2 = []
        self.hair3 = []
        self.hair4 = []
        self.hair5 = []
        self.hair6 = []
        for i in range(100):
            self.hair1.append( {'x':self.x - 0.5*self.size , 'y':self.y } )
            self.hair2.append( {'x':self.x - 0.3*self.size , 'y':self.y } )
            self.hair3.append( {'x':self.x - 0.1*self.size , 'y':self.y } )
            self.hair4.append( {'x':self.x + 0.1*self.size , 'y':self.y } )
            self.hair5.append( {'x':self.x + 0.3*self.size , 'y':self.y } )
            self.hair6.append( {'x':self.x + 0.5*self.size , 'y':self.y } )

    def resetTarget(self):
    # Randomly change the fish target point
        self.targetX = random(self.size, width()-self.size)
        self.targetY = random(self.size, height()-self.size)

    def move(self):
        # Accelerate creature toward random target position
        self.ax = 0.0001*(self.targetX-self.x);
        self.ay = 0.0001*(self.targetY-self.y);

        # Change velocity to reflect acceleration
        self.vx += self.ax;
        self.vy += self.ay;

        # The creature can only swim so fast in any direction
        self.vx = constrain(self.vx, -0.5, 0.5);
        self.vy = constrain(self.vy, -0.5, 0.5);

        # Change position to reflect velocity
        self.x += self.vx;
        self.y += self.vy;

        if dist(self.x, self.y, mouseX(), mouseY()) < 30:
            self.resetTarget

        # Update  tentacles strands
        del self.hair1[0]
        del self.hair2[0]
        del self.hair3[0]
        del self.hair4[0]
        del self.hair5[0]
        del self.hair6[0]
        self.hair1.append( {'x':self.x - 0.5*self.size , 'y':self.y } )
        self.hair2.append( {'x':self.x - 0.3*self.size , 'y':self.y } )
        self.hair3.append( {'x':self.x - 0.1*self.size , 'y':self.y } )
        self.hair4.append( {'x':self.x + 0.1*self.size , 'y':self.y } )
        self.hair5.append( {'x':self.x + 0.3*self.size , 'y':self.y } )
        self.hair6.append( {'x':self.x + 0.5*self.size , 'y':self.y } )

    def draw(self):
        # Draw a jellyfish
        stroke(self.r, self.g, self.b)
        fill(self.r, self.g, self.b)
        ellipseMode(CENTER)
        arc(self.x, self.y, 2*self.size, self.size, radians(-180), 0)
        # Draw tentacles
        stroke( self.r, self.g, self.b)
        for h in [ self.hair1, self.hair2, self.hair3, self.hair4, self.hair5, self.hair6 ]:
            for i in range(1, len(h)):
                line( h[i-1]['x'], h[i-1]['y'], h[i]['x'], h[i]['y'] )

# -------------------
class Nrahman01(Creature):

    def __init__(self, size):
        Creature.__init__(self, size)

        # Creature velocity and acceleration
        self.vx, self.vy = 1.0, 1.0
        self.ax, self.ay = 0.0, 0.0

        # Randomly generated target position
        self.resetTarget()

        # List to hold bubble locations
        self.bubbles = []

    def resetTarget(self):
        # Randomly change the fish target point
        self.targetx = random(self.size, width()-self.size)
        self.targety = random(self.size, height()-self.size)

    def move(self):
        # Accelerate creature toward random target position
        self.ax = 0.0001*(self.targetx-self.x);
        self.ay = 0.0001*(self.targety-self.y);                         

        # Change velocity to reflect acceleration
        self.vx += self.ax;
        self.vy += self.ay;

        # The creature can only swim so fast in any direction
        self.vx = constrain(self.vx, -0.5, 0.5);
        self.vy = constrain(self.vy, -0.5, 0.5);

        # Change position to reflect velocity
        self.x += self.vx;
        self.y += self.vy;

        # Move bubbles
        i = len(self.bubbles) - 1
        while i >= 0:
            b = self.bubbles[i]
            if b['y'] < 0:
                del self.bubbles[i]
            else:
                b['y'] -= 1.5
            i = i - 1

        # periodically add a new bubble
        if random(100) < 4:
            self.bubbles.append( {'x':self.x, 'y':self.y} )

        # If gets too close to the target, reset
        if dist(self.x, self.y, self.targetx, self.targety) < 200:
            self.resetTarget()

    def draw(self):
        x, y, s = self.x, self.y, self.size

        # Side Fins
        fill( 202, 204, 0 )
        stroke( 255, 212, 0 )
        strokeWeight(2)
        ellipse( x+0.12*s, y-0.6*s, 0.7*s, 0.7*s )
        ellipse( x+0.12*s, y+0.6*s, 0.7*s, 0.7*s )

        # Creature outline
        fill( 202, 204, 0 )
        stroke( 255, 212, 0 )
        strokeWeight(2)
        ellipse( x, y, 2.0*s, s )

        # Smile
        fill( 255, 62, 24 )
        stroke( 255, 105, 30 )
        strokeWeight(2)
        #noStroke()
        ellipse( x-0.85*s, y+0.15*s, 0.3*s, 0.25*s )

        # Eye
        noStroke()
        fill( 255, 255, 255 )
        ellipse( x-0.725*s, y-0.125*s, 0.25*s, 0.25*s )
        fill( 0, 0, 0 )
        ellipse( x-0.75*s, y-0.1*s, 0.175*s, 0.175*s )

        # Pattern
        fill ( 255, 0, 237 )
        stroke( 255, 212, 0 )
        strokeWeight(1)
        ellipse( x+0.125*s, y+0.275*s, 0.25*s, 0.25*s )
        ellipse( x+0.5*s, y-0.25*s, 0.175*s, 0.175*s )
        ellipse( x+0.55*s, y+0.15*s, 0.2*s, 0.2*s )
        ellipse( x-0.3*s, y-0.15*s, 0.2*s, 0.2*s )
        fill ( 87, 103, 198 )
        ellipse( x+0.785*s, y-0.1*s, 0.175*s, 0.175*s )
        ellipse( x-0.255*s, y+0.165*s, 0.225*s, 0.225*s )
        ellipse( x+0.25*s, y, 0.2*s, 0.2*s )
        ellipse( x+0.05*s, y-0.3*s, 0.225*s, 0.225*s )

        # Draw bubbles
        for p in self.bubbles:
            fill(255)
            stroke(127)
            ellipse(p['x']-0.85*s, p['y']+0.15*s, 0.25*s, 0.25*s)

# ------------------
class Mrowe(Creature):

    def __init__(self, size):
        Creature.__init__(self, size)

        #Create color change depending on distance
        self.fillColor = color(178,102,255)

        #Create fin movement
        self.time = 0.0
        self.finscale = 1.0

        # Creature velocity and acceleration
        self.vx, self.vy = 1.0, 1.0
        self.ax, self.ay = 0.0, 0.0

        # Randomly generated target position
        self.resetTarget()

    def resetTarget(self):
        # Randomly change the fish target point
        self.targetx = random(self.size, width()-self.size)
        self.targety = random(self.size, height()-self.size)

    def move(self):

        self.time = self.time + 0.2
        self.finscale = math.sin (self.time+1.7) + 0.5
        self.finscale2 = math.sin (self.time+1.3) + 0.5
        self.finscale3 = math.sin (self.time+2) + 0.5
        self.finscale4 = math.sin (self.time+1.5) + 0.5
        self.finscale5 = math.sin (self.time+1.7) + 0.5

        # Accelerate creature toward random target position
        self.ax = 0.0001*(self.targetx-self.x);
        self.ay = 0.0001*(self.targety-self.y);

        # Change velocity to reflect acceleration
        self.vx += self.ax;
        self.vy += self.ay;

        # The creature can only swim so fast in any direction
        self.vx = constrain(self.vx, -0.5, 0.5);
        self.vy = constrain(self.vy, -0.5, 0.5);

        # Change position to reflect velocity
        self.x += self.vx;
        self.y += self.vy;

        # If gets too close to the target, reset
        if dist(self.x, self.y, self.targetx, self.targety) < 100:
            self.resetTarget()

        for c in creatures:
            if c is not self:
                #l = c.location()
                cx = c.x
                cy = c.y
                d = dist(self.x, self.y, cx, cy)

                if ( d > 50 and d < 100):
                    self.fillColor = color(153,51,255)

                elif ( d < 50 ):
                    self.fillColor = color (204,153,255,128)
                else:
                    self.fillColor = color(76,0,153)

    def draw(self):
        x, y, s = self.x, self.y, self.size

        # Body of puffer
        stroke(0,0,153)
        fill(self.fillColor)
        ellipse(x, y, s*1.3, s)

        # Tail
        noStroke ()
        fill(self.fillColor)
        triangle(x-1*s, y+0.2*s, x-1*s, y-0.2*s,x-0.2*s, y)
        fill(self.fillColor)
        line (x-0.9*s, y, x-0.5*s,y)

        # Mouth
        fill(self.fillColor)
        triangle(x+0.7*s, y+0.09*s, x+0.7*s, y-0.09*s,x+0.5*s, y)

        fill (102,51,0)
        noStroke()

        strokeWeight (2)
        stroke(153,153,255)

        #Tail fin to make fish seem like it's moving
        pushMatrix ()
        translate (x-0.8*s, y)
        pushMatrix()
        scale (self.finscale)
        line (-0.1*s, 0, 0, 0)

        popMatrix()
        pushMatrix()
        scale (self.finscale2)
        line (-0.1*s, -0.1*s, 0, 0)

        popMatrix ()
        pushMatrix()
        scale (self.finscale3)
        line (-0.1*s, 0.1*s, 0, 0)
        popMatrix ()

        pushMatrix ()
        scale (self.finscale4)
        line (-0.1*s, -0.05*s, 0, 0)
        popMatrix ()

        pushMatrix ()
        scale (self.finscale5)
        line (-0.1*s, 0.05*s, 0, 0)
        popMatrix ()
        popMatrix ()

        #Side fin to make fish look like it's swimming
        strokeWeight (2)
        stroke(153,153,255)

        pushMatrix ()
        translate (x+0.1*s, y+0.05*s)
        rotate (radians (300))
        pushMatrix()
        scale (self.finscale)
        line (-0.1*s, 0, 0, 0)

        popMatrix()
        pushMatrix()
        scale (self.finscale2)
        line (-0.1*s, -0.1*s, 0, 0)

        popMatrix ()
        pushMatrix()
        scale (self.finscale3)
        line (-0.1*s, 0.1*s, 0, 0)
        popMatrix ()

        pushMatrix ()
        scale (self.finscale4)
        line (-0.1*s, -0.05*s, 0, 0)
        popMatrix ()

        pushMatrix ()
        scale (self.finscale5)
        line (-0.1*s, 0.05*s, 0, 0)
        popMatrix ()
        popMatrix ()


        # Eye of puffer
        strokeWeight(1)
        stroke(0,0,153)
        fill (229,204,255)
        ellipse(x+0.4*s, y-0.1*s, 0.3*s, 0.3*s)
        fill(0,0,153)
        noStroke()
        ellipse(x+0.4*s, y-0.1*s, 0.18*s, 0.18*s)

# ------------------
class Rshahab(Creature):
    def __init__(self, size):
        Creature.__init__(self, size)

         # Creature velocity and acceleration
        self.vx, self.vy = 1.0, 1.0
        self.ax, self.ay = 0.2, 0.2

        # Randomly generated target position
        self.resetTarget()

    def resetTarget(self):
        # Randomly change the fish target point
        self.targetx = random(self.size, width()-self.size)
        self.targety = random(self.size, height()-self.size)

    def move(self):
        # Accelerate creature toward random target position
        self.ax = 0.0001*(self.targetx-self.x);
        self.ay = 0.0001*(self.targety-self.y);

        # Change velocity to reflect acceleration
        self.vx += self.ax;
        self.vy += self.ay;
        # The creature can only swim so fast in any direction
        self.vx = constrain(self.vx, -0.7, 0.7);
        self.vy = constrain(self.vy, -0.5, 0.5);

        # Change position to reflect velocity
        self.x += self.vx;
        self.y += self.vy;

         # If gets too close to the target, reset
        if dist(self.x, self.y, self.targetx, self.targety) < 100:
            self.resetTarget()

    def draw(self):
        x, y, s = self.x, self.y, self.size

        #poptart
        fill(232, 192, 49)
        quad(x+100, y+75, x+200, y+75, x+200, y+144, x+100, y+144)
        #frosting
        if y >= 10 and y < 150:
            fill(224, 62, 181)
        elif y > 150 and y < 350:
            fill(140, 0, 132)
        elif y > 350 and y < 600:
            fill(8, 162, 209)
        else:
            fill(239, 137, 12)
        quad(x+110, y+85, x+190, y+85, x+190, y+135, x+110, y+135)
        #sprinkles
        if x >= 50 and x <= 199:
            fill(102, 237, 12)
        elif x >= 200 and x < 400:
            fill(32, 32, 241)
        elif x >= 500 and x <= 800:
            fill(203, 26, 17)
        else:
            fill(166, 0, 152)
        ellipse(x+120, y+90, 6, 6)
        ellipse(x+140, y+100, 0.1*s, 0.1*s)
        ellipse(x+145, y+110, 6, 6)
        ellipse(x+155, y+100, 0.1*s, 0.1*s)
        ellipse(x+170, y+105, 0.1*s, 0.1*s)
        ellipse(x+180, y+115, 6, 6)
        ellipse(x+180, y+90, 6, 6)
        ellipse(x+150, y+130, 0.1*s, 0.1*s)
        ellipse(x+160, y+125, 0.1*s, 0.1*s)
        ellipse(x+175, y+128, 6, 6)

        #Head
        fill(128)
        ellipse(x+110, y+120, 70, 50)
        #Left eye
        fill(255, 255, 255)
        ellipse(x+95, y+120 , 18, 13)
        fill(random(255, 255))
        fill(0)
        ellipse(x+95,y+120 , 3, 8)
        #Right eye
        fill(255, 255, 255)
        ellipse(x+125,y+120 , 18, 13)
        fill(random(255, 255))
        fill(0)
        ellipse(x+125,y+120 , 3, 8)
        #Ears
        fill(128)
        triangle(x+120, y+100, x+140, y+110, x+140, y+90)
        triangle(x+100, y+100, x+80, y+110, x+80, y+90)
        #Inner Ear
        fill(242, 77, 198)
        triangle(x+122, y+102, x+137, y+95, x+136, y+109)
        triangle(x+98, y+102, x+85, y+95, x+84, y+109)
        #Mouth
        fill(241, 107, 243)
        ellipse(x+110, y+127 , 5, 5)
        stroke(2)
        fill(0)
        line(x+110, y+130, x+110, y+135)
        noFill()
        arc(x+110, y+131, 15, 10, 0, radians(180))

# ------------------
class Rshaheen(Creature):

    def __init__(self, size):
        Creature.__init__(self, size)

        # Creature velocity and acceleration
        self.vx, self.vy = 1.0, 1.0
        self.ax, self.ay = 0.0, 0.0

        # Randomly generated target position
        self.resetTarget()

        # List to hold bubble locations
        self.bubbles = []


    def resetTarget(self):
        # Randomly change the fish target point
        self.targetx = random(self.size, width()-self.size)
        self.targety = random(self.size, height()-self.size)

    def move(self):
        # Accelerate creature toward random target position
        self.ax = 0.0001*(self.targetx-self.x);
        self.ay = 0.0001*(self.targety-self.y);

        # Change velocity to reflect acceleration
        self.vx += self.ax;
        self.vy += self.ay;

        # The creature can only swim so fast in any direction
        self.vx = constrain(self.vx, -0.5, 0.5);
        self.vy = constrain(self.vy, -0.5, 0.5);

        # Change position to reflect velocity
        self.x += self.vx;
        self.y += self.vy;


        # Move bubbles
        i = len(self.bubbles) - 1
        while i >= 0:
            b = self.bubbles[i]
            if b['y'] < 0:              # Delete bubbles that are off sketch
                del self.bubbles[i]
            else:
                b['y'] -= 2.5
            i = i - 1

        # periodically add a new bubble
        if random(100) < 5:
            self.bubbles.append( {'x':self.x, 'y':self.y} )

        # If gets too close to the target, reset
        if dist(self.x, self.y, self.targetx, self.targety) < 100:
            self.resetTarget()

    def draw(self):
        rectMode(CORNER)
        x, y, s = self.x, self.y, self.size

        # Face
        stroke(189, 183, 107)
        fill(255,225, 0)
        rect(x-50, y-50, s, s+40)

        #Sponge Spots
        fill (189, 183, 107, 190)
        ellipse (x+20, y+60, s/6, s/15)
        ellipse (x-30, y+40, s/8, s/10)
        ellipse (x+20, y-40, s/10, s/10)
        ellipse (x-20, y-40, s/7, s/10)
        ellipse (x-15, y+65, s/10, s/10)

        # Eyes
        fill(255)
        stroke(0)
        ellipse(x-0.24*s, y-0.2*s, 0.45*s, 0.45*s)
        ellipse(x+0.24*s, y-0.2*s, 0.45*s, 0.45*s)
        fill (135, 206, 250)
        ellipse(x-0.18*s, y-0.2*s, 0.2*s, 0.2*s)
        ellipse(x+0.18*s, y-0.2*s, 0.2*s, 0.2*s)
        fill(0)
        noStroke()
        ellipse(x-0.18*s, y-0.2*s, 0.1*s, 0.1*s)
        ellipse(x+0.18*s, y-0.2*s, 0.1*s, 0.1*s)


        # Cheeks
        stroke(189, 183, 107)
        fill(255,225, 0)
        ellipse(x-0.3*s, y+0.15*s, s/4, s/4)
        ellipse(x+0.3*s, y+0.15*s, s/4, s/4)

        # Smile
        stroke(0)
        fill(255)
        arc(x, y+10, s/1.4, s/1.5, 0, radians(180))
        stroke(0)
        fill(255, 255, 0)
        arc(x, y+10, s/1.4, s/5, 0, radians(180))

        #Tongue
        stroke(0)
        fill (255, 192, 203)
        arc(x, y+39, s/2, s/3, 280, radians(340))

        #Nose
        stroke(0)
        fill (255,225, 0)
        ellipse (x, y, s/7, s/7)


        # Draw bubbles
        for p in self.bubbles:
            fill(0, 0, 0, 20)
            stroke(127)
            ellipse(p['x'], p['y'], 20, 20)

# ------------------
class Nsoohoo(Creature):
    def __init__(self, size):
        Creature.__init__(self, size)
        self.angle = 0.0
        self.bubbles = []

    def move(self):
        #rotation
        self.angle = self.angle + 0.05
        
        #bubbles
        i = len(self.bubbles) - 1
        while i >= 0:
            b = self.bubbles[i]
            if b['y'] < 0:
                del self.bubbles[i]
            else:
                b['y'] -= 1.5
            i = i - 1
        if random(100) < 3:
            self.bubbles.append( {'x':self.x+(self.size/2.5), 'y':self.y} )

    def draw(self):
        pushMatrix()
        translate(self.x, self.y)
        rotate(self.angle)
        #tail
        fill(0, 255, 0)
        beginShape()
        vertex(0-(self.size/3.5), 0-(self.size/5))
        curveVertex(0-(self.size/1.5), 0-(self.size/3))
        curveVertex(0-((self.size/3)+(self.size/4)), 0)
        curveVertex(0-(self.size/1.5), 0+(self.size/3))
        vertex(0-(self.size/3.5), 0+(self.size/5))
        endShape()
        #body
        fill(255, 255, 0)
        ellipse(0, 0, self.size, self.size/1.3)
        #fins
        fill(0, 255, 0)
        triangle(0-8, 0-(self.size/2.6)+1, 0, 0-(self.size/2.6)-9, 0+8, 0-(self.size/2.6)+1)
        triangle(0-(self.size/6), 0-(self.size/20), 0-(self.size/3), 0+(self.size/5), 0+(self.size/14), 0+(self.size/12))
        #eye
        fill(255)
        ellipse(0+(self.size/5), 0-(self.size/7), self.size/3, self.size/3)
        fill(0)
        ellipse(0+(self.size/4), 0-(self.size/7), self.size/5, self.size/5)
        popMatrix()

        #bubbles
        for p in self.bubbles:
            fill(255)
            stroke(127)
            ellipse(p['x'], p['y'], 10, 10)

# ------------------
class kholladay(Creature):

    def __init__(self,size):
        Creature.__init__(self,size)
        self.strokeColor = color(255,0,0)
        self.fillColor = color(255, 0,0)

    def move(self):
        self.x = (self.x + 3) % width()

    # Draw the creature
    def draw(self):
        stroke(self.strokeColor)
        fill(self.fillColor)

        pushMatrix()
        translate(self.x, self.y)
        scale(self.size)
        rotate(2.3)

        #ellipse(self.x, self.y, self.size, self.size)
        ellipseMode(CENTER)
        ellipse(0, 0, 70, 70)
        ellipse(30, 30, 50, 50)
        ellipse(55, 55, 40, 40)
        ellipse(75, 75, 30, 30)
        ellipse(90, 90, 20, 20)

        #Tail
        stroke(self.strokeColor)
        ellipseMode(CENTER)
        ellipse(120,100,80,50)
        ellipse(100,120,50,80)

        #Eyes
        fill(255)
        ellipse(  0, -25, 20, 20)
        ellipse(-25,  -5, 20, 20)

        fill(0)
        ellipse(  0, -25, 5, 5)
        ellipse(-25,  -5, 5, 5)

        if self.x <150:
            fill(255,0,0)
            ellipse(  0, -25, 20, 20)
            ellipse(-25,  -5, 20, 20)

        #Claws
        strokeWeight(0)
        fill(255,0,0)
        arc(10,60,30,50,190,radians(45))
        pushMatrix()
        rotate( radians(295))
        arc(10,60,30,50,190,radians(45))
        popMatrix()
        popMatrix()

# ------------------
class Raalexis(Creature):

    def __init__(self, size):
        Creature.__init__(self, size)
        self.angle=0

# Creature velocity and acceleration
        self.vx, self.vy = 1.0, 1.0
        self.ax, self.ay = 0.0, 0.0

        # Randomly generated target position
        #self.resetTarget()
    def draw(self):
        self.x=(self.x+2)% width()
        w, h = width(), height()
        r=self.size
        self.angle=self.angle+0.05

        if self.x > 0.5*w:
            if self.y > 0.5*h:
                fill(255, 0, 0)
            else:
                fill(0, 0, 250)
        elif self.x <= 0.5*w:
            if self.y > 0.5*h:
                fill(255, 255, 0)
            else:
                fill(0, 255, 0)
        ellipse(self.x, self.y, 2*r, 2*r)
        pushMatrix ()
        translate (self.x, self.y)
        rotate (self.angle)
        ellipse(0,0, 3*r, 1.5*r)
        popMatrix ()
        ellipse(self.x, self.y, 2.2*r, 1.1*r)

        fill(0)
        r2 = 0.3*r
        r3 = 0.1*r
        ellipse(self.x - r2, self.y - r2, r3, r3)
        ellipse(self.x + r2, self.y - r2, r3, r3)
        ellipse(self.x + r2, self.y - r2, r3, r3)
        #noFill()
        fill(0,0,0)
        arc(self.x, self.y, r, r, 0, PI/2)


# ------------------
# List of all creatures
creatures = []
creatures.append( sberrettin(0.25) )
creatures.append( egulley(40) )
creatures.append( Thamid(140) )
creatures.append( rdhamilton( 1 ) )
creatures.append( Yhuang(0.5) )
creatures.append( Kirick(35) )
creatures.append( Kkury(80 ))
creatures.append( Yli04(100) )
creatures.append( Kmatsuguch(60) )
creatures.append( Nrahman01(50) )
creatures.append( Mrowe(80) )
creatures.append( Rshahab(50) )
creatures.append( Rshaheen(100) )
creatures.append( Nsoohoo(60) )
creatures.append( kholladay(0.7) )
creatures.append( Raalexis(40) )

# ------------------
# Create sketch window
window(800, 600)

# Draw all creatures
backImage = loadImage("underwater.jpg")

# Draw all creatures
def draw(o, e):
    # Draw the tank background
    image(backImage, 0, 0)

    # Draw and animate each of the creature objects
    for c in creatures:
        c.move()
        c.draw()

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