C++实现缓动动画效果,使用Tween算法(含详细代码)

本人微信公众号:CPP进阶之旅
如果觉得这篇文章对您有帮助,欢迎关注 “CPP进阶之旅” 学习更多技术干货

C++实现缓动动画效果,使用Tween算法(含详细代码)

1、简介

在实际的项目开发中,遇到需要通过算法为程序提供流畅的显示效果的时候,我们通常需要借助计时器和位置计算的算法来实现。这里的Tween就是一个缓动数据计算的类,有了tween算法,我们就可以在此基础上,根据具体的业务调整数据实现流畅的缓动效果了。

2、代码

#pragma once
// Algorithm Reference:
//http://www.cnblogs.com/cloudgamer/archive/2009/01/06/Tween.html
 
#ifndef PI
#define PI	3.1415926f
#endif
const float EPSINON = 0.000001f;
#define EQUAL_ZERO(x) ((x >= - EPSINON) && (x <= EPSINON)) ? true : false
/*
缓动函数介绍:
easeIn:速度从0开始加速的缓动
easeOut:减速到0的缓动
easeInOut:速度的前半段从0开始加速,后半段减速到0的缓动。
*/ 
class CPPTween
{
public:
	CPPTween(void);
	~CPPTween(void);
 
	// Linear 匀速
	float Linear_easeIn(float t, float b, float c, float d);
	float Linear_easeOut(float t, float b, float c, float d);
	float Linear_easeInOut(float t, float b, float c, float d);
 
	// Quadratic 二次方的缓动(t^2)
	float Quad_easeIn(float t, float b, float c, float d);
	float Quad_easeOut(float t, float b, float c, float d);
	float Quad_easeInOut(float t, float b, float c, float d);
 
	// Cubic三次方的缓动(t^3)
	float Cubic_easeIn(float t, float b, float c, float d);
	float Cubic_easeOut(float t, float b, float c, float d);
	float Cubic_easeInOut(float t, float b, float c, float d);
 
	// Quartic四次方的缓动(t^4)
	float Quart_easeIn(float t, float b, float c, float d);
	float Quart_easeOut(float t, float b, float c, float d);
	float Quart_easeInOut(float t, float b, float c, float d);
 
	// Quintic五次方的缓动
	float Quint_easeIn(float t, float b, float c, float d);
	float Quint_easeOut(float t, float b, float c, float d);
	float Quint_easeInOut(float t, float b, float c, float d);
 
	// Sinusoidal正弦曲线的缓动(sin(t))
	float Sine_easeIn(float t, float b, float c, float d);
	float Sine_easeOut(float t, float b, float c, float d);
	float Sine_easeInOut(float t, float b, float c, float d);
 
	// Exponential指数曲线的缓动(2^t)
	float Expo_easeIn(float t, float b, float c, float d);
	float Expo_easeOut(float t, float b, float c, float d);
	float Expo_easeInOut(float t, float b, float c, float d);
 
	// Circular圆形曲线的缓动sqrt(1-t^2)
	float Circ_easeIn(float t, float b, float c, float d);
	float Circ_easeOut(float t, float b, float c, float d);
	float Circ_easeInOut(float t, float b, float c, float d);
 
	// Elastic指数衰减的正弦曲线缓动
	float Elastic_easeIn(float t, float b, float c, float d, float a = 0.0f, float p = 0.0f);
	float Elastic_easeOut(float t, float b, float c, float d, float a = 0.0f, float p = 0.0f);
	float Elastic_easeInOut(float t, float b, float c, float d, float a = 0.0f, float p = 0.0f);
 
	// Back超过范围的三次方缓动((s+1)*t^3 - s*t^2)
	float Back_easeIn(float t, float b, float c, float d, float s = 0.0f);
	float Back_easeOut(float t, float b, float c, float d, float s = 0.0f);
	float Back_easeInOut(float t, float b, float c, float d, float s = 0.0f);
 
	// Bounce指数衰减的反弹缓动
	float Bounce_easeOut(float t, float b, float c, float d);
	float Bounce_easeIn(float t, float b, float c, float d);
	float Bounce_easeInOut(float t, float b, float c, float d);
 
public:
	//t: current time(当前时间);
	//b: beginning value(初始值);
	//c: change in value(变化量);
	//d: duration(持续时间)。
	float t, b, c, d, p;
};
#include "CPPTween.h"
#include <math.h>

