aa develop

開発と成長

Processingでイージング

少し前に、fladdictさんの乱数にコクを出すという話がネットで盛り上がっていました。

乱数にコクを出す方法について - Togetterまとめ

私もかれこれ1年以上、Processingで作品を作ってきましたが、自分の作品のクオリティをもっと上げていくには、こういう細かい動きや配色にこだわっていかないのかなーと思っています。

www.openprocessing.org

そうぼんやりと思っているときに、jQueryを使う機会があり、アニメーションの動き方を設定するイージングというものを知りました。

Easing Function 早見表

Processingでも、今までだったらオブジェクトを線形に動かしていたところを、イージングで動きに変化をつけると面白いのではないかと思い、とりあえずProcessingに上の早見表に載っている30のイージングを移植してみました。

f:id:aa_debdeb:20161119165627j:plain

easing test - OpenProcessing

/*
* easing test
*/

float startX = 150;
float endX = 480;
int duration = 200;
float margin = 30;
float ellipseSize = 20;

void setup(){
  size(1000, 480);
}

void draw(){
  background(255);
  fill(60);
  stroke(60);
  text("1. easeInSine", 20, margin * 1);
  text("2. easeOutSine", 20, margin * 2);
  text("3. easeInOutSine", 20, margin * 3);
  text("4. easeInQuad", 20, margin * 4);
  text("5. easeOutQuad", 20, margin * 5);
  text("6. easeInOutQuad", 20, margin * 6);
  text("7. easeInCubic", 20, margin * 7);
  text("8. easeOutCubic", 20, margin * 8);
  text("9. easeInOutCubic", 20, margin * 9);
  text("10. easeinQuart", 20, margin * 10);
  text("11. easeOutQuart", 20, margin * 11);
  text("12. easeInOutQuart", 20, margin * 12);
  text("13. easeinQuint", 20, margin * 13);
  text("14. iaseOutQuint", 20, margin * 14);
  text("15. easeInOutQuint", 20, margin * 15);
  line(startX, 0, startX, height);
  line(endX, 0, endX, height);
  fill(128, 0, 0);
  noStroke();
  ellipse(easeInSine(frameCount % duration, startX, endX - startX, duration), margin * 1, ellipseSize, ellipseSize);
  ellipse(easeOutSine(frameCount % duration, startX, endX - startX, duration), margin * 2, ellipseSize, ellipseSize);
  ellipse(easeInOutSine(frameCount % duration, startX, endX - startX, duration), margin * 3, ellipseSize, ellipseSize);
  ellipse(easeInQuad(frameCount % duration, startX, endX - startX, duration), margin * 4, ellipseSize, ellipseSize);
  ellipse(easeOutQuad(frameCount % duration, startX, endX - startX, duration), margin * 5, ellipseSize, ellipseSize);
  ellipse(easeInOutQuad(frameCount % duration, startX, endX - startX, duration), margin * 6, ellipseSize, ellipseSize);
  ellipse(easeInCubic(frameCount % duration, startX, endX - startX, duration), margin * 7, ellipseSize, ellipseSize);
  ellipse(easeOutCubic(frameCount % duration, startX, endX - startX, duration), margin * 8, ellipseSize, ellipseSize);
  ellipse(easeInOutCubic(frameCount % duration, startX, endX - startX, duration), margin * 9, ellipseSize, ellipseSize);
  ellipse(easeInQuart(frameCount % duration, startX, endX - startX, duration), margin * 10, ellipseSize, ellipseSize);
  ellipse(easeOutQuart(frameCount % duration, startX, endX - startX, duration), margin * 11, ellipseSize, ellipseSize);
  ellipse(easeInOutQuart(frameCount % duration, startX, endX - startX, duration), margin * 12, ellipseSize, ellipseSize);
  ellipse(easeInQuint(frameCount % duration, startX, endX - startX, duration), margin * 13, ellipseSize, ellipseSize);
  ellipse(easeOutQuint(frameCount % duration, startX, endX - startX, duration), margin * 14, ellipseSize, ellipseSize);
  ellipse(easeInOutQuint(frameCount % duration, startX, endX - startX, duration), margin * 15, ellipseSize, ellipseSize);

  translate(width / 2, 0);
  fill(60);
  stroke(60);
  text("16. easeInExpo", 20, margin * 1);
  text("17. easeOutExpo", 20, margin * 2);
  text("18. easeInOutExpo", 20, margin * 3);
  text("19. easeinCirc", 20, margin * 4);
  text("20. easeOutCirc", 20, margin * 5);
  text("21. easeInOutCirc", 20, margin * 6);
  text("22. easeInBack", 20, margin * 7);
  text("23. easeOutBack", 20, margin * 8);
  text("24. easeInOutBack", 20, margin * 9);
  text("25. easeInElastic", 20, margin * 10);
  text("26. easeOutElastic", 20, margin * 11);
  text("27. easeInOutElastic", 20, margin * 12);
  text("28. easeInBounce", 20, margin * 13);
  text("29. easeOutBounce", 20, margin * 14);
  text("30. easeInOutBounce", 20, margin * 15);
  line(startX, 0, startX, height);
  line(endX, 0, endX, height);
  fill(128, 0, 0);
  noStroke();
  ellipse(easeInExpo(frameCount % duration, startX, endX - startX, duration), margin * 1, ellipseSize, ellipseSize);
  ellipse(easeOutExpo(frameCount % duration, startX, endX - startX, duration), margin * 2, ellipseSize, ellipseSize);
  ellipse(easeInOutExpo(frameCount % duration, startX, endX - startX, duration), margin * 3, ellipseSize, ellipseSize);
  ellipse(easeInCirc(frameCount % duration, startX, endX - startX, duration), margin * 4, ellipseSize, ellipseSize);
  ellipse(easeOutCirc(frameCount % duration, startX, endX - startX, duration), margin * 5, ellipseSize, ellipseSize);
  ellipse(easeInOutCirc(frameCount % duration, startX, endX - startX, duration), margin * 6, ellipseSize, ellipseSize);
  ellipse(easeInBack(frameCount % duration, startX, endX - startX, duration, 1.0), margin * 7, ellipseSize, ellipseSize);
  ellipse(easeOutBack(frameCount % duration, startX, endX - startX, duration, 1.0), margin * 8, ellipseSize, ellipseSize);
  ellipse(easeInOutBack(frameCount % duration, startX, endX - startX, duration, 1.0), margin * 9, ellipseSize, ellipseSize);
  ellipse(easeInElastic(frameCount % duration, startX, endX - startX, duration), margin * 10, ellipseSize, ellipseSize);
  ellipse(easeOutElastic(frameCount % duration, startX, endX - startX, duration), margin * 11, ellipseSize, ellipseSize);
  ellipse(easeInOutElastic(frameCount % duration, startX, endX - startX, duration), margin * 12, ellipseSize, ellipseSize);
  ellipse(easeInBounce(frameCount % duration, startX, endX - startX, duration), margin * 13, ellipseSize, ellipseSize);
  ellipse(easeOutBounce(frameCount % duration, startX, endX - startX, duration), margin * 14, ellipseSize, ellipseSize);
  ellipse(easeInOutBounce(frameCount % duration, startX, endX - startX, duration), margin * 15, ellipseSize, ellipseSize);

}

