Your browser does not support the canvas tag.

previous        Show / Hide Source        Download        next
/*
Object-Oriented Toy: Lineye
 by Tom Kun 21/10/2016
 A toy of clicking blocks in two different columns of 7 blocks
 in order to attack the flowing eye with the line 
 which connects those two blocks
 
 The concept is about line and columns, color effects catching the flow(eye).
 Met 4+ problems while creating, like how to create the color blending blocks etc.
 */

//initializes
Eye boss;
Shooter[] shooters= new Shooter [14]; 
boolean fActive=false;
boolean lActive=false;
int l1Y=0;
int l2Y=0;
color lineSkin;
boolean done=false;
boolean damageDone=false;

//setup and put value
void setup() {
  noCursor();
  size(800, 600);
  boss= new Eye(400, 300);
  for (int i=0; i<14; i=i+2) {
    shooters[i] = new Shooter(80, 40+i*40, color(i*50, i*20, i*10));
  }
  for (int i=1; i<14; i=i+2) {
    shooters[i] = new Shooter(685, i*40, color(i*10, i*20, i*40));
  }

  println(shooters[0].shooterX);
  println(shooters[1].shooterX);
}

// display and update
void draw() {
  //update
  frameRate(50);
  noStroke();
  //using function of Eye class
  boss.EyeMovement();
  //loop for detecting 
  // left column(plural i)
  for (int i=-2; i<14; i=i+2) {
    if (mouseX>80) {
      if (mouseX<115) {
        if (mouseY>40+40*i) {
          if (mouseY>40+40*i+40) {
            if (mousePressed) {
              fActive=true;
              l1Y=40+i*40;
              // color blending factor
              lineSkin=color(i*50, i*20, i*10);
            }
          }
        }
      }
    }
  }
  // right column(single i)
  for (int i=1; i<14; i=i+2) {
    if (mouseX>685) {
      if (mouseX<715) {
        if (mouseY>40*i) {
          if (mouseY<40+40*i) {
            if (mousePressed) {
              lActive=true;
              l2Y=i*40;
              //color blending factor
              lineSkin=color (i*10, i*20, i*40);
            }
          }
        }
      }
    }
  }

  //display
  background(#D7DF23);
  //decoration
  fill(#fff100);
  rect(200, 0, 400, 400);
  rect(200, 300, 50, 400);
  fill(#f05a2e);
  rect(200, 330, 405, 400);
  // moving shades
  fill(#fff100, 20);
  rect(220, 300, 20, 400+sin(frameCount/10)*500);
  rect(500, 300, 20, 40+sin(frameCount/10)*50);
  rect(440, 410, 20, 10+sin(frameCount/10)*50);
  rect(550, 430, 20, 100+sin(frameCount/10)*50);
  rect(400, 420, 20, 60+sin(frameCount/10)*50);
  rect(300, 430, 20, 60+sin(frameCount/10)*50);
  rect(460, 440, 20, 200+sin(frameCount/10)*50);
  rect(500, 450, 20, 60+sin(frameCount/10)*50);
  //orange blocks texture
  fill(#f05a2e);
  rect(585, 0, 20, 400);
  rect(500, 0, 20, 40);
  rect(440, 0, 20, 10);
  rect(440, 30, 20, 100);
  rect(400, 0, 20, 60);
  rect(300, 0, 20, 60);
  rect(250, 0, 20, 200);
  rect(210, 0, 20, 60);

  // shooting line, checking conditions
  if (fActive==true) {
    if (lActive==true) {
      stroke(lineSkin);
      strokeWeight(10);
      line(shooters[2].shooterX, l1Y+80, 
        shooters[1].shooterX, l2Y );
      //refresh
      fActive=false;
      lActive=false;
      done=true;
    }
  }
  // display the class objects
  boss.display();
  for (int i=0; i<14; i=i+2) {
    shooters[i].display();
  }
  for (int a=1; a<14; a=a+2) {
    shooters[a].display();
  }
  //custom cursor
  fill(255);
  triangle(pmouseX, pmouseY, mouseX, 
    mouseY-10, mouseX, mouseY+10);
  ellipse(mouseX, mouseY, 20, 20);
  // using the boolean for circile line intersection
  if (circleLineIntersect(float(shooters[2].shooterX), float(l1Y), float(shooters[1].shooterX), float(l2Y), float(boss.eyeX), float(boss.eyeY), 150)==true) {

    fill(255, 0, 100, 255*90/100);  
    ellipse(float(boss.eyeX), float(boss.eyeY), 150, 150);
    frameRate(5);
    l1Y=-10000;
    l2Y=-10000;
    frameRate(50);
  }
}

// Reference:  https://www.openprocessing.org/sketch/8009#
// REAS (Casey Reas)

// Code adapted from Paul Bourke:
// http://local.wasp.uwa.edu.au/~pbourke/geometry/sphereline/raysphere.c
boolean circleLineIntersect(float x1, float y1, float x2, float y2, float cx, float cy, float cr ) {
  float dx = x2 - x1;
  float dy = y2 - y1;
  float a = dx * dx + dy * dy;
  float b = 2 * (dx * (x1 - cx) + dy * (y1 - cy));
  float c = cx * cx + cy * cy;
  c += x1 * x1 + y1 * y1;
  c -= 2 * (cx * x1 + cy * y1);
  c -= cr * cr;
  float bb4ac = b * b - 4 * a * c;
  if (bb4ac < 0) {  // Not intersecting
    return false;
  } else {

    float mu = (-b + sqrt( b*b - 4*a*c )) / (2*a);
    float ix1 = x1 + mu*(dx);
    float iy1 = y1 + mu*(dy);
    mu = (-b - sqrt(b*b - 4*a*c )) / (2*a);
    float ix2 = x1 + mu*(dx);
    float iy2 = y1 + mu*(dy);

    // The intersection points
    //ellipse(ix1, iy1, 10, 10);
    //ellipse(ix2, iy2, 10, 10);

    float testX;
    float testY;
    // Figure out which point is closer to the circle
    if (dist(x1, y1, cx, cy) < dist(x2, y2, cx, cy)) {
      testX = x2;
      testY = y2;
    } else {
      testX = x1;
      testY = y1;
    }

    if (dist(testX, testY, ix1, iy1) < dist(x1, y1, x2, y2) || dist(testX, testY, ix2, iy2) < dist(x1, y1, x2, y2)) {
      return true;
    } else {
      return false;
    }
  }
}
class Eye {
  //initializes
  int eyeX;
  int eyeY;
  int eyeVX;
  int eyeVY=1;
  int aspeed=frameCount/100;
  color eyeC;
  boolean goingDown=true;
  boolean goingUp=false;
  PVector eyeLocation = new PVector(eyeX, eyeY);
  PVector eyeVelocity = new PVector(eyeVX, eyeVY);

  //constructor
  Eye(int TeyeX, int TeyeY) {
    eyeX=TeyeX;
    eyeY=TeyeY;
  }
  //show
  void display() {
    //eye
    noStroke();
    fill(#d5de26);
    ellipse(eyeX, eyeY, 150, 150);
    fill(#00A651);
    ellipse(eyeX, eyeY, 70, 70);
    fill(#495a52);
    ellipse(eyeX, eyeY, 40, 40);
    fill(#FFF200, 255*mouseX/800);
    ellipse(eyeX+30, eyeY-30, 50, 50);
    fill(#F15A29, 255*mouseY/600);
    ellipse(eyeX-30, eyeY+30, 40, 40);
    //upper blocks decoration
    fill(255, 255*0.9);
    rect(eyeX-50, eyeY-200, 20, 50);
    rect(eyeX-10, eyeY-250-sin(frameCount/10)*30, 30, 100+sin(frameCount/10)*30);
    rect(eyeX+30, eyeY-200, 20, 50);
    rect(eyeX-50, eyeY-150, 100, 100);
    //lower blocks decoration
    rect(eyeX-50, eyeY+50, 20, 50);
    rect(eyeX-14, eyeY+80, 30, 100+sin(frameCount/10)*30);
    rect(eyeX+30, eyeY+50, 20, 50);
    rect(eyeX-50, eyeY+50, 100, 100);
  }
  // motion update
  void EyeMovement() {
  // go up and set up border
    if (goingUp==true) {
      goingDown=false;
      eyeY=eyeY-eyeVY;
      if (eyeY<100) {
        goingUp=false;
        goingDown=true;
      }
    }
  // go down and set up border
    if (goingDown==true) {
      goingUp=false;
      eyeY=eyeY+eyeVY;
      if (eyeY>500) {
        goingUp=true;
        goingDown=false;
      }
    }
  }
}
class Shooter {
  //initializes
  boolean isActive;
  int shooterX;
  int shooterY;
  color shooterSkin;
  color laserSkin;
  boolean MouseOver=false;
  boolean MClicked=false;
  PVector ShooterLocation= new PVector(shooterX, shooterY);
  
  //constructor
  Shooter(int TshooterX, int TshooterY, color TshooterSkin) {
    shooterX=TshooterX;
    shooterY=TshooterY;
    shooterSkin=TshooterSkin;
  }
  void display() {
    //reset
    MouseOver=false;
    MClicked=false;
    //blocks react when mouse over
    if (shooterX+30>mouseX) {
      if (mouseX>shooterX) {
        if (mouseY<shooterY+40) {
          if (mouseY>shooterY) {
            MouseOver=true;
            if (mousePressed) {
              fill(shooterSkin);
              ellipse(shooterX, shooterY, 20, 20);
            }
          }
        }
      }
    }
    //draw the things when mouse over
    if (MouseOver==true) {
      fill(255);
      rect(shooterX, shooterY-sin(frameCount/12)*2, 30, 40+sin(frameCount/12)*2);
    }
    // draw the things with default animation
    else if (MouseOver==false) {
      fill(shooterSkin);
      rect(shooterX, shooterY-sin(frameCount/12)*2, 30, 40+sin(frameCount/12)*2);
    }
  }
}