CPPTween::CPPTween(void)
{
}
 
CPPTween::~CPPTween(void)
{
}
 
// Linear
float CPPTween::Linear_easeIn(float t, float b, float c, float d)
{
	return c * t / d + b;
}
 
float CPPTween::Linear_easeOut(float t, float b, float c, float d)
{
	return c * t / d + b;
}
 
float CPPTween::Linear_easeInOut(float t, float b, float c, float d)
{
	return c * t / d + b;
}
 
// Quadratic
float CPPTween::Quad_easeIn(float t, float b, float c, float d)
{
	return c * (t /= d) * t + b;
}
 
float CPPTween::Quad_easeOut(float t, float b, float c, float d)
{
	return -c * (t /= d) * (t - 2) + b;
}
 
float CPPTween::Quad_easeInOut(float t, float b, float c, float d)
{
	if ((t /= d / 2) < 1)
		return c / 2 * t * t + b;
	return -c / 2 * ((--t) * (t - 2) - 1) + b;
}
 
// Cubic
float CPPTween::Cubic_easeIn(float t, float b, float c, float d)
{
	return c * (t /= d) * t * t + b;
}
 
float CPPTween::Cubic_easeOut(float t, float b, float c, float d)
{
	return c * ((t = t / d - 1) * t * t + 1) + b;
}
 
float CPPTween::Cubic_easeInOut(float t, float b, float c, float d)
{
	if ((t /= d / 2) < 1)
		return c / 2 * t * t * t + b;
	return c / 2 * ((t -= 2) * t * t + 2) + b;
}
 
// Quartic
float CPPTween::Quart_easeIn(float t, float b, float c, float d)
{
	return c * (t /= d) * t * t * t + b;
}
 
float CPPTween::Quart_easeOut(float t, float b, float c, float d)
{
	return -c * ((t = t / d - 1) * t * t * t - 1) + b;
}
 
float CPPTween::Quart_easeInOut(float t, float b, float c, float d)
{
	if ((t /= d / 2) < 1)
		return c / 2 * t * t * t * t + b;
	return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
}
 
// Quintic
float CPPTween::Quint_easeIn(float t, float b, float c, float d)
{
	return c * (t /= d) * t * t * t * t + b;
}
 
float CPPTween::Quint_easeOut(float t, float b, float c, float d)
{
	return c * ((t = t / d - 1)* t * t * t * t + 1) + b;
}
 
float CPPTween::Quint_easeInOut(float t, float b, float c, float d)
{
	if ((t /= d / 2) < 1)
		return c / 2 * t * t * t * t * t + b;
	return c / 2 * ((t -= 2) * t * t * t * t + 2) + b;
}
 
// Sinusoidal
float CPPTween::Sine_easeIn(float t, float b, float c, float d)
{
	return -c * cos(t / d * (PI / 2)) + c + b;
}
 
float CPPTween::Sine_easeOut(float t, float b, float c, float d)
{
	return c * sin(t / d * (PI / 2)) + b;
}
 
float CPPTween::Sine_easeInOut(float t, float b, float c, float d)
{
	return -c / 2 * (cos(PI * t/ d) - 1) + b;
}
 
// Exponential
float CPPTween::Expo_easeIn(float t, float b, float c, float d)
{
	return (t == 0) ? b : c * pow(2, 10 * (t / d - 1)) + b;
}
 
float CPPTween::Expo_easeOut(float t, float b, float c, float d)
{
	return (t == d) ? b + c : c * (-pow(2, -10 * t / d) + 1) + b;
}
 
float CPPTween::Expo_easeInOut(float t, float b, float c, float d)
{
	if (t == 0)
		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;
}
 
// Circular
float CPPTween::Circ_easeIn(float t, float b, float c, float d)
{
	return -c * (sqrt(1 - (t /= d) * t) - 1) + b;
}
 
float CPPTween::Circ_easeOut(float t, float b, float c, float d)
{
	return c * sqrt(1 - (t = t / d - 1) * t) + b;
}
 
float CPPTween::Circ_easeInOut(float t, float b, float c, float d)
{
	if ((t /= d / 2) < 1)
		return -c / 2 * (sqrt(1 - t * t) - 1) + b;
	return c / 2 * (sqrt(1 - (t -= 2) * t) + 1) + b;
}
 