float easeInSine(float t, float b, float c, float d){
  return -c * cos(t / d * (PI / 2)) + c + b;
}

float easeOutSine(float t, float b, float c, float d){
  return c * sin(t / d * (PI / 2)) + b;
}

float easeInOutSine(float t, float b, float c, float d){
  return -c / 2 * (cos(PI * t / d) - 1) + b;
}

float easeInQuad(float t, float b, float c, float d){
  t /= d;
  return c * t * t + b; 
}

float easeOutQuad(float t, float b, float c, float d){
  t /= d;
  return -c * t * (t - 2) + b; 
}

float easeInOutQuad(float t, float b, float c, float d){
  t /= d / 2;
  if(t < 1)
    return c / 2 * t * t + b;
  t--;
  return -c / 2 * (t * (t - 2) - 1) + b; 
}

float easeInCubic(float t, float b, float c, float d){
  t /= d;
  return c * t * t * t + b; 
}

float easeOutCubic(float t, float b, float c, float d){
  t /= d;
  t--;
  return c * (t * t * t + 1) + b; 
}

float easeInOutCubic(float t, float b, float c, float d){
  t /= d / 2;
  if(t < 1)
    return c / 2 * t * t * t + b;
  t -= 2;
  return c / 2 * (t * t * t + 2) + b; 
}

float easeInQuart(float t, float b, float c, float d){
  t /= d;
  return c * t * t * t * t + b; 
}

float easeOutQuart(float t, float b, float c, float d){
  t /= d;
  t--;
  return -c * (t * t * t * t - 1) + b; 
}

float easeInOutQuart(float t, float b, float c, float d){
  t /= d / 2;
  if(t < 1)
    return c / 2 * t * t * t * t + b;
  t -= 2;
  return -c / 2 * (t * t * t * t - 2) + b; 
}

float easeInQuint(float t, float b, float c, float d){
  t /= d;
  return c * t * t * t * t * t + b; 
}

float easeOutQuint(float t, float b, float c, float d){
  t /= d;
  t--;
  return c * (t * t * t * t  * t + 1) + b; 
}

