Using built-in eases

Now, say we want to make use of the easing algorithms that we saw in the EaseGallery sample. To do that, we have to change the code by following certain steps.

To use the easing functions, we have to include the Easing.h header file:

#include "cinder/Easing.h"

First we are going to add two more variables, startPostition and circleTimeBase:

Vec2f startPosition[CIRCLE_COUNT];
Vec2f currentPosition[CIRCLE_COUNT];
Vec2f targetPosition[CIRCLE_COUNT];
float circleRadius[CIRCLE_COUNT];
float circleTimeBase[CIRCLE_COUNT];

Then, in the setup() method implementation, we have to change the currentPosition parts to startPosition and add an initial value to the circleTimeBase array members:

startPosition[i].x = Rand::randFloat(0, getWindowWidth());
startPosition[i].y = Rand::randFloat(0, getWindowHeight());
circleTimeBase[i] = 0;

Next, we have to change the update() method so that it can be used along with the easing functions. They are based on time and they return a floating point value between 0 and 1 that defines the playhead position on an abstract 0 to 1 timeline:

void BasicAnimationApp::update() {
  Vec2f difference;
  for (int i=0; i<CIRCLE_COUNT; i++) {
    difference = targetPosition[i] - startPosition[i];
    currentPosition[i] = easeOutExpo(
      getElapsedSeconds()-circleTimeBase[i]) *
      difference + startPosition[i];

    if ( currentPosition[i].distance(targetPosition[i])
    < 1.0f )
    {
      targetPosition[i].x =
      Rand::randFloat(0, getWindowWidth());
      targetPosition[i].y =
      Rand::randFloat(0, getWindowHeight());
      startPosition[i] = currentPosition[i];
      circleTimeBase[i] = getElapsedSeconds();
    }
  }
}

The highlighted parts in the preceding code snippet are those that have been changed. The most important part of it is the currentPosition[i] calculation part. We take the distance between the start and end points of the timeline and multiply it with the position floating point number that is being returned by our easing function, which in this case is easeOutExpo(). Again, it returns a floating point variable between 0 and 1 that represents the position on an abstract 0 to 1 timeline. If we multiply any number with, say, 0.33f, we get one-third of that number, 0.5f, we get one-half of that number, and so on. So, we add this distance to the circle's starting position and we get it's current position!

Compile and run our application now. You should see something as follows:

Using built-in eases

Almost like a snow storm! We will add a small modification to the code though. I will add a TWEEN_SPEED definition at the top of the code and multiply the time parameter passed to the ease function with it, so we can control the speed of the circles:

#define TWEEN_SPEED 0.2

Change the following line in the update() method implementation:

currentPosition[i] = easeOutExpo(
  (getElapsedSeconds()-circleTimeBase[i])*TWEEN_SPEED) *
  difference + startPosition[i];

I did this because the default time base for each tween is 1 second. That means that each transition is happening exactly for 1 second and that's a bit too fast for our current situation. We want it to be slower, so we multiply the time we pass to the easing function with a floating point number that is less than 1.0f and greater than 0.0f. By doing that we ensure that the time is scaled down and instead of 1 second we get 5 seconds for our transition.

So try to compile and run this, and see for yourself! Here is the full source code of our circle-creation:

#include "cinder/app/AppBasic.h"
#include "cinder/gl/gl.h"
#include "cinder/Rand.h"
#include "cinder/Easing.h"

#define CIRCLE_COUNT 100
#define TWEEN_SPEED 0.2

using namespace ci;
using namespace ci::app;
using namespace std;

class BasicAnimationApp : public AppBasic {
  public:
  void setup();
  void update();
  void draw();

  void prepareSettings( Settings *settings );
  Vec2f startPosition[CIRCLE_COUNT];
  Vec2f currentPosition[CIRCLE_COUNT];
  Vec2f targetPosition[CIRCLE_COUNT];
  float circleRadius[CIRCLE_COUNT];
  float circleTimeBase[CIRCLE_COUNT];
};

void BasicAnimationApp::prepareSettings( Settings *settings ) {
  settings->setWindowSize(800,600);
  settings->setFrameRate(60);
}

void BasicAnimationApp::setup() {
  for(int i=0; i<CIRCLE_COUNT; i++) {
    currentPosition[i].x=Rand::randFloat(0, getWindowWidth());
    currentPosition[i].y=Rand::randFloat(0, getWindowHeight());
    targetPosition[i].x=Rand::randFloat(0, getWindowWidth());
    targetPosition[i].y=Rand::randFloat(0, getWindowHeight());
    circleRadius[i] = Rand::randFloat(1, 10);
    startPosition[i].x = Rand::randFloat(0, getWindowWidth());
    startPosition[i].y = Rand::randFloat(0, getWindowHeight());
    circleTimeBase[i] = 0;
  }
}

void BasicAnimationApp::update() {
  Vec2f difference;
  for (int i=0; i<CIRCLE_COUNT; i++) {
    difference = targetPosition[i] - startPosition[i];
    currentPosition[i] = easeOutExpo(
      (getElapsedSeconds()-circleTimeBase[i]) *
      TWEEN_SPEED) *
      difference + startPosition[i];

      if ( currentPosition[i].distance(
      targetPosition[i]) < 1.0f )
    {
      targetPosition[i].x =
      Rand::randFloat(0, getWindowWidth());
      targetPosition[i].y =
      Rand::randFloat(0, getWindowHeight());
      startPosition[i] = currentPosition[i];
      circleTimeBase[i] = getElapsedSeconds();
    }
  }
}

void BasicAnimationApp::draw() {
  gl::clear( Color( 0, 0, 0 ) );
  for (int i=0; i<CIRCLE_COUNT; i++) {
    gl::drawSolidCircle( currentPosition[i], circleRadius[i] );
  }
}

CINDER_APP_BASIC( BasicAnimationApp, RendererGl )

Experiment with the properties and try to change the eases. Not all of them will work with this example, but at least you will understand how to use them to create smooth animations with Cinder.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.142.156.235