Merge pull request #852 from flashback-fx/master
easings.h refinement and example
This commit is contained in:
commit
163a6581aa
3 changed files with 707 additions and 90 deletions
263
examples/others/easings.h
Normal file
263
examples/others/easings.h
Normal file
|
@ -0,0 +1,263 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib easings (header only file)
|
||||
*
|
||||
* Useful easing functions for values animation
|
||||
*
|
||||
* This header uses:
|
||||
* #define EASINGS_STATIC_INLINE // Inlines all functions code, so it runs faster.
|
||||
* // This requires lots of memory on system.
|
||||
* How to use:
|
||||
* The four inputs t,b,c,d are defined as follows:
|
||||
* t = current time (in any unit measure, but same unit as duration)
|
||||
* b = starting value to interpolate
|
||||
* c = the total change in value of b that needs to occur
|
||||
* d = total time it should take to complete (duration)
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* int currentTime = 0;
|
||||
* int duration = 100;
|
||||
* float startPositionX = 0.0f;
|
||||
* float finalPositionX = 30.0f;
|
||||
* float currentPositionX = startPositionX;
|
||||
*
|
||||
* while (currentPositionX < finalPositionX)
|
||||
* {
|
||||
* currentPositionX = EaseSineIn(currentTime, startPositionX, finalPositionX - startPositionX, duration);
|
||||
* currentTime++;
|
||||
* }
|
||||
*
|
||||
* A port of Robert Penner's easing equations to C (http://robertpenner.com/easing/)
|
||||
*
|
||||
* Robert Penner License
|
||||
* ---------------------------------------------------------------------------------
|
||||
* Open source under the BSD License.
|
||||
*
|
||||
* Copyright (c) 2001 Robert Penner. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* - Neither the name of the author nor the names of contributors may be used
|
||||
* to endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ---------------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2015 Ramon Santamaria
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty. In no event
|
||||
* will the authors be held liable for any damages arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose, including commercial
|
||||
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not claim that you
|
||||
* wrote the original software. If you use this software in a product, an acknowledgment
|
||||
* in the product documentation would be appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
|
||||
* as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
**********************************************************************************************/
|
||||
|
||||
#ifndef EASINGS_H
|
||||
#define EASINGS_H
|
||||
|
||||
#define EASINGS_STATIC_INLINE // NOTE: By default, compile functions as static inline
|
||||
|
||||
#if defined(EASINGS_STATIC_INLINE)
|
||||
#define EASEDEF static inline
|
||||
#else
|
||||
#define EASEDEF extern
|
||||
#endif
|
||||
|
||||
#include <tgmath.h> // Required for: sin(), cos(), sqrt(), pow()
|
||||
|
||||
#ifndef PI
|
||||
#define PI 3.14159265358979323846f //Required as PI is not always defined in math.h
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" { // Prevents name mangling of functions
|
||||
#endif
|
||||
|
||||
// Linear Easing functions
|
||||
EASEDEF float EaseLinearNone(float t, float b, float c, float d) { return (c*t/d + b); }
|
||||
EASEDEF float EaseLinearIn(float t, float b, float c, float d) { return (c*t/d + b); }
|
||||
EASEDEF float EaseLinearOut(float t, float b, float c, float d) { return (c*t/d + b); }
|
||||
EASEDEF float EaseLinearInOut(float t,float b, float c, float d) { return (c*t/d + b); }
|
||||
|
||||
// Sine Easing functions
|
||||
EASEDEF float EaseSineIn(float t, float b, float c, float d) { return (-c*cos(t/d*(PI/2.0f)) + c + b); }
|
||||
EASEDEF float EaseSineOut(float t, float b, float c, float d) { return (c*sin(t/d*(PI/2.0f)) + b); }
|
||||
EASEDEF float EaseSineInOut(float t, float b, float c, float d) { return (-c/2.0f*(cos(PI*t/d) - 1.0f) + b); }
|
||||
|
||||
// Circular Easing functions
|
||||
EASEDEF float EaseCircIn(float t, float b, float c, float d) { t /= d; return (-c*(sqrt(1.0f - t*t) - 1.0f) + b); }
|
||||
EASEDEF float EaseCircOut(float t, float b, float c, float d) { t = t/d - 1.0f; return (c*sqrt(1.0f - t*t) + b); }
|
||||
EASEDEF float EaseCircInOut(float t, float b, float c, float d)
|
||||
{
|
||||
if ((t/=d/2.0f) < 1.0f) return (-c/2.0f*(sqrt(1.0f - t*t) - 1.0f) + b);
|
||||
t -= 2.0f; return (c/2.0f*(sqrt(1.0f - t*t) + 1.0f) + b);
|
||||
}
|
||||
|
||||
// Cubic Easing functions
|
||||
EASEDEF float EaseCubicIn(float t, float b, float c, float d) { t /= d; return (c*t*t*t + b); }
|
||||
EASEDEF float EaseCubicOut(float t, float b, float c, float d) { t = t/d - 1.0f; return (c*(t*t*t + 1.0f) + b); }
|
||||
EASEDEF float EaseCubicInOut(float t, float b, float c, float d)
|
||||
{
|
||||
if ((t/=d/2.0f) < 1.0f) return (c/2.0f*t*t*t + b);
|
||||
t -= 2.0f; return (c/2.0f*(t*t*t + 2.0f) + b);
|
||||
}
|
||||
|
||||
// Quadratic Easing functions
|
||||
EASEDEF float EaseQuadIn(float t, float b, float c, float d) { t /= d; return (c*t*t + b); }
|
||||
EASEDEF float EaseQuadOut(float t, float b, float c, float d) { t /= d; return (-c*t*(t - 2.0f) + b); }
|
||||
EASEDEF float EaseQuadInOut(float t, float b, float c, float d)
|
||||
{
|
||||
if ((t/=d/2) < 1) return (((c/2)*(t*t)) + b);
|
||||
return (-c/2.0f*(((t - 1.0f)*(t - 3.0f)) - 1.0f) + b);
|
||||
}
|
||||
|
||||
// Exponential Easing functions
|
||||
EASEDEF float EaseExpoIn(float t, float b, float c, float d) { return (t == 0.0f) ? b : (c*pow(2.0f, 10.0f*(t/d - 1.0f)) + b); }
|
||||
EASEDEF float EaseExpoOut(float t, float b, float c, float d) { return (t == d) ? (b + c) : (c*(-pow(2.0f, -10.0f*t/d) + 1.0f) + b); }
|
||||
EASEDEF float EaseExpoInOut(float t, float b, float c, float d)
|
||||
{
|
||||
if (t == 0.0f) return b;
|
||||
if (t == d) return (b + c);
|
||||
if ((t/=d/2.0f) < 1.0f) return (c/2.0f*pow(2.0f, 10.0f*(t - 1.0f)) + b);
|
||||
|
||||
return (c/2.0f*(-pow(2.0f, -10.0f*(t - 1.0f)) + 2.0f) + b);
|
||||
}
|
||||
|
||||
// Back Easing functions
|
||||
EASEDEF float EaseBackIn(float t, float b, float c, float d)
|
||||
{
|
||||
float s = 1.70158f;
|
||||
float postFix = t/=d;
|
||||
return (c*(postFix)*t*((s + 1.0f)*t - s) + b);
|
||||
}
|
||||
|
||||
EASEDEF float EaseBackOut(float t, float b, float c, float d)
|
||||
{
|
||||
float s = 1.70158f;
|
||||
t = t/d - 1.0f;
|
||||
return (c*(t*t*((s + 1.0f)*t + s) + 1.0f) + b);
|
||||
}
|
||||
|
||||
EASEDEF float EaseBackInOut(float t, float b, float c, float d)
|
||||
{
|
||||
float s = 1.70158f;
|
||||
if ((t/=d/2.0f) < 1.0f)
|
||||
{
|
||||
s *= 1.525f;
|
||||
return (c/2.0f*(t*t*((s + 1.0f)*t - s)) + b);
|
||||
}
|
||||
|
||||
float postFix = t-=2.0f;
|
||||
s *= 1.525f;
|
||||
return (c/2.0f*((postFix)*t*((s + 1.0f)*t + s) + 2.0f) + b);
|
||||
}
|
||||
|
||||
// Bounce Easing functions
|
||||
EASEDEF float EaseBounceOut(float t, float b, float c, float d)
|
||||
{
|
||||
if ((t/=d) < (1.0f/2.75f))
|
||||
{
|
||||
return (c*(7.5625f*t*t) + b);
|
||||
}
|
||||
else if (t < (2.0f/2.75f))
|
||||
{
|
||||
float postFix = t-=(1.5f/2.75f);
|
||||
return (c*(7.5625f*(postFix)*t + 0.75f) + b);
|
||||
}
|
||||
else if (t < (2.5/2.75))
|
||||
{
|
||||
float postFix = t-=(2.25f/2.75f);
|
||||
return (c*(7.5625f*(postFix)*t + 0.9375f) + b);
|
||||
}
|
||||
else
|
||||
{
|
||||
float postFix = t-=(2.625f/2.75f);
|
||||
return (c*(7.5625f*(postFix)*t + 0.984375f) + b);
|
||||
}
|
||||
}
|
||||
|
||||
EASEDEF float EaseBounceIn(float t, float b, float c, float d) { return (c - EaseBounceOut(d - t, 0.0f, c, d) + b); }
|
||||
EASEDEF float EaseBounceInOut(float t, float b, float c, float d)
|
||||
{
|
||||
if (t < d/2.0f) return (EaseBounceIn(t*2.0f, 0.0f, c, d)*0.5f + b);
|
||||
else return (EaseBounceOut(t*2.0f - d, 0.0f, c, d)*0.5f + c*0.5f + b);
|
||||
}
|
||||
|
||||
// Elastic Easing functions
|
||||
EASEDEF float EaseElasticIn(float t, float b, float c, float d)
|
||||
{
|
||||
if (t == 0.0f) return b;
|
||||
if ((t/=d) == 1.0f) return (b + c);
|
||||
|
||||
float p = d*0.3f;
|
||||
float a = c;
|
||||
float s = p/4.0f;
|
||||
float postFix = a*pow(2.0f, 10.0f*(t-=1.0f));
|
||||
|
||||
return (-(postFix*sin((t*d-s)*(2.0f*PI)/p )) + b);
|
||||
}
|
||||
|
||||
EASEDEF float EaseElasticOut(float t, float b, float c, float d)
|
||||
{
|
||||
if (t == 0.0f) return b;
|
||||
if ((t/=d) == 1.0f) return (b + c);
|
||||
|
||||
float p = d*0.3f;
|
||||
float a = c;
|
||||
float s = p/4.0f;
|
||||
|
||||
return (a*pow(2.0f,-10.0f*t)*sin((t*d-s)*(2.0f*PI)/p) + c + b);
|
||||
}
|
||||
|
||||
EASEDEF float EaseElasticInOut(float t, float b, float c, float d)
|
||||
{
|
||||
if (t == 0.0f) return b;
|
||||
if ((t/=d/2.0f) == 2.0f) return (b + c);
|
||||
|
||||
float p = d*(0.3f*1.5f);
|
||||
float a = c;
|
||||
float s = p/4.0f;
|
||||
|
||||
if (t < 1.0f)
|
||||
{
|
||||
float postFix = a*pow(2.0f, 10.0f*(t-=1.0f));
|
||||
return -0.5f*(postFix*sin((t*d-s)*(2.0f*PI)/p)) + b;
|
||||
}
|
||||
|
||||
float postFix = a*pow(2.0f, -10.0f*(t-=1.0f));
|
||||
|
||||
return (postFix*sin((t*d-s)*(2.0f*PI)/p)*0.5f + c + b);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // EASINGS_H
|
354
examples/others/easings_testbed.c
Normal file
354
examples/others/easings_testbed.c
Normal file
|
@ -0,0 +1,354 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [easings] example
|
||||
*
|
||||
* This example has been created using raylib 2.5 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
*
|
||||
* Copyright (c) 2019 Juan Miguel López
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
|
||||
#include <raylib.h>
|
||||
#include "easings.h"
|
||||
|
||||
|
||||
// Application constants
|
||||
#define SCR_WIDTH 800
|
||||
#define SCR_HEIGHT 450
|
||||
#define BALL_RADIUS 16.0f
|
||||
#define BALL_COLOR MAROON
|
||||
#define PAD 80.0f
|
||||
#define START_X (0.0f + (BALL_RADIUS) + (PAD))
|
||||
#define END_X ((SCR_WIDTH) - ((BALL_RADIUS) + (PAD)))
|
||||
#define START_Y (0.0f + (BALL_RADIUS) + (PAD))
|
||||
#define END_Y ((SCR_HEIGHT) - ((BALL_RADIUS) + (PAD)))
|
||||
#define T_ADVANCE 1.0f
|
||||
#define D_DFT 300.0f
|
||||
#define TARGET_FPS 60
|
||||
#define BG_COLOR RAYWHITE
|
||||
#define TEXT_COLOR LIGHTGRAY
|
||||
#define FONT_SIZE 20
|
||||
#define D_STEP 20.0f
|
||||
#define D_STEP_FINE 2.0f
|
||||
#define D_MIN 1.0f
|
||||
#define D_MAX 10000.0f
|
||||
|
||||
// Application control keys
|
||||
#define KEY_NEXT_EASE_X KEY_RIGHT
|
||||
#define KEY_PREV_EASE_X KEY_LEFT
|
||||
#define KEY_NEXT_EASE_Y KEY_DOWN
|
||||
#define KEY_PREV_EASE_Y KEY_UP
|
||||
#define KEY_INCR_D_STEP KEY_W
|
||||
#define KEY_DECR_D_STEP KEY_Q
|
||||
#define KEY_INCR_D_FINE KEY_S
|
||||
#define KEY_DECR_D_FINE KEY_A
|
||||
#define KEY_PLAY_PAUSE KEY_ENTER
|
||||
#define KEY_RESTART KEY_SPACE
|
||||
#define KEY_TOGGLE_UNBOUNDED_T KEY_T
|
||||
|
||||
|
||||
// Easing types
|
||||
enum EasingTypes {
|
||||
EASE_LINEAR_NONE,
|
||||
EASE_LINEAR_IN,
|
||||
EASE_LINEAR_OUT,
|
||||
EASE_LINEAR_IN_OUT,
|
||||
EASE_SINE_IN,
|
||||
EASE_SINE_OUT,
|
||||
EASE_SINE_IN_OUT,
|
||||
EASE_CIRC_IN,
|
||||
EASE_CIRC_OUT,
|
||||
EASE_CIRC_IN_OUT,
|
||||
EASE_CUBIC_IN,
|
||||
EASE_CUBIC_OUT,
|
||||
EASE_CUBIC_IN_OUT,
|
||||
EASE_QUAD_IN,
|
||||
EASE_QUAD_OUT,
|
||||
EASE_QUAD_IN_OUT,
|
||||
EASE_EXPO_IN,
|
||||
EASE_EXPO_OUT,
|
||||
EASE_EXPO_IN_OUT,
|
||||
EASE_BACK_IN,
|
||||
EASE_BACK_OUT,
|
||||
EASE_BACK_IN_OUT,
|
||||
EASE_BOUNCE_OUT,
|
||||
EASE_BOUNCE_IN,
|
||||
EASE_BOUNCE_IN_OUT,
|
||||
EASE_ELASTIC_IN,
|
||||
EASE_ELASTIC_OUT,
|
||||
EASE_ELASTIC_IN_OUT,
|
||||
NUM_EASING_TYPES,
|
||||
EASING_NONE = NUM_EASING_TYPES
|
||||
};
|
||||
|
||||
|
||||
static float NoEase(float t, float b, float c, float d); // NoEase function declaration, function used when "no easing" is selected for any axis
|
||||
|
||||
|
||||
// Easing functions reference data
|
||||
static const struct {
|
||||
const char *name;
|
||||
float (*func)(float, float, float, float);
|
||||
} Easings[] = {
|
||||
[EASE_LINEAR_NONE] = {
|
||||
.name = "EaseLinearNone",
|
||||
.func = EaseLinearNone,
|
||||
},
|
||||
[EASE_LINEAR_IN] = {
|
||||
.name = "EaseLinearIn",
|
||||
.func = EaseLinearIn,
|
||||
},
|
||||
[EASE_LINEAR_OUT] = {
|
||||
.name = "EaseLinearOut",
|
||||
.func = EaseLinearOut,
|
||||
},
|
||||
[EASE_LINEAR_IN_OUT] = {
|
||||
.name = "EaseLinearInOut",
|
||||
.func = EaseLinearInOut,
|
||||
},
|
||||
[EASE_SINE_IN] = {
|
||||
.name = "EaseSineIn",
|
||||
.func = EaseSineIn,
|
||||
},
|
||||
[EASE_SINE_OUT] = {
|
||||
.name = "EaseSineOut",
|
||||
.func = EaseSineOut,
|
||||
},
|
||||
[EASE_SINE_IN_OUT] = {
|
||||
.name = "EaseSineInOut",
|
||||
.func = EaseSineInOut,
|
||||
},
|
||||
[EASE_CIRC_IN] = {
|
||||
.name = "EaseCircIn",
|
||||
.func = EaseCircIn,
|
||||
},
|
||||
[EASE_CIRC_OUT] = {
|
||||
.name = "EaseCircOut",
|
||||
.func = EaseCircOut,
|
||||
},
|
||||
[EASE_CIRC_IN_OUT] = {
|
||||
.name = "EaseCircInOut",
|
||||
.func = EaseCircInOut,
|
||||
},
|
||||
[EASE_CUBIC_IN] = {
|
||||
.name = "EaseCubicIn",
|
||||
.func = EaseCubicIn,
|
||||
},
|
||||
[EASE_CUBIC_OUT] = {
|
||||
.name = "EaseCubicOut",
|
||||
.func = EaseCubicOut,
|
||||
},
|
||||
[EASE_CUBIC_IN_OUT] = {
|
||||
.name = "EaseCubicInOut",
|
||||
.func = EaseCubicInOut,
|
||||
},
|
||||
[EASE_QUAD_IN] = {
|
||||
.name = "EaseQuadIn",
|
||||
.func = EaseQuadIn,
|
||||
},
|
||||
[EASE_QUAD_OUT] = {
|
||||
.name = "EaseQuadOut",
|
||||
.func = EaseQuadOut,
|
||||
},
|
||||
[EASE_QUAD_IN_OUT] = {
|
||||
.name = "EaseQuadInOut",
|
||||
.func = EaseQuadInOut,
|
||||
},
|
||||
[EASE_EXPO_IN] = {
|
||||
.name = "EaseExpoIn",
|
||||
.func = EaseExpoIn,
|
||||
},
|
||||
[EASE_EXPO_OUT] = {
|
||||
.name = "EaseExpoOut",
|
||||
.func = EaseExpoOut,
|
||||
},
|
||||
[EASE_EXPO_IN_OUT] = {
|
||||
.name = "EaseExpoInOut",
|
||||
.func = EaseExpoInOut,
|
||||
},
|
||||
[EASE_BACK_IN] = {
|
||||
.name = "EaseBackIn",
|
||||
.func = EaseBackIn,
|
||||
},
|
||||
[EASE_BACK_OUT] = {
|
||||
.name = "EaseBackOut",
|
||||
.func = EaseBackOut,
|
||||
},
|
||||
[EASE_BACK_IN_OUT] = {
|
||||
.name = "EaseBackInOut",
|
||||
.func = EaseBackInOut,
|
||||
},
|
||||
[EASE_BOUNCE_OUT] = {
|
||||
.name = "EaseBounceOut",
|
||||
.func = EaseBounceOut,
|
||||
},
|
||||
[EASE_BOUNCE_IN] = {
|
||||
.name = "EaseBounceIn",
|
||||
.func = EaseBounceIn,
|
||||
},
|
||||
[EASE_BOUNCE_IN_OUT] = {
|
||||
.name = "EaseBounceInOut",
|
||||
.func = EaseBounceInOut,
|
||||
},
|
||||
[EASE_ELASTIC_IN] = {
|
||||
.name = "EaseElasticIn",
|
||||
.func = EaseElasticIn,
|
||||
},
|
||||
[EASE_ELASTIC_OUT] = {
|
||||
.name = "EaseElasticOut",
|
||||
.func = EaseElasticOut,
|
||||
},
|
||||
[EASE_ELASTIC_IN_OUT] = {
|
||||
.name = "EaseElasticInOut",
|
||||
.func = EaseElasticInOut,
|
||||
},
|
||||
[EASING_NONE] = {
|
||||
.name = "None",
|
||||
.func = NoEase,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
Vector2 ballPos = { .x = START_X, .y = START_Y };
|
||||
float t = 0.0f; // Current time (in any unit measure, but same unit as duration)
|
||||
float d = D_DFT; // Total time it should take to complete (duration)
|
||||
bool paused = true;
|
||||
bool boundedT = true; // If true, t will stop when d >= td, otherwise t will keep adding td to its value every loop
|
||||
|
||||
enum EasingTypes easingX = EASING_NONE; // Easing selected for x axis
|
||||
enum EasingTypes easingY = EASING_NONE; // Easing selected for y axis
|
||||
|
||||
InitWindow(SCR_WIDTH, SCR_HEIGHT, "raylib [easings] example");
|
||||
SetTargetFPS(TARGET_FPS);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyPressed(KEY_TOGGLE_UNBOUNDED_T))
|
||||
boundedT = 1 - boundedT;
|
||||
|
||||
// Choose easing for the X axis
|
||||
if (IsKeyPressed(KEY_NEXT_EASE_X))
|
||||
{
|
||||
++easingX;
|
||||
|
||||
if (easingX > EASING_NONE)
|
||||
easingX = 0;
|
||||
}
|
||||
else if (IsKeyPressed(KEY_PREV_EASE_X))
|
||||
{
|
||||
if (easingX == 0)
|
||||
easingX = EASING_NONE;
|
||||
else
|
||||
--easingX;
|
||||
}
|
||||
|
||||
// Choose easing for the Y axis
|
||||
if (IsKeyPressed(KEY_NEXT_EASE_Y))
|
||||
{
|
||||
++easingY;
|
||||
|
||||
if (easingY > EASING_NONE)
|
||||
easingY = 0;
|
||||
}
|
||||
else if (IsKeyPressed(KEY_PREV_EASE_Y))
|
||||
{
|
||||
if (easingY == 0)
|
||||
easingY = EASING_NONE;
|
||||
else
|
||||
--easingY;
|
||||
}
|
||||
|
||||
// Change d (duration) value
|
||||
if (IsKeyPressed(KEY_INCR_D_STEP) && d < D_MAX - D_STEP)
|
||||
d += D_STEP;
|
||||
else if (IsKeyPressed(KEY_DECR_D_STEP) && d > D_MIN + D_STEP)
|
||||
d -= D_STEP;
|
||||
|
||||
if (IsKeyDown(KEY_INCR_D_FINE) && d < D_MAX - D_STEP_FINE)
|
||||
d += D_STEP_FINE;
|
||||
else if (IsKeyDown(KEY_DECR_D_FINE) && d > D_MIN + D_STEP_FINE)
|
||||
d -= D_STEP_FINE;
|
||||
|
||||
// Play, pause and restart controls
|
||||
if (IsKeyPressed(KEY_RESTART) ||
|
||||
IsKeyPressed(KEY_NEXT_EASE_X) || IsKeyPressed(KEY_PREV_EASE_X) ||
|
||||
IsKeyPressed(KEY_NEXT_EASE_Y) || IsKeyPressed(KEY_PREV_EASE_Y) ||
|
||||
IsKeyPressed(KEY_INCR_D_STEP) || IsKeyPressed(KEY_DECR_D_STEP) ||
|
||||
IsKeyPressed(KEY_TOGGLE_UNBOUNDED_T) ||
|
||||
IsKeyDown(KEY_INCR_D_FINE) || IsKeyDown(KEY_DECR_D_FINE) ||
|
||||
(IsKeyPressed(KEY_PLAY_PAUSE) && boundedT == true && t >= d))
|
||||
{
|
||||
t = 0.0f;
|
||||
ballPos.x = START_X;
|
||||
ballPos.y = START_Y;
|
||||
paused = true;
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KEY_PLAY_PAUSE))
|
||||
paused = 1 - paused;
|
||||
|
||||
// Movement computation
|
||||
if ((paused == false) &&
|
||||
((boundedT == true && t < d) || boundedT == false))
|
||||
{
|
||||
ballPos.x = Easings[easingX].func(t, START_X, END_X - START_X, d);
|
||||
ballPos.y = Easings[easingY].func(t, START_Y, END_Y - START_Y, d);
|
||||
t += T_ADVANCE;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(BG_COLOR);
|
||||
|
||||
// Draw information text
|
||||
int line = 0;
|
||||
|
||||
DrawText(TextFormat("Easing x: %s", Easings[easingX].name), 0, FONT_SIZE * (line++), FONT_SIZE, TEXT_COLOR);
|
||||
DrawText(TextFormat("Easing y: %s", Easings[easingY].name), 0, FONT_SIZE * (line++), FONT_SIZE, TEXT_COLOR);
|
||||
DrawText(TextFormat("t (%c) = %.2f d = %.2f", (boundedT == true)? 'b' : 'u', t, d),
|
||||
0, FONT_SIZE * (line++), FONT_SIZE, TEXT_COLOR);
|
||||
|
||||
// Draw instructions text
|
||||
line = 1;
|
||||
DrawText("Use ENTER to play or pause movement, use SPACE to restart", 0, SCR_HEIGHT - FONT_SIZE * (line++), FONT_SIZE, TEXT_COLOR);
|
||||
DrawText("Use D and W or A and S keys to change duration", 0, SCR_HEIGHT - FONT_SIZE * (line++), FONT_SIZE, TEXT_COLOR);
|
||||
DrawText("Use LEFT or RIGHT keys to choose easing for the x axis", 0, SCR_HEIGHT - FONT_SIZE * (line++), FONT_SIZE, TEXT_COLOR);
|
||||
DrawText("Use UP or DOWN keys to choose easing for the y axis", 0, SCR_HEIGHT - FONT_SIZE * (line++), FONT_SIZE, TEXT_COLOR);
|
||||
|
||||
// Draw ball
|
||||
DrawCircleV(ballPos, BALL_RADIUS, BALL_COLOR);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow();
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// NoEase function, used when "no easing" is selected for any axis. It just ignores all parameters besides b.
|
||||
static float NoEase(float t, float b, float c, float d)
|
||||
{
|
||||
float burn = t + b + c + d; // Hack to avoid compiler warning (about unused variables)
|
||||
d += burn;
|
||||
|
||||
return b;
|
||||
}
|
180
src/easings.h
180
src/easings.h
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib easings (header only file)
|
||||
*
|
||||
*
|
||||
* Useful easing functions for values animation
|
||||
*
|
||||
* This header uses:
|
||||
|
@ -32,31 +32,31 @@
|
|||
*
|
||||
* Robert Penner License
|
||||
* ---------------------------------------------------------------------------------
|
||||
* Open source under the BSD License.
|
||||
* Open source under the BSD License.
|
||||
*
|
||||
* Copyright (c) 2001 Robert Penner. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* - Neither the name of the author nor the names of contributors may be used
|
||||
* to endorse or promote products derived from this software without specific
|
||||
* - Neither the name of the author nor the names of contributors may be used
|
||||
* to endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ---------------------------------------------------------------------------------
|
||||
*
|
||||
|
@ -90,7 +90,7 @@
|
|||
#define EASEDEF extern
|
||||
#endif
|
||||
|
||||
#include <math.h> // Required for: sin(), cos(), sqrt(), pow()
|
||||
#include <tgmath.h> // Required for: sin(), cos(), sqrt(), pow()
|
||||
|
||||
#ifndef PI
|
||||
#define PI 3.14159265358979323846f //Required as PI is not always defined in math.h
|
||||
|
@ -107,153 +107,153 @@ EASEDEF float EaseLinearOut(float t, float b, float c, float d) { return (c*t/d
|
|||
EASEDEF float EaseLinearInOut(float t,float b, float c, float d) { return (c*t/d + b); }
|
||||
|
||||
// Sine Easing functions
|
||||
EASEDEF float EaseSineIn(float t, float b, float c, float d) { return (-c*cos(t/d*(PI/2)) + c + b); }
|
||||
EASEDEF float EaseSineOut(float t, float b, float c, float d) { return (c*sin(t/d*(PI/2)) + b); }
|
||||
EASEDEF float EaseSineInOut(float t, float b, float c, float d) { return (-c/2*(cos(PI*t/d) - 1) + b); }
|
||||
EASEDEF float EaseSineIn(float t, float b, float c, float d) { return (-c*cos(t/d*(PI/2.0f)) + c + b); }
|
||||
EASEDEF float EaseSineOut(float t, float b, float c, float d) { return (c*sin(t/d*(PI/2.0f)) + b); }
|
||||
EASEDEF float EaseSineInOut(float t, float b, float c, float d) { return (-c/2.0f*(cos(PI*t/d) - 1.0f) + b); }
|
||||
|
||||
// Circular Easing functions
|
||||
EASEDEF float EaseCircIn(float t, float b, float c, float d) { t /= d; return (-c*(sqrt(1 - t*t) - 1) + b); }
|
||||
EASEDEF float EaseCircOut(float t, float b, float c, float d) { t = t/d - 1; return (c*sqrt(1 - t*t) + b); }
|
||||
EASEDEF float EaseCircInOut(float t, float b, float c, float d)
|
||||
EASEDEF float EaseCircIn(float t, float b, float c, float d) { t /= d; return (-c*(sqrt(1.0f - t*t) - 1.0f) + b); }
|
||||
EASEDEF float EaseCircOut(float t, float b, float c, float d) { t = t/d - 1.0f; return (c*sqrt(1.0f - t*t) + b); }
|
||||
EASEDEF float EaseCircInOut(float t, float b, float c, float d)
|
||||
{
|
||||
if ((t/=d/2) < 1) return (-c/2*(sqrt(1 - t*t) - 1) + b);
|
||||
t -= 2; return (c/2*(sqrt(1 - t*t) + 1) + b);
|
||||
if ((t/=d/2.0f) < 1.0f) return (-c/2.0f*(sqrt(1.0f - t*t) - 1.0f) + b);
|
||||
t -= 2.0f; return (c/2.0f*(sqrt(1.0f - t*t) + 1.0f) + b);
|
||||
}
|
||||
|
||||
// Cubic Easing functions
|
||||
EASEDEF float EaseCubicIn(float t, float b, float c, float d) { t /= d; return (c*t*t*t + b); }
|
||||
EASEDEF float EaseCubicOut(float t, float b, float c, float d) { t = t/d-1; return (c*(t*t*t + 1) + b); }
|
||||
EASEDEF float EaseCubicInOut(float t, float b, float c, float d)
|
||||
{
|
||||
if ((t/=d/2) < 1) return (c/2*t*t*t + b);
|
||||
t -= 2; return (c/2*(t*t*t + 2) + b);
|
||||
EASEDEF float EaseCubicOut(float t, float b, float c, float d) { t = t/d - 1.0f; return (c*(t*t*t + 1.0f) + b); }
|
||||
EASEDEF float EaseCubicInOut(float t, float b, float c, float d)
|
||||
{
|
||||
if ((t/=d/2.0f) < 1.0f) return (c/2.0f*t*t*t + b);
|
||||
t -= 2.0f; return (c/2.0f*(t*t*t + 2.0f) + b);
|
||||
}
|
||||
|
||||
// Quadratic Easing functions
|
||||
EASEDEF float EaseQuadIn(float t, float b, float c, float d) { t /= d; return (c*t*t + b); }
|
||||
EASEDEF float EaseQuadOut(float t, float b, float c, float d) { t /= d; return (-c*t*(t - 2) + b); }
|
||||
EASEDEF float EaseQuadInOut(float t, float b, float c, float d)
|
||||
EASEDEF float EaseQuadOut(float t, float b, float c, float d) { t /= d; return (-c*t*(t - 2.0f) + b); }
|
||||
EASEDEF float EaseQuadInOut(float t, float b, float c, float d)
|
||||
{
|
||||
if ((t/=d/2) < 1) return (((c/2)*(t*t)) + b);
|
||||
t--; return (-c/2*(((t - 2)*t) - 1) + b);
|
||||
return (-c/2.0f*(((t - 1.0f)*(t - 3.0f)) - 1.0f) + b);
|
||||
}
|
||||
|
||||
// Exponential Easing functions
|
||||
EASEDEF float EaseExpoIn(float t, float b, float c, float d) { return (t == 0) ? b : (c*pow(2, 10*(t/d - 1)) + b); }
|
||||
EASEDEF float EaseExpoOut(float t, float b, float c, float d) { return (t == d) ? (b + c) : (c*(-pow(2, -10*t/d) + 1) + b); }
|
||||
EASEDEF float EaseExpoInOut(float t, float b, float c, float d)
|
||||
EASEDEF float EaseExpoIn(float t, float b, float c, float d) { return (t == 0.0f) ? b : (c*pow(2.0f, 10.0f*(t/d - 1.0f)) + b); }
|
||||
EASEDEF float EaseExpoOut(float t, float b, float c, float d) { return (t == d) ? (b + c) : (c*(-pow(2.0f, -10.0f*t/d) + 1.0f) + b); }
|
||||
EASEDEF float EaseExpoInOut(float t, float b, float c, float d)
|
||||
{
|
||||
if (t == 0) return b;
|
||||
if (t == 0.0f) return b;
|
||||
if (t == d) return (b + c);
|
||||
if ((t/=d/2) < 1) return (c/2*pow(2, 10*(t - 1)) + b);
|
||||
|
||||
return (c/2*(-pow(2, -10*--t) + 2) + b);
|
||||
if ((t/=d/2.0f) < 1.0f) return (c/2.0f*pow(2.0f, 10.0f*(t - 1.0f)) + b);
|
||||
|
||||
return (c/2.0f*(-pow(2.0f, -10.0f*(t - 1.0f)) + 2.0f) + b);
|
||||
}
|
||||
|
||||
// Back Easing functions
|
||||
EASEDEF float EaseBackIn(float t, float b, float c, float d)
|
||||
EASEDEF float EaseBackIn(float t, float b, float c, float d)
|
||||
{
|
||||
float s = 1.70158f;
|
||||
float postFix = t/=d;
|
||||
return (c*(postFix)*t*((s + 1)*t - s) + b);
|
||||
return (c*(postFix)*t*((s + 1.0f)*t - s) + b);
|
||||
}
|
||||
|
||||
EASEDEF float EaseBackOut(float t, float b, float c, float d)
|
||||
{
|
||||
{
|
||||
float s = 1.70158f;
|
||||
t = t/d - 1;
|
||||
return (c*(t*t*((s + 1)*t + s) + 1) + b);
|
||||
t = t/d - 1.0f;
|
||||
return (c*(t*t*((s + 1.0f)*t + s) + 1.0f) + b);
|
||||
}
|
||||
|
||||
EASEDEF float EaseBackInOut(float t, float b, float c, float d)
|
||||
{
|
||||
float s = 1.70158f;
|
||||
if ((t/=d/2) < 1)
|
||||
if ((t/=d/2.0f) < 1.0f)
|
||||
{
|
||||
s *= 1.525f;
|
||||
return (c/2*(t*t*((s + 1)*t - s)) + b);
|
||||
return (c/2.0f*(t*t*((s + 1.0f)*t - s)) + b);
|
||||
}
|
||||
|
||||
float postFix = t-=2;
|
||||
|
||||
float postFix = t-=2.0f;
|
||||
s *= 1.525f;
|
||||
return (c/2*((postFix)*t*((s + 1)*t + s) + 2) + b);
|
||||
return (c/2.0f*((postFix)*t*((s + 1.0f)*t + s) + 2.0f) + b);
|
||||
}
|
||||
|
||||
// Bounce Easing functions
|
||||
EASEDEF float EaseBounceOut(float t, float b, float c, float d)
|
||||
EASEDEF float EaseBounceOut(float t, float b, float c, float d)
|
||||
{
|
||||
if ((t/=d) < (1/2.75f))
|
||||
if ((t/=d) < (1.0f/2.75f))
|
||||
{
|
||||
return (c*(7.5625f*t*t) + b);
|
||||
}
|
||||
else if (t < (2/2.75f))
|
||||
}
|
||||
else if (t < (2.0f/2.75f))
|
||||
{
|
||||
float postFix = t-=(1.5f/2.75f);
|
||||
return (c*(7.5625f*(postFix)*t + 0.75f) + b);
|
||||
}
|
||||
else if (t < (2.5/2.75))
|
||||
}
|
||||
else if (t < (2.5/2.75))
|
||||
{
|
||||
float postFix = t-=(2.25f/2.75f);
|
||||
return (c*(7.5625f*(postFix)*t + 0.9375f) + b);
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
float postFix = t-=(2.625f/2.75f);
|
||||
return (c*(7.5625f*(postFix)*t + 0.984375f) + b);
|
||||
}
|
||||
}
|
||||
|
||||
EASEDEF float EaseBounceIn(float t, float b, float c, float d) { return (c - EaseBounceOut(d-t, 0, c, d) + b); }
|
||||
EASEDEF float EaseBounceInOut(float t, float b, float c, float d)
|
||||
EASEDEF float EaseBounceIn(float t, float b, float c, float d) { return (c - EaseBounceOut(d - t, 0.0f, c, d) + b); }
|
||||
EASEDEF float EaseBounceInOut(float t, float b, float c, float d)
|
||||
{
|
||||
if (t < d/2) return (EaseBounceIn(t*2, 0, c, d)*0.5f + b);
|
||||
else return (EaseBounceOut(t*2-d, 0, c, d)*0.5f + c*0.5f + b);
|
||||
if (t < d/2.0f) return (EaseBounceIn(t*2.0f, 0.0f, c, d)*0.5f + b);
|
||||
else return (EaseBounceOut(t*2.0f - d, 0.0f, c, d)*0.5f + c*0.5f + b);
|
||||
}
|
||||
|
||||
// Elastic Easing functions
|
||||
EASEDEF float EaseElasticIn(float t, float b, float c, float d)
|
||||
EASEDEF float EaseElasticIn(float t, float b, float c, float d)
|
||||
{
|
||||
if (t == 0) return b;
|
||||
if ((t/=d) == 1) return (b + c);
|
||||
|
||||
if (t == 0.0f) return b;
|
||||
if ((t/=d) == 1.0f) return (b + c);
|
||||
|
||||
float p = d*0.3f;
|
||||
float a = c;
|
||||
float s = p/4;
|
||||
float postFix = a*pow(2, 10*(t-=1));
|
||||
|
||||
return (-(postFix*sin((t*d-s)*(2*PI)/p )) + b);
|
||||
float a = c;
|
||||
float s = p/4.0f;
|
||||
float postFix = a*pow(2.0f, 10.0f*(t-=1.0f));
|
||||
|
||||
return (-(postFix*sin((t*d-s)*(2.0f*PI)/p )) + b);
|
||||
}
|
||||
|
||||
EASEDEF float EaseElasticOut(float t, float b, float c, float d)
|
||||
{
|
||||
if (t == 0) return b;
|
||||
if ((t/=d) == 1) return (b + c);
|
||||
|
||||
if (t == 0.0f) return b;
|
||||
if ((t/=d) == 1.0f) return (b + c);
|
||||
|
||||
float p = d*0.3f;
|
||||
float a = c;
|
||||
float s = p/4;
|
||||
|
||||
return (a*pow(2,-10*t)*sin((t*d-s)*(2*PI)/p) + c + b);
|
||||
float a = c;
|
||||
float s = p/4.0f;
|
||||
|
||||
return (a*pow(2.0f,-10.0f*t)*sin((t*d-s)*(2.0f*PI)/p) + c + b);
|
||||
}
|
||||
|
||||
EASEDEF float EaseElasticInOut(float t, float b, float c, float d)
|
||||
{
|
||||
if (t == 0) return b;
|
||||
if ((t/=d/2) == 2) return (b + c);
|
||||
|
||||
if (t == 0.0f) return b;
|
||||
if ((t/=d/2.0f) == 2.0f) return (b + c);
|
||||
|
||||
float p = d*(0.3f*1.5f);
|
||||
float a = c;
|
||||
float s = p/4;
|
||||
float s = p/4.0f;
|
||||
|
||||
if (t < 1)
|
||||
if (t < 1.0f)
|
||||
{
|
||||
float postFix = a*pow(2, 10*(t-=1));
|
||||
return -0.5f*(postFix*sin((t*d-s)*(2*PI)/p)) + b;
|
||||
float postFix = a*pow(2.0f, 10.0f*(t-=1.0f));
|
||||
return -0.5f*(postFix*sin((t*d-s)*(2.0f*PI)/p)) + b;
|
||||
}
|
||||
|
||||
float postFix = a*pow(2, -10*(t-=1));
|
||||
|
||||
return (postFix*sin((t*d-s)*(2*PI)/p)*0.5f + c + b);
|
||||
|
||||
float postFix = a*pow(2.0f, -10.0f*(t-=1.0f));
|
||||
|
||||
return (postFix*sin((t*d-s)*(2.0f*PI)/p)*0.5f + c + b);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue