1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
|
namespace tweeny {
/**
@page manual Tweeny Manual
This document is the manual for Tweeny. It walks you through all the important steps when creating and controlling tweens.
@section creating Creating a tween
Tweeny can interpolate a single value, a set of values and a set of values with different types. For each of these cases, you create a tween using the same method: tweeny::from. The argument types you pass to it defines the tween itself which in turn defines argument number and types for tween::to, tween::during and tween::via, as well as the callback argument types.
Here is how you create a tween:
@code
// Creates a single-valued tween
auto tween = tweeny::from(0);
// Creates a multi-valued tween
auto tween2 = tweeny::from(0, 1, 2);
// Creates a multi-value heterogeneous tween
auto tween3 = tweeny::from(0, 'a', 1.0f);
@endcode
@section points Adding tween points
A tween without a target value does nothing. To add a point to a tween, use the method tween::to. Since tweeny::from returns the tween instance itself, you can chain both calls, forming the following:
@code
// For a single value
auto tween = tweeny::from(0).to(100);
// For multiple values
auto tween = tweeny::from(0, 'a').to(10, 'z');
@endcode
Notice how arguments to tween::to were of the same type of the arguments to tweeny::from.
@section durations Specifying durations
A tween needs a duration between each point. This duration unit is a unsigned integer that can represent anything you want. Usually I use it as milliseconds (this is relevant when stepping a tween). To specify the duration, call tween::during **after** tween::to:
@code
auto tween = tweeny::from(0).to(100).during(100);
@endcode
When you have a multivalued tween, you can either pass one single duration for all the values or specify a value for each point:
@code
auto tween = tweeny::from(0, 1, 2).to(3, 4, 5).during(50, 100, 200);
@endcode
The total duration from the starting point `(0, 1, 2)` to the next point `(3, 4, 5)` is 200, but each value will reach their target at different times.
To specify the same time for each value, pass a single value for tween::during:
@code
auto tween = tweeny::from(0, 1, 2).to(3, 4, 5).during(200);
@endcode
@section easings Changing easing functions
Easing functions control the interpolation values between each point. Given a percentage `p`, initial value `a` and final value `b`, a easing function will return a value between `a` and `b` corresponding to that `p`. For instance, the common implementation of a linear easing function is the following:
@code
int linear(float p, int a, int b) {
return (b-a)*p + a;
}
@endcode
By default, tweens use a linear easing function to interpolate their values. You can change that, though: Tweeny has 30 easing functions that you can specify using tween::via function.
@code
auto tween = tweeny::from(0).to(10).during(100).via(tweeny::easing::circularInOut);
@endcode
The same rules of tween::during applies here: if you have multi-valued tweens, you can specify a different easing for each one or use the same for all of them:
@code
using tweeny::easing;
auto tween = tweeny::from(0, 1, 2).to(3, 4, 5).during(200).via(easing::exponentialIn, easing::exponentialInOut, easing::backOut);
@endcode
For a list of all available easings, consult the <a href="modules.html">modules</a> page.
http://easings.net has a nice visualization of those easing curves.
You can specify custom easing functions if a different behavior is needed, by passing any callable type to tween::via conforming to the <code>T ease(float p, T begin, T end)</code>
prototype and returning the corresponding value.
@code
auto tween = tweeny::from(0).to(100).during(100).via([](float p, int a, int b) { return (b-a)*p + a; } );
@endcode
To a multi type tween, you need to make sure that easing arguments conform to their type:
@code
auto tween = tweeny::from(0, 1.0f).to(100, 200.0f).during(100)
.via([](float p, int a, int b) { return (b-a)*p + a; }, [](float p, float a, float b) { return (b-a)*p + a; });
@endcode
Beware that when using integral types most easing functions will not round but truncate their results. This leads to strange behaviors such as
the tween reaching its final value only when it its 100% but staying in its initial value for a long percentage portion. You can use floating point values
and round them to obtain smoother results. easing::linear does this by default for integral types, but other easings don't.
@section multipoint Multi point tweens
Tweens can have multiple points: a sequence of values that will be reached in order. For instance, you might want to start from 0, reach
100 during 500ms through a easing::linear easing, then reach 200 during 100ms through a easing::circularOut easing.
To allow for that, each call to tween::to adds a new tweening point. Calls to tween::during and tween::via always refer to the last added
point:
@code
auto tween = tweeny::from(0)
.to(100).during(500) // 0 to 100 during 500
.to(200).during(100).via(easing::circularOut); // 100 to 200 during 100 via circularOut
@endcode
Stepping and seeking works transparently for the user, regardless of how many tween points there are. This means that Tweeny will
automatically manage switching from one point to another when using tween::step and tween::seek.
@section interpolating Stepping, seeking and jumping.
After setting up points, durations and easings, a tween is ready to interpolate. There are three main ways to do that and we are going
to cover them in this section.
The first one is **stepping**. It is used to move the tween forward by a delta amount, which can be either specified in duration units
or percentage. Stepping is particularly useful when you are in a event/rendering loop and has access to the delta time between frames:
@code
auto tween = tweeny::from(0).to(100).during(1000);
while (!done) {
tween.step(dt);
}
@endcode
Passing a integral quantity (integers) to tween::step will step it in duration units. Passing a float value will step it by
a percentage (ranging from 0.0f to 1.0f).
You can set a tween to go backwards, so that it steps in reverse. To to that, use tween::backward: each tween::step call will decrease
a tween time until it reaches 0. To make it go forward again, use tween::forward. Tween direction makes no difference when seeking or jumping.
The second one is **seeking**. Seeking is useful if you need the tween to move to a specific point in time or percentage.
@code
auto tween = tweeny::from(0).to(100).during(1000);
tween.seek(0.5f);
@endcode
The same value type rules of tween::step applies: a float value means a percentage and an integral value means duration.
The third one is **jumping**. Jumping is useful to seek to a specific tween point, when you have @ref multipoint .
@code
auto tween = tweeny::from(0).to(100).during(100).to(200).during(100);
tween.jump(1);
@endcode
tween::step, tween::seek and tween::jump both returns the result of their action. The return type varies according to the
tween type according to these rules:
- If the tween has a single value, it will yield that value directly:
@code
auto tween = tweeny::from(0).to(100).during(100);
int value = tween.step(10);
@endcode
- If the tween has multiple values of the same type, it will yield an array with those values:
@code
auto tween = tweeny::from(0, 1).to(2, 3).during(100);
std::array<int, 2> v = tween.step(10);
@endcode
- If the tween has multiple types, it will return a tuple:
@code
auto tween = tweeny::from(0, 1.0f).to(2, 3.0f).during(100);
std::tuple<int, float> v = tween.step(10);
@endcode
@section callbacks Callbacks
Tweeny lets you specify seeking and stepping callbacks so that actions can executed in specific points
(e.g, playing a sound when a tween reaches a frame). tween::onStep add a function that will be called whenever a tween
steps whereas tween::onSeek will add a function to be called when it seeks. Although stepping is resolved
in terms of seeking, tween::step it will not trigger seek callbacks.
Callbacks can be of three different types:
- Accept the tween and its current values. Useful if you want access to tween values and need to control the tween instance:
@code
bool stepped(tween<int, int> & t, int x, int y);
auto tween = tweeny::from(0, 0).to(100, 200).during(100).onStep(stepped);
@endcode
- Accept only a tween, useful if the values itself are not interesting but you need to control tween behavior:
@code
bool stepped(tween<int, int> & t);
auto tween = tweeny::from(0, 0).to(100, 200).during(100).onStep(stepped);
@endcode
- Accept only tween values, if you just want tween values:
@code
bool stepped(int x, int y);
auto tween = tweeny::from(0, 0).to(100, 200).during(100).onStep(stepped);
@endcode
The return type of a callback is always boolean. If it returns true, it will be *dismissed* and
removed from the callback list. Returning false keeps the callback in the queue:
@code
bool stepped(int x, int y) {
printf("x: %d, y: %d\n", x, y);
if (x == y) return true;
return false;
}
auto tween = tweeny::from(0, 0).to(100, 200).during(100).onStep(stepped);
@endcode
All callable types can be used as a callback, as long as they conform to the interface.
@code
struct ftor {
bool operator()(int x, int y) { return false; }
};
auto tween = tweeny::from(0, 0).to(100, 200).during(100);
tween.onStep([](int, int) { return false; }); // lambdas
tween.onStep(ftor()); // functors
@endcode
The @ref loop has some nice ways of using callbacks.
<hr>
This covers all the basics steps of using Tweeny. There is more to learn though, take a look at the <a href="http://github.com/mobius3/tweey-demos">demo repository</a> to see
more. Consult the API of the @ref tween class to see all its methods and more examples within.
I hope you have fun using Tweeny.
*/
}
|