Time passage arithmetic explanation
- by Cyber Axe
I ported this from http://www.effectgames.com/effect/article.psp.html/joe/Old_School_Color_Cycling_with_HTML5 some time ago.
However i'm now wanting to modify it for the purpose of changing it from floating point to fixed point maths for enhanced efficiency (for those who are going to talk about premature optimization and what not, i want to have my entire engine in fixed point both as a learning process for me and so i can port code more easily to systems in the future that dont have native floating points such as arm cpus)
My initial conversion to fixed points just resulted in the cycling stuck on either the first or last frame of cycling.
Plus it would be nice to understand better how it works so i can add more options and so forth in the future, my maths however sucks and the comments are limited so i don't really know how the maths work for determining the frame it shoud use (cycleAmount)
I was also a beginner when i ported it as i had no idea between floating points and integers and what not.
So in summary my question is, can anyone give an explination of the arithmatic used for determining the cycleAmount (which determings the "frame" of the cycle)
This is the working floating point maths version of the code:
public final void cycle(Colour[] sourceColours, double timeNow, double speedAdjust) {
// Cycle all animated colour ranges in palette based on timestamp.
sourceColours = sourceColours.clone();
int cycleSize;
double cycleRate;
double cycleAmount;
Cycle cycle;
for (int i = 0, len = cycles.length; i < len; ++i) {
cycle = cycles[i];
cycleSize = (cycle.HIGH - cycle.LOW) + 1;
cycleRate = cycle.RATE / (int) (CYCLE_SPEED / speedAdjust);
cycleAmount = 0;
if (cycle.REVERSE < 3) {
// Standard Cycle
cycleAmount = DFLOAT_MOD((timeNow / (1000 / cycleRate)), cycleSize);
if (cycle.REVERSE < 1) {
cycleAmount = cycleSize - cycleAmount; // If below 1 make sure its not reversed.
}
} else if (cycle.REVERSE == 3) {
// Ping-Pong
cycleAmount = DFLOAT_MOD((timeNow / (1000 / cycleRate)), cycleSize << 1);
if (cycleAmount >= cycleSize) {
cycleAmount = (cycleSize * 2) - cycleAmount;
}
} else if (cycle.REVERSE < 6) {
// Sine Wave
cycleAmount = DFLOAT_MOD((timeNow / (1000 / cycleRate)), cycleSize);
cycleAmount = Math.sin((cycleAmount * 3.1415926 * 2) / cycleSize) + 1;
if (cycle.REVERSE == 4) {
cycleAmount *= (cycleSize / 4);
} else if (cycle.REVERSE == 5) {
cycleAmount *= (cycleSize >> 1);
}
}
if (cycle.REVERSE == 2) {
reverseColours(sourceColours, cycle);
}
if (USE_BLEND_SHIFT) {
blendShiftColours(sourceColours, cycle, cycleAmount);
} else {
shiftColours(sourceColours, cycle, cycleAmount);
}
if (cycle.REVERSE == 2) {
reverseColours(sourceColours, cycle);
}
}
colours = sourceColours;
}
// This utility function allows for variable precision floating point modulus.
private double DFLOAT_MOD(final double d, final double b) {
return (Math.floor(d * PRECISION) % Math.floor(b * PRECISION)) / PRECISION;
}