C 实现通用Tween缓动动画(3)快捷链式调用接口

本文介绍了一种简化Tween动画设置的方法,通过构建上下文来缓存链式调用中创建的对象,实现更简洁的动画控制流程。适用于需要频繁设置动画属性的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  Tween创建action有很多属性设置,不同的动画效果,需要不同的属性控制。多个action的动画需要多次设置,使用起来十分不方便,还要创建临时数组存放一组action。通常,tween的参数设置会使用链式调用,形成一组连续的控制。在面向对象中上下文可以获得当前对象,但在C中无法获得。往往在C中方法设置一个对象的属性,需要把当前对象手动传进去非常不方便。所以,我们需要构建一个上下文,保存链式调用中创建的对象,好像方法不需要每次都传入当前对象。


   在Tween的实现函数之上,将会封装一套便捷的使用接口,完成以下功能。

  • 链式调用创建多个action并执行
  • 链式调用设置action和actionValue的属性
  • 缓存当前创建的action作为调用方法的上下文
  • 缓存actionValueIndex作为调用方法的上下文

   完整实现代码如下:

   
/*
 * TweenTool.h
 *
 *  Created on: 2016-6-24
 *      Author: scott.cgi
 */

#ifndef tween_tool_h_
#define tween_tool_h_

#include <stdbool.h>
#include "Mojoc/Toolkit/Utils/Tween.h"


typedef struct
{
	TweenActionValueOnGet get;
	TweenActionValueOnSet set;
}
TweenActionValueCallback;


typedef struct _ATweenTool_ _ATweenTool_;
struct _ATweenTool_
{
	/**
	 * Create one TweenAction in context for chain setting
	 **/

	_ATweenTool_* (*CreateAction)    (int actionValueCount);


	/**
	 * Create one TweenAction with one action value in context for chain setting
	 */
	_ATweenTool_* (*CreateActionOne) (TweenActionValueCallback valueCallback, float value, float duration);


	/**
	 * Create action with no actionValue, so actionValueCount is 0
	 * just through duration time then callback
	 */
	_ATweenTool_* (*CreateInterval)  (float duration);


	/**
	 * Set TweenAction property for current context created
	 **/


	_ATweenTool_* (*SetDuration)     (float                    duration);
	_ATweenTool_* (*SetUserData)     (void*                    userData);
	_ATweenTool_* (*SetQueue)        (bool                     isQueue);
	_ATweenTool_* (*SetOnComplete)   (TweenActionOnComplete    OnComplete);
	_ATweenTool_* (*SetTarget)       (void*                    target);

	/**
	 * Get TweenAction in current context
	 */
	_ATweenTool_* (*GetAction)       (TweenAction**            outActionPtr);



	/**
	 * Set TweenActionValue property for current context created
	 **/


	_ATweenTool_* (*SetRelative)     (bool                     isRelative);
	_ATweenTool_* (*SetEaseType)     (TweenEaseType            easeType);

	/**
	 * Update new value index, and index must smaller than actionValueCount
	 * after, each set TweenActionValue property will on this current index
	 */
	_ATweenTool_* (*SetValue)        (TweenActionValueCallback valueCallback, float value);


	/**
	 * Run actions all in current context, set action target if has actionValue
	 * and use target be tweenId
	 */
	void          (*RunActions)      (void* target);

	/**
	 * Run actions all in current context, action must set target if has actionValue
	 * and return tweenId
	 */
	void*         (*RunTargets)      ();

};

extern _ATweenTool_ ATweenTool[1];

#endif

/*
 * TweenTool.c
 *
 *  Created on: 2016-6-24
 *      Author: scott.cgi
 */

#include "Mojoc/Toolkit/Utils/TweenTool.h"
#include "Mojoc/Toolkit/Platform/Log.h"
#include "Mojoc/Toolkit/Utils/Array.h"

#define action_length 30

static Array(TweenAction*) actionArr[1] =
{
	(TweenAction*[action_length]) {},
	0
};

static TweenAction* action      = NULL;
static int          valueCount  =  0;
static int          valueIndex  = -1;


#define CheckAction(tag) \
	ALog_A(action, "ATweenTool " tag " TweenAction not created");