// Elastic
float CPPTween::Elastic_easeIn(float t, float b, float c, float d, float a/* = 0.0f*/, float p/* = 0.0f*/)
{
	float s = 0;
	if (t == 0)
		return b;
	if ((t /= d) == 1)
		return b + c;
	if (!p)
		p = d * .3f;
	if (!a || a < fabsf(c))
	{
		a = c;
		s = p/4;
	}
	else
		s = p / (2 * PI) * asin (c / a);
	return -(a * pow(2, 10 * (t -= 1)) * sin((t * d - s) * (2 * PI) / p)) + b;
}
 
float CPPTween::Elastic_easeOut(float t, float b, float c, float d, float a/* = 0.0f*/, float p/* = 0.0f*/)
{
	float s = 0;
	if (t == 0)
		return b;
	if ((t /= d) == 1)
		return (b + c);
	if (!p)
		p = d *.3f;
	if (!a || a < fabsf(c))
	{
		a = c;
		s = p / 4;
	}
	else
		s = p / (2 * PI) * sin((float)c / a);
 
	return (a * pow(2.0f, (int) - 10 * t) * sin((t * d - s) * (2 * PI) / p) + c + b);
}
 
float CPPTween::Elastic_easeInOut(float t, float b, float c, float d, float a/* = 0.0f*/, float p/* = 0.0f*/)
{
	float s = 0;
	if (t == 0)
		return b;
	if ((t /= d / 2) == 2)
		return b + c;
	if (!p)
		p = d * (.3f * 1.5f);
	if (!a || a < fabsf(c))
	{
		a = c;
		s = p/4;
	}
	else
		s = p / (2 * PI) * asin (c / a);
	if (t < 1)
		return -.5f * (a * pow(2, 10 * (t -= 1)) * sin( (t * d - s) * (2 * PI) / p )) + b;
	return a * pow(2, -10 * (t -= 1)) * sin((t * d - s) * (2 * PI) / p ) * .5f + c + b;
}
 
// Back
float CPPTween::Back_easeIn(float t, float b, float c, float d, float s/* = 0.0f*/)
{
	if (EQUAL_ZERO(s))
		s = 1.70158f;
	return c * (t /= d) * t * ((s + 1) * t - s) + b;
}
 
float CPPTween::Back_easeOut(float t, float b, float c, float d, float s/* = 0.0f*/)
{
	if (EQUAL_ZERO(s))
		s = 1.70158f;
	return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
}
 
float CPPTween::Back_easeInOut(float t, float b, float c, float d, float s/* = 0.0f*/)
{
	if (EQUAL_ZERO(s))
		s = 1.70158f;
	if ((t /= d / 2) < 1)
		return c / 2 * (t * t * (((s *= (1.525f)) + 1) * t - s)) + b;
	return c / 2 * ((t -= 2) * t * (((s *= (1.525f)) + 1) * t + s) + 2) + b;
}
 
// Bounce
float CPPTween::Bounce_easeOut(float t, float b, float c, float d)
{
	if ((t /= d) < (1 / 2.75))
	{
		return c * (7.5625f * t * t) + b;
	}
	else if (t < (2 / 2.75))
	{
		return c * (7.5625f * (t -= (1.5f / 2.75f)) * t + .75f) + b;
	}
	else if (t < (2.5 / 2.75))
	{
		return c * (7.5625f * (t -= (2.25f / 2.75f)) * t + .9375f) + b;
	}
	else
	{
		return c * (7.5625f * (t -= (2.625f / 2.75f)) * t + .984375f) + b;
	}
}
 
float CPPTween::Bounce_easeIn(float t, float b, float c, float d)
{
	return c - Bounce_easeOut(d - t, 0, c, d) + b;
}
 
float CPPTween::Bounce_easeInOut(float t, float b, float c, float d)
{
	if (t < d / 2)
		return Bounce_easeIn(t * 2, 0, c, d) * .5f + b;
	else return Bounce_easeOut(t * 2 - d, 0, c, d) * .5f + c * .5f + b;
}

3、重要说明

欢迎大家关注我的个人微信公众号,查看专业的客户端/服务端开发知识、笔试面试题目、程序员职场经验与心得分享。
在这里插入图片描述

参考博文:
https://www.cnblogs.com/cloudgamer/archive/2009/01/06/Tween.html

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值