/* 缓动插值 全套缓动函数的 js 实现 https://www.jianshu.com/p/ddff577138bf 缓动函数图形说明 http://www.xuanfengge.com/easeing/easeing/ */ #pragma once #include "gstl.h" class GachaEase { public: static float getEasePercent(float pct,const string& strEaseFunc); static float linear(float pct); static float easeInSine(float pct); static float easeOutSine(float pct); static float easeInOutSine(float pct); static float easeInQuad(float pct); static float easeOutQuad(float pct); static float easeInOutQuad(float pct); static float easeInCubic(float pct); static float easeOutCubic(float pct); static float easeInOutCubic(float pct); static float easeInQuart(float pct); static float easeOutQuart(float pct); static float easeInOutQuart(float pct); static float easeInOutBack(float pct); static float easeInElastic(float pct); static float easeInBack(float pct); static float easeOutBack(float pct); static float easeOutBounce(float pct); static float easeInCirc(float pct); static float easeOutCirc(float pct); static float easeInOutCirc(float pct); private: static float bounceOut(float pct); public: const static float PI; const static float c1; const static float c2; const static float c3; const static float c4; const static float c5; };
#include "GachaEase.h" #include <map> #include <functional> #define REGIST_EASE_FUNC(ease_name) funcmap.insert(std::make_pair(#ease_name, std::bind(GachaEase::ease_name, std::placeholders::_1))) const float GachaEase::PI = 3.1415926; const float GachaEase::c1 = 1.70158; const float GachaEase::c2 = c1 * 1.525; const float GachaEase::c3 = c1 + 1; const float GachaEase::c4 = (2 * PI) / 3; const float GachaEase::c5 = (2 * PI) / 4.5; static std::map<string, std::function<float(float)>> funcmap; /*static*/ float clampf(float& v, float min, float max) { if (v < min) v = min; if (v > max) v = max; return v; } static void initFuncMap() { //funcmap.insert(std::make_pair("linear", std::bind(GachaEase::linear, std::placeholders::_1))); REGIST_EASE_FUNC(linear); REGIST_EASE_FUNC(easeInSine); REGIST_EASE_FUNC(easeOutSine); REGIST_EASE_FUNC(easeInOutSine); REGIST_EASE_FUNC(easeInQuad); REGIST_EASE_FUNC(easeOutQuad); REGIST_EASE_FUNC(easeInOutQuad); REGIST_EASE_FUNC(easeInCubic); REGIST_EASE_FUNC(easeOutCubic); REGIST_EASE_FUNC(easeInOutCubic); REGIST_EASE_FUNC(easeInQuart); REGIST_EASE_FUNC(easeOutQuart); REGIST_EASE_FUNC(easeInOutQuart); REGIST_EASE_FUNC(easeInOutBack); REGIST_EASE_FUNC(easeInElastic); REGIST_EASE_FUNC(easeInBack); REGIST_EASE_FUNC(easeOutBack); REGIST_EASE_FUNC(easeOutBounce); } float GachaEase::getEasePercent(float pct, const string& strEaseFunc) { if (funcmap.empty()) { initFuncMap(); } auto it = funcmap.find(strEaseFunc); if (it != funcmap.end()) { float fEasePct = it->second(pct); return fEasePct; } return linear(pct); } float GachaEase::linear(float pct) { return clampf(pct, 0.f, 1.f); } float GachaEase::easeInCubic(float pct) { clampf(pct, 0.f, 1.f); pct = pct * pct * pct; return pct; } float GachaEase::easeOutCubic(float pct) { clampf(pct, 0.f, 1.f); return 1 - pow(1 - pct, 3); } float GachaEase::easeInOutCubic(float pct) { clampf(pct, 0.f, 1.f); if (pct < 0.5) { return 4 * pct * pct * pct; } else { return 1 - pow(-2 * pct + 2, 3) / 2; } } float GachaEase::easeInOutBack(float pct) { clampf(pct, 0.f, 1.f); pct = pct < 0.5 ? (pow(2 * pct, 2)*((c2 + 1) * 2 * pct - c2)) / 2 : (pow(2 * pct - 2, 2)*((c2 + 1)*(pct * 2 - 2) + c2) + 2) / 2; return pct; } float GachaEase::easeInElastic(float pct) { clampf(pct, 0.f, 1.f); if (pct <= 0.f) { return 0; } if (pct >= 1.f) { return 1; } return -pow(2, 10 * pct - 10)* sin((pct * 10 - 10.75)* c4); } float GachaEase::easeInSine(float pct) { clampf(pct, 0.f, 1.f); return 1 - cos(pct * PI / 2); } float GachaEase::easeOutSine(float pct) { clampf(pct, 0.f, 1.f); return sin(pct * PI / 2); } float GachaEase::easeInOutSine(float pct) { clampf(pct, 0.f, 1.f); return -(cos(PI * pct) - 1) / 2; } float GachaEase::easeInQuad(float pct) { clampf(pct, 0.f, 1.f); return pct * pct; } float GachaEase::easeOutQuad(float pct) { clampf(pct, 0.f, 1.f); return 1 - (1 - pct)*(1 - pct); } float GachaEase::easeInOutQuad(float pct) { clampf(pct, 0.f, 1.f); if (pct < 0.5) { return 2 * pct * pct; } else { return 1 - pow(-2 * pct + 2, 2) / 2; } } float GachaEase::easeInQuart(float pct) { clampf(pct, 0.f, 1.f); return pct * pct * pct * pct; } float GachaEase::easeOutQuart(float pct) { clampf(pct, 0.f, 1.f); return 1 - pow(1 - pct, 4); } float GachaEase::easeInOutQuart(float pct) { clampf(pct, 0.f, 1.f); if (pct < 0.5) { return 8 * pct * pct * pct * pct; } else { return 1 - pow(-2 * pct + 2, 4) / 2; } } float GachaEase::easeInBack(float pct) { clampf(pct, 0.f, 1.f); return c3 * pct * pct * pct - c1 * pct * pct; } float GachaEase::easeOutBack(float pct) { return 1 + c3 * pow(pct - 1, 3) + c1 * pow(pct - 1, 2); } float GachaEase::easeOutBounce(float pct) { return bounceOut(pct); } float GachaEase::bounceOut(float pct) { float n1 = 7.5625; float d1 = 2.75; if (pct < 1 / d1) { return n1*pct*pct; } else if (pct < 2 / d1) { return n1*(pct -= (1.5 / d1))*pct + .75; } else if (pct < 2.5 / d1) { return n1*(pct -= (2.25 / d1))*pct + .9375; } else { return n1*(pct -= (2.625 / d1))*pct + .984375; } }