#define CheckIndex(tag, actionValueIndex) \
	ALog_A(valueIndex > -1 && actionValueIndex < valueCount, "ATweenTool " tag " actionValueIndex invalid");

static _ATweenTool_* CreateAction(int actionValueCount)
{
	ALog_A
	(
		actionArr->length <=  action_length,
		"ATweenTool can not cache TweenActions = %d more than %d",
		actionArr->length,
		action_length
	);

	action     = ATween->CreateAction(actionValueCount);
	valueCount = actionValueCount;
    valueIndex = -1;

	AArray_Set
	(
		actionArr,
		actionArr->length++,
		action,
		TweenAction*
	);

	return ATweenTool;
}

static _ATweenTool_* CreateActionOne(TweenActionValueCallback valueCallback, float value, float duration)
{
	return CreateAction(1)->SetValue(valueCallback, value)->SetDuration(duration);
}

static _ATweenTool_* CreateInterval(float duration)
{
	return CreateAction(0)->SetDuration(duration);
}


static _ATweenTool_* SetDuration(float duration)
{
	CheckAction("SetDuration");
	action->duration = duration;

	return ATweenTool;
}


static _ATweenTool_* SetUserData(void* userData)
{
	CheckAction("SetUserData");
	action->userData = userData;

	return ATweenTool;
}

static _ATweenTool_* SetQueue(bool isQueue)
{
	CheckAction("SetQueue");
	action->isQueue = isQueue;

	return ATweenTool;
}

static _ATweenTool_* SetOnComplete(TweenActionOnComplete OnComplete)
{
	CheckAction("SetOnComplete");
	action->OnComplete = OnComplete;

	return ATweenTool;
}

static _ATweenTool_* SetTarget(void* target)
{
	CheckAction("SetTarget");
	action->target = target;

	return ATweenTool;
}

static _ATweenTool_* GetAction(TweenAction** outActionPtr)
{
	CheckAction("GetAction");
	*outActionPtr = action;

	return ATweenTool;
}


static _ATweenTool_* SetRelative(bool isRelative)
{
	CheckAction("SetRelative");
	CheckIndex("SetRelative", valueIndex);
	action->actionValues[valueIndex].isRelative = isRelative;

	return ATweenTool;
}

static _ATweenTool_* SetEaseType(TweenEaseType easeType)
{
	CheckAction("SetEaseType");
	CheckIndex ("SetEaseType", valueIndex);
	action->actionValues[valueIndex].easeType = easeType;

	return ATweenTool;
}



static _ATweenTool_* SetValue(TweenActionValueCallback valueCallback, float value)
{
	valueIndex++;

	CheckAction("SetValue");
	CheckIndex ("SetValue", valueIndex);

	action->actionValues[valueIndex].OnGet = valueCallback.get;
	action->actionValues[valueIndex].OnSet = valueCallback.set;
	action->actionValues[valueIndex].value = value;

	return ATweenTool;
}


static void RunActions(void* target)
{
	ALog_A(target, "RunActions, target must not NULL");

	for (int i = 0; i < actionArr->length; i++)
	{
		TweenAction* action = AArray_Get(actionArr, i, TweenAction*);

		if (action->actionValueCount > 0)
		{
			action->target = target;
		}
	}

	ATween->RunActions(actionArr, &target);

	actionArr->length = 0;
    action            = NULL;
}


static void* RunTargets()
{
	for (int i = 0; i < actionArr->length; i++)
	{
		TweenAction* action = AArray_Get(actionArr, i, TweenAction*);

		if (action->actionValueCount > 0)
		{
			ALog_A
			(
				 action->target,
				"RunActions, the {%d} action value count is 0 so must set target",
				i
			);
		}
	}

	void* tweenId = NULL;

	ATween->RunActions(actionArr, &tweenId);

	actionArr->length = 0;
    action            = NULL;

    return tweenId;
}

_ATweenTool_ ATweenTool[1] =
{
	CreateAction,
	CreateActionOne,
	CreateInterval,

	SetDuration,
	SetUserData,
	SetQueue,
	SetOnComplete,
	SetTarget,
	GetAction,

	SetRelative,
	SetEaseType,
	SetValue,

	RunActions,
	RunTargets,
};


    这套结构和算法可以更加容易的用面向对象语言改写。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值