float easeInOutQuint(float t, float b, float c, float d){
  t /= d / 2;
  if(t < 1)
    return c / 2 * t * t * t * t * t + b;
  t -= 2;
  return c / 2 * (t * t * t * t * t + 2) + b; 
}

float easeInExpo(float t, float b, float c, float d){
  return t == 0 ? b: c * pow(2, 10 * (t / d - 1)) + b;
}

float easeOutExpo(float t, float b, float c, float d){
  return t == d ? b + c: c * (-pow(2, -10 * t / d) + 1) + b;
}

float easeInOutExpo(float t, float b, float c, float d){
  if(t == 0)
    return b;
  if(t == d)
    return b + c;
  t /= d / 2;
  if(t < 1)
    return c / 2 * pow(2, 10 * (t - 1)) + b;
  t--;
  return c / 2 * (-pow(2, -10 * t) + 2) + b;
}

float easeInCirc(float t, float b, float c, float d){
  t /= d;
  return -c * (sqrt(1 - t * t) - 1) + b;
}

float easeOutCirc(float t, float b, float c, float d){
  t /= d;
  t--;
  return c * sqrt(1 - t * t) + b;
}

float easeInOutCirc(float t, float b, float c, float d){
  t /= d / 2;
  if(t < 1)
    return -c / 2 * (sqrt(1 - t * t) - 1) + b;
  t -= 2;
  return c / 2 * (sqrt(1 - t * t) + 1) + b;
}

float easeInBack(float t, float b, float c, float d, float s){
  t /= d;
  return c * t * t * ((s + 1) * t - s) + b;
}

float easeOutBack(float t, float b, float c, float d, float s){
  t /= d;
  t--;
  return c * (t * t * ((s + 1) * t + s) + 1) + b;
}

float easeInOutBack(float t, float b, float c, float d, float s){
  t /= d / 2;
  s *= 1.525;
  if(t < 1) 
    return c / 2 * (t * t * ((s + 1) * t - s)) + b;
  t -= 2;
   return c / 2 * (t * t * ((s + 1) * t + s) + 2) + b;
}

float easeInElastic(float t, float b, float c, float d){
  float s = 1.70158;
  float a = c;
  if(t == 0)
    return b;
  t /= d;
  if(t == 1)
    return b + c;
  float p = d * 0.3;
  if(a < abs(c)){
    a = c;
    s = p / 4;
  } else {
    s = p / (2 * PI) * asin(c / a);
  }
  t--;
  return -(a * pow(2, 10 * t) * sin((t * d - s) * (2 * PI) / p)) + b;
}

float easeOutElastic(float t, float b, float c, float d){
  float s = 1.70158;
  float a = c;
  if(t == 0)
    return b;
  t /= d;
  if(t == 1)
    return b + c;
  float p = d * 0.3;
  if(a < abs(c)){
    a = c;
    s = p / 4;
  } else {
    s = p / (2 * PI) * asin(c / a);
  }
  return a * pow(2, -10 * t) * sin((t * d - s) * (2 * PI) / p) + c + b;
}

float easeInOutElastic(float t, float b, float c, float d){
  float s = 1.70158;
  float a = c;
  if(t == 0)
    return b;
  t /= d / 2; 
  if(t == 2)
    return b + c;
  float p = d * (0.3 * 1.5);
  if(a < abs(c)){
    a = c;
    s = p / 4;
  } else {
    s = p / (2 * PI) * asin(c / a);
  }
  if(t < 1){
    t--;
    return -0.5 * (a * pow(2, 10 * t) * sin((t * d - s) * (2 * PI) / p)) + b;
  }
  t--;
  return a * pow(2, -10 * t) * sin((t * d - s) * (2 * PI) / p) * 0.5 + c + b;
}

float easeInBounce(float t, float b, float c, float d){
  return c - easeOutBounce(d - t, 0, c, d) + b;
}

float easeOutBounce(float t, float b, float c, float d){
  t /= d;
  if(t < 1.0 / 2.75){
    return c * (7.5265 * t * t) + b;
  } else if(t < 2.0 / 2.75){
    t -= 1.5 / 2.75;
    return c * (7.5265 * t * t + 0.75) + b;
  } else if(t < 2.5 / 2.75){
    t -= 2.25 / 2.75;
    return c * (7.5265 * t * t + 0.9375) + b;
  }else{
    t -= 2.625 / 2.75;
    return c * (7.5265 * t * t + 0.984375) + b;
  }
}

float easeInOutBounce(float t, float b, float c, float d){
  if(t < d / 2)
    return easeInBounce(t * 2, 0, c, d) * 0.5 + b;
  return easeOutBounce(t * 2 - d, 0, c, d) * 0.5 + c * 0.5 + b;
}

イージングを使うと、動きがこんな感じになります。