A creative coding animation with multiple easing functions

Image that made with Processing code examples in this article.

The magical dance of creative coding.

It's one of my creative coding animation work made with the 'Processing'.

Yet another implementation of 'I Wish I Were Your Mirror'. And I added multiple easing functions in it. Please enjoy this interesting moving.

This code does not display any images on the screen but generates image files for animation. You can make an animation with these files.








 

The 'Processing' code example.

Please feel free to use this example code under the terms of the GPL. To see other works based on my code is my pleasure. And my honor.


/**
 * Dance With Me.
 * Have a dots ball.
 * @author @deconbatch
 * @version 0.1
 * Processing 3.2.1
 * 2019.02.12
 */

void setup() {

  size(720, 720);
  colorMode(HSB, 360, 100, 100, 100);
  rectMode(CENTER);
  smooth();
  noLoop();
  
}

void draw() {

  translate(width / 2.0, height / 2.0);
  
  int   frameCntMax  = 24 * 6;
  int   easeLanding  = 2 + floor(random(3)); // easing will stop 2, 3 or 4 times on the way
  float hueBase      = random(360.0);
  float initRotation = random(PI);
  float initPosition = random(1.0);

  StepEasing se = new StepEasing(easeLanding);
  EasingCalculator ec = (random(1.0) > 0.5) ? new FourthPow() : new InOutCubic();
  
  for (int frameCnt = 0; frameCnt < frameCntMax; ++frameCnt) {
    
    float easeRatio = se.calculate(ec, map(frameCnt, 0, frameCntMax, 0.0, 1.0));

    background(0.0, 0.0, 90.0, 100);
    pushMatrix();
    rotate(initRotation);
    drawShapes(hueBase, initPosition, easeRatio);
    popMatrix();

    casing(hueBase);
    saveFrame("frames/" + String.format("%04d", frameCnt) + ".png");

  }

  exit();
  
}

/**
 * drawShapes : draw 2 shapes with Lissajous like figure.
 * @param  _hueBase      : 0.0 - 360.0 : base color of shape.
 * @param  _initPosition : 0.0 - 1.0   : start position of shape.
 * @param  _shapeFactor  : 0.0 - 1.0   : change factor of shape.
 */
private void drawShapes(float _hueBase, float _initPosition, float _shapeFactor) {

  int   plotCntMax = 6;
  float plotScale  = width * 0.25;
  float plotWidth = sin(PI * _shapeFactor) * 0.08;

  strokeWeight(3.0);
  stroke(0.0, 0.0, 90.0, 100.0);
  
  for (int shapeCnt = 0; shapeCnt < 2; ++shapeCnt) {
    
    float xPrev = 0.0;
    float yPrev = 0.0;

    // rotate shape location with PI, not TWO_PI
    float xInit = width * plotWidth * cos(PI * (_shapeFactor + shapeCnt + _initPosition));
    float yInit = height * plotWidth * sin(PI * (_shapeFactor + shapeCnt + _initPosition));

    // for distorted shape
    float xDist = map(sin(TWO_PI * _shapeFactor), -1.0, 1.0, 0.9, 1.1);
    float yDist = map(xDist, 0.95, 1.05, 1.1, 0.9);
      
    float eHue = _hueBase + map(sin(TWO_PI * (_shapeFactor + shapeCnt / 3.0)), -1.0, 1.0, 0.0, 60.0);
    float eSize = 50.0;
      
    for (int plotCnt = 0; plotCnt < plotCntMax; ++plotCnt) {

      float xCurr = xInit + plotScale * cos(3.0 * TWO_PI * plotCnt * 1.0 / plotCntMax + TWO_PI * _shapeFactor);
      float yCurr = yInit + plotScale * sin(2.0 * TWO_PI * plotCnt * 1.0 / plotCntMax );
      fill(
           eHue % 360.0,
           map(plotCnt, 0, plotCntMax, 40.0, 10.0),
           map(plotCnt, 0, plotCntMax, 30.0, 80.0),
           100.0
           );
      ellipse(xCurr, yCurr, eSize, eSize);

    }
  }

}

/**
 * casing : draw fancy casing
 * @param  _hueBase : 0.0 - 360.0 :  casing color.
 */
private void casing(float _hueBase) {

  fill(0.0, 0.0, 0.0, 0.0);
  strokeWeight(54.0);
  stroke(_hueBase, 80.0, 30.0, 100.0);
  rect(0.0, 0.0, width, height);
  strokeWeight(50.0);
  stroke(0.0, 0.0, 100.0, 100.0);
  rect(0.0, 0.0, width, height);
  noStroke();
  noFill();

}

/**
 * StepEasing : calculate easing value with step landing. It just has one easing function yet.
 * @param  _landingCount : 1 - any int value : landing number.
 */
private class StepEasing {

  private float landingPoint;
  private float easePrev;
  private float easeRatio;
  
  StepEasing(int _landingCount) {
    landingPoint = 1.0 / (_landingCount + 1);
    reset();
  }

  StepEasing() {
    landingPoint = 1.0;
    reset();
  }

  private void reset() {
    easePrev  = 0.0;
    easeRatio = 0.0;
  }
  
  /**
   * calculate : calculate easing value with step landing.
   * @param  _t    0.0 - 1.0 : linear value.
   * @return float 0.0 - 1.0 : eased value with step landing.
   */
  public float calculate(EasingCalculator _calc, float _t) {
    float easeCurr = _calc.calculate(map(_t % landingPoint, 0.0, landingPoint, 0.0, 1.0));
    easeRatio += constrain((easeCurr - easePrev) * landingPoint, 0.0, 1.0);
    easePrev = easeCurr;

    return easeRatio;
  }

}

/**
 * easeInOutCubic easing function.
 * @param  _t    : 0.0 - 1.0 : linear value.
 * @return float : 0.0 - 1.0 : eased value.
 */
interface EasingCalculator {
  float calculate(float _t);
}

private class InOutCubic implements EasingCalculator {
  public float calculate(float _t) {
    _t *= 2.0;
    if (_t < 1.0) {
      return pow(_t, 3) / 2.0;
    }
    _t -= 2.0;
    return (pow(_t, 3) + 2.0) / 2.0;
  }
}

private class Squre implements EasingCalculator {
  public float calculate(float _t) {
    return 1.0 - pow(1.0 - _t, 2);
  }
}

private class FourthPow implements EasingCalculator {
  public float calculate(float _t) {
    return 1.0 - pow(1.0 - _t, 4);
  }
}

/*
Copyright (C) 2019- deconbatch

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>
*/


 

Next Post Previous Post
No Comment
Add Comment
comment url