Sweet Snippet 之 PlayMode实现

本文简述了一种 PlayMode 的实现方式

PlayMode(播放模式)应该是编程开发中常见的概念,一般来讲有以下几种播放模式:

enum class EPlayMode : uint8
{
	Once, // 单次播放
	Loop, // 循环播放
	PingPong, // 往返播放
};

总结来讲, PlayMode 影响的是 时间因子(TimeFactor) 的计算,我们可以抽象出以下结构来进行实现说明:

class CPlayMode
{
public:
    CPlayMode(EPlayMode Mode_, float Duration_) :
        Mode(Mode_),
        Duration(Duration_),
        Elapsed(0)
    {
    }
    
    void Update(float DeltaTime);
	float GetFactor() const;
    
protected:    
	EPlayMode Mode;
    float Duration;
    float Elapsed;
};

开始实现之前,我们先定义几个辅助函数:

float FloatDivide(float Dividend, float Divisor)
{
	if (Divisor != 0)
	{
		return Dividend / Divisor;
	}

	return 0;
}

float FloatModulo(float Dividend, float Divisor)
{
    if (Divisor != 0)
    {
        return Dividend - ((int)(Dividend / Divisor)) * Divisor;
    }
	
	return 0;
}

作用就是处理浮点数的除法和取模(用以解决除零等问题).

之后便是正式的实现了:

void CPlayMode::Update(float DeltaTime)
{
	switch (Mode)
	{
		case EPlayMode::Once:
		{
			Elapsed += DeltaTime;
			if (Elapsed > Duration)
			{
				Elapsed = Duration;
			}
		}
		break;
		case EPlayMode::Loop:
		{
			Elapsed += DeltaTime;
			if (Elapsed > Duration)
			{
				Elapsed = FloatModulo(Elapsed, Duration);
			}
		}
		break;
		case EPlayMode::PingPong:
		{
			Elapsed += DeltaTime;

			float LoopDuration = 2.0f * Duration;
			if (Elapsed > LoopDuration)
			{
				Elapsed = FloatModulo(Elapsed, LoopDuration);
			}
		}
		break;
	}
}

Update 函数主要用于更新 Elapsed:

  • 对于 Once 模式,直接使用 Duration 截断 Elapsed
  • 对于 Loop 模式,简单处理的话可以直接 Elapsed - Duration(当 Elapsed 超过 Duration 时),但是使用 FloatModulo 会更健壮一些(可以处理 DeltaTime 过大的情况)
  • 对于 PingPong 模式,处理上会取巧一些,直接将往返一次算作一次循环,这样处理上就和 Loop 模式类似了(原本的 Duration 需要加倍)

GetFactor 就是按照 Elapsed 获取当前的 TimeFactor :

float CPlayMode::GetFactor() const
{
	switch (Mode)
	{
	case EPlayMode::Once:
	case EPlayMode::Loop:
	{
		return FloatDivide(Elapsed, Duration);
	}
	case EPlayMode::PingPong:
	{
	    if (Elapsed <= Duration)
		{
		    return FloatDivide(Elapsed, Duration);
		}
		else
		{
			return 1.0f - FloatDivide(Elapsed - Duration, Duration);
		}
	}
	}

	return 0;
}

其中 PingPong 模式的处理会有些特殊,但是了解了上面 Elapsed 的处理方式(PingPong 模式下)就容易理解了,有兴趣的朋友可以细看一下.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值