> show canvas only <


/* built with Studio Sketchpad: 
 *   http://sketchpad.cc
 * 
 * observe the evolution of this sketch: 
 *   http://studio.sketchpad.cc/sp/pad/view/ro.CgRtvYqJL2c/rev.2
 * 
 * authors: 
 *   GoToLoop

 * license (unless otherwise specified): 
 *   creative commons attribution-share alike 3.0 license.
 *   http://creativecommons.org/licenses/by-sa/3.0/ 
 */ 



/**
 * Bouncing Angry Bird (2.75)
 * by ani_abd (2013/Mar)
 * mod GoToLoop
 *
 * http://forum.processing.org/topic/wanna-change-direction-with-keypressed
 */

final static short w  = 0200, h = 0170;
//final static short ww = w >> 1, hh = h >> 1;
PImage imgBG, imgBird = createImage(w, h, ARGB);

final static color BG = 0;

final static byte  sp = 4;
byte  spd = sp;
int   incX = spd, incY = spd;

final static short opac = 0xFF, opacMax = 0xFF;
final static byte  opacStep = 5, opacMin = 0;
short x, y, opacity = opac;

void setup() {
  size(640, 480);
  smooth();
  frameRate(50);
  imageMode(CORNER);

  // Places imgBird's at a random position:
  x = (short) random(width  - w);
  y = (short) random(height - h);

  // Loads background image:
  //imgBG = loadImage("G1.jpg");
  //imgBG.resize(width, height);

  // Draws bird in the canvas:
  prepareCanvas();
  drawBird(280, 272, 200, 20, 20);

  // Copies PGraphics g to PImage imgBird:
  imgBird.copy(get(), 0, 0, w, h, 0, 0, w, h);
}

void draw() {
  // Clears canvas:
  background(BG);
  //background(imgBG);

  // Moves & checks canvas' limits for bird:
  birdUpdate();

  // Displays imgBird:
  int sig = signum(incX); // returns either -1 or 1 for incX
  scale(sig, 1);          // horizontal flip if incX < 0
  image(imgBird, x*sig + w*(sig >> 1), y);

  //frame.setTitle
  //  ("Angry Birds  ---  FPS: " + round(frameRate) + 
  //  "  ---  Spd: " + spd + "  ---  Opac: " + opacity);
}

void keyPressed() {
  switch (keyCode) {

  case LEFT:
  case 'A':
    incX = -spd;
    break;

  case RIGHT:
  case 'D':
    incX = spd;
    break;

  case UP:
  case 'W':
    incY = -spd;
    break;

  case DOWN:
  case 'S':
    incY = spd;
    break;

  case ALT:
  case 'J':
    --spd;
    refreshSpeed();
    break;

  case ' ':
  case 'K':
    ++spd;
    refreshSpeed();
    break;

  case BACKSPACE:
  case 'H':
    spd = sp;
    refreshSpeed();
    break;

  case ENTER:
  case RETURN:
    if (looping)    noLoop();
    else            loop();
  }
}

void mousePressed() {
  if (mouseButton == LEFT)
    if ( (opacity -= opacStep) < opacMin)
      opacity = opacMax;

  if (mouseButton == RIGHT)
    if ((opacity += opacStep) > opacMax)
      opacity = opacMin;

  if (mouseButton == CENTER)    opacity = opac;

  tint(0xFF, opacity);
}

void prepareCanvas() {
  // Loads canvas' PGraphics g into pixels[]:
  loadPixels();

  // Makes PGraphics g 100% transparent black:
  for (int i = pixels.length; i != 0; pixels[--i] = 0);
  //Arrays.fill(pixels, 0);
  updatePixels();
}

void birdUpdate() {
  if ( (x += incX) < 0 | x > width  - w )   incX *= -1;
  if ( (y += incY) < 0 | y > height - h )   incY *= -1;
}

void refreshSpeed() {
  incX = spd * signum(incX);
  incY = spd * signum(incY);
}

final static int signum(int n) {
  // returns either -1 or 1:
  return n >> 31 | 1;
}

void drawBird(int x, int y, 
color R, color G, color B) {

  //tail
  noStroke();
  fill(R, G, B);
  quad(x-210, y-210, x-270, y-197, x-265, y-210, x-220, y-190);
  quad(x-190, y-212, x-275, y-192, x-277, y-182, x-200, y-212);
  quad(x-190, y-220, x-265, y-183, x-260, y-175, x-195, y-220);

  //head
  stroke(0);
  strokeWeight(3);
  fill(R, G, B);
  beginShape();

  curveVertex(x-300, y-200);
  curveVertex(x-190, y-240);
  curveVertex(x-250, y-250);
  curveVertex(x-100, y-100);

  endShape(CLOSE);

  beginShape();

  curveVertex(x-300, y-230);
  curveVertex(x-200, y-240);
  curveVertex(x-235, y-265);
  curveVertex(x-300, y-110);

  endShape(CLOSE);

  ellipse(x-205, y-205, 100, 100);

  //dark dots on the body
  noStroke();
  fill(R-33, G-6, G-6);
  ellipse(x-210, y-205, 20, 30);
  ellipse(x-168, y-200, 20, 30);
  ellipse(x-225, y-195, 10, 20);
  ellipse(x-235, y-185, 10, 10);

  //tan part on the body
  fill(R+34, G+166, B+117);
  arc(x-195, y-153, 80, 80, radians(192), radians(328));
  noFill();
  stroke(0);
  ellipse(x-205, y-205, 100, 100);
  noStroke();
  fill(R, G, B);
  rect(x-230, y-256, 27, 20);

  //left eye
  stroke(0);
  fill(-1);
  ellipse(x-195, y-204, 23, 23);
  fill(0);
  ellipse(x-191, y-204, 5, 5);

  //left eyebrow
  quad(x-185, y-215, x-215, y-220, x-215, y-213, x-185, y-210);

  //right eye
  fill(-1);
  ellipse(x-173, y-204, 23, 23);

  fill(0);
  ellipse(x-178, y-204, 5, 5);

  //right eyebrow
  quad(x-185, y-215, x-160, y-220, x-160, y-213, x-185, y-210);

  //beak
  fill(R+55, G+176, B-20);
  strokeWeight(2);
  stroke(0);
  triangle(x-185, y-170, x-170, y-185, x-200, y-185);

  fill(R+55, G+200, B-20);

  beginShape();

  curveVertex(x-140, y-20);
  curveVertex(x-165, y-185);
  curveVertex(x-205, y-185);
  curveVertex(x-200, y-185);
  curveVertex(x-200, y-185);
  curveVertex(x-220, y-185);

  endShape(CLOSE);

  noStroke();
  fill(R+34, G+166, B+117);
  rect(x-210, y-190, 10, 10);
}