綜述
這篇教程介紹了什么是特效以及如何創(chuàng)建它們
特效是建立在曲線集(線、三角形、矩形、)之上的,它們具有不同參數(shù)如:大小、旋度、位置、速度、顏色等。
特效在配置文件中設(shè)置,僅僅只需要一行代碼就可以在對象上使用這些特效。
8條任意類型的曲線組合在一起就可以形成一個特效。
在同一時間,可以有多達(dá)4個特效應(yīng)用于同一個對象上面。
特效可以使用絕對值或者相對值,這取決于配置文件中Absolute標(biāo)簽。
控制曲線的周期、相位、和大小都是允許的。
對于位置和速度特效,輸出值可以使用對象的原始大小,這是為了可以更貼近對象當(dāng)前的狀態(tài)。這也就允許我們創(chuàng)造極其拉風(fēng)的視覺特效。
除非特效已經(jīng)緩存在內(nèi)存中,否則特效參數(shù)全部在配置文件中進(jìn)行調(diào)整,并且使用退格鍵來即時重載。
比如說:你不能調(diào)整正在運(yùn)行的循環(huán)特效,因?yàn)樗呀?jīng)在默認(rèn)的配置文件中定義好了。在這個測試程序運(yùn)行的時候,所有其它的特效能夠被更新。
通常說來,隨機(jī)值的使用可以給特效帶來更多的變化。
比如:搖擺的刻度(譯者:實(shí)在不知如何翻譯這個詞組 the wobble scale),閃光色調(diào)還有那個攻擊特效都是用了少量的隨機(jī)值。
為了顯示特效播放和停止,我們也需要注冊特效事件。
因?yàn)樘匦窃谝粋€標(biāo)記為循環(huán)模式的盒對象上面,所以它不會停下來。因此,同步事件(orxFX_EVENT_STOP)將永遠(yuǎn)不會被發(fā)送出去。
我們也會簡單的介紹一下如何一些個性數(shù)據(jù)到orxOBJECT(這里包換一個boolean值)中。
在事件的回調(diào)函數(shù)中,我們通過它,在特效開始的時候?yàn)閷ο蠹渔i,在結(jié)束的時候解鎖。
這個鎖的作用就是在同一時刻,只有一個特效在使用。
詳細(xì)內(nèi)容
通常,我們先載入配置文件,創(chuàng)建一個時鐘,然后注冊更新函數(shù),最后,創(chuàng)建我們的soldier(譯者:不知翻譯成哪個名字好)和盒對象。請?jiān)谥暗慕坛讨蝎@取更多信息。
注冊 輸入和特效事件
orxEvent_AddHandler(orxEVENT_TYPE_FX, EventHandler);

orxEvent_AddHandler(orxEVENT_TYPE_INPUT, EventHandler);

大家可以看到,在這兩個事件中,我們使用了同一個回調(diào)函數(shù)(EventHandler).
現(xiàn)在我們迅速的掃一眼自己的“對象”數(shù)據(jù)結(jié)構(gòu)。
typedef struct MyObject



{

orxBOOL bLock;

} MyObject;

接下來,看看如何用orxObject_SetUserData()
將它綁定到soldier上
MyObject *pstMyObject;


pstMyObject = orxMemory_Allocate(sizeof(MyObject), orxMEMORY_TYPE_MAIN);

pstMyObject->bLock = orxFALSE;


orxObject_SetUserData(pstSoldier, pstMyObject);

現(xiàn)在看看如何在Update函數(shù)中使用特效
orxSTRING zSelectedFX;


if(orxInput_IsActive("SelectWobble"))



{

zSelectedFX = "WobbleFX";

}

else if(orxInput_IsActive("SelectCircle"))



{

zSelectedFX = "CircleFX";

}


[
]


// Soldier not locked?

if(!((MyObject *)orxObject_GetUserData(pstSoldier))->bLock)



{

if(orxInput_IsActive("ApplyFX") && orxInput_HasNewStatus("ApplyFX"))


{

orxObject_AddFX(pstSoldier, zSelectedFX);

}

}


可以看到,我們通過orxObject_GetUserData()這個函數(shù)得到了我們想要的數(shù)據(jù),向solder里添加特效的方法跟添加聲音的方法如出一轍,用的都是這個函數(shù)orxObject_AddFX()。
接下來,看看EventHandler這個函數(shù)
首先是輸入方面,這里只展示了每次輸入時哪個按鍵被使用了。
if(_pstEvent->eType == orxEVENT_TYPE_INPUT)



{

if(_pstEvent->eID == orxINPUT_EVENT_ON)


{

orxINPUT_EVENT_PAYLOAD *pstPayload;


pstPayload = (orxINPUT_EVENT_PAYLOAD *)_pstEvent->pstPayload;


if(pstPayload->aeType[1] != orxINPUT_TYPE_NONE)


{

orxLOG("[%s] triggered by '%s' + '%s'.", pstPayload->zInputName, orxInput_GetBindingName(pstPayload->aeType[0], pstPayload->aeID[0]), orxInput_GetBindingName(pstPayload->aeType[1], pstPayload->aeID[1]));

}

else


{

orxLOG("[%s] triggered by '%s'.", pstPayload->zInputName, orxInput_GetBindingName(pstPayload->aeType[0], pstPayload->aeID[0]));

}

}

}

正如你所見,我們通過按下的是一個單鍵還是一個組合鍵來判斷展示不同的信息。
我們僅使用了兩個首次輸入點(diǎn),因?yàn)槲覀冎溃覀兊呐渲梦募袥]有超過兩個的組合鍵。盡管orx支持最多四個組合鍵來做為一個單鍵。
orxInput_GetBindingName()
函數(shù)給了我們一個輸入的文字顯示。
注意:這些名稱在配置文件中也綁定到了對應(yīng)的按鍵上面。
現(xiàn)在來看下如何處理這個事件
if(_pstEvent->eType == orxEVENT_TYPE_FX)


{
orxFX_EVENT_PAYLOAD *pstPayload;
orxOBJECT *pstObject;
pstPayload = _pstEvent->pstPayload;
pstObject = orxOBJECT(_pstEvent->hRecipient);
switch(_pstEvent->eID)

{
case orxFX_EVENT_START:
orxLOG("FX <%s>@<%s> has started!", pstPayload->zFXName, orxObject_GetName(pstObject));
if(pstObject == pstSoldier)

{
// Locks it
((MyObject *)orxObject_GetUserData(pstObject))->bLock = orxTRUE;
}
break;
case orxSOUND_EVENT_STOP:
orxLOG("FX <%s>@<%s> has stoped!", pstPayload->zFXName, orxObject_GetName(pstObject));
if(pstObject == pstSoldier)

{
// Unlocks it
((MyObject *)orxObject_GetUserData(pstObject))->bLock = orxFALSE;
}
break;
}
}

在soldier上的動畫開始的時候,我們用自己的數(shù)據(jù)結(jié)構(gòu)來鎖定它,相應(yīng)的,停止的時候解鎖。
看完了代碼部分,我們再去看看配置文件。
首先看個簡單的特效 :盒子上旋轉(zhuǎn)的特效。
[RotateLoopFX]

SlotList = Rotate

Loop = true


[Rotate]

Type = rotation

StartTime = 0.0

EndTime = 2.0

Curve = sine

Pow = 2.0

StartValue = 0

EndValue = 360


[Box]

FXList = RotateLoopFX


看到了吧,特效是在它創(chuàng)建之初直接應(yīng)用在盒對象上面的,而不是在代碼中。
RotateLoopFX
包含僅包含一個時間段(Rotate)并且一直循環(huán)(attribute Loop)
然后定義Rotates時間段。時間的單位都是秒,角度的單位都是度。
定義這個旋轉(zhuǎn)動畫的時候,我們使用了一個正弦曲線,讓他每兩秒旋轉(zhuǎn)360度。
下面看下我們的搖擺特效。
[WobbleFX]

SlotList = Wobble


[Wobble]

Type = scale

StartTime = 0.0

EndTime = 1.0

Period = 0.2

Curve = sine

Amplification = 0.0

StartValue = (1.0, 1.0, 1.0)

EndValue = (2.0, 2.0, 1.0) ~ (6.0, 6.0, 1.0)


我們修改了scale屬性,并賦予它一個開始值和結(jié)束值。
他們都是用向量來表示的,如果不想使用任何異向值(譯者注:專業(yè)名字anisotropic value去知道確切意思)的話,也可是使用float類型來表示。
雖然看起來我們正在使用一個isotropic值,這個結(jié)束值也不過是一個隨機(jī)值。
它的X和Y部分可能是完全統(tǒng)統(tǒng)的隨機(jī)值!
除此之外,我們使用了一個簡單的周期為0.2秒的正弦曲線,它將會播放1秒鐘。
看到了吧,我們將Amplification的值設(shè)為0,這就是說,隨著時間的推進(jìn),曲線的振幅會逐漸變低。
注意:默認(rèn)的振幅是1,當(dāng)值大于1時,振幅就會加大;當(dāng)值小于1時,振幅就會減少。
看看圓是如何運(yùn)動的。
[CircleFX]
SlotList = CircleX#CircleY
KeepInCache = true
[CircleX]
Type = position
StartTime = 0.0
EndTime = 1.0
Curve = sine
StartValue = (0.0, 0.0, 0.0)
EndValue = (-50.0, 0.0, 0.0)
UseOrientation = true
UseScale = true
[CircleY@CircleX]
Phase = 0.25
StartValue = (0.0, -25.0, 0.0)
EndValue = (0.0, 25.0, 0.0)

我們使用兩個時間段來控制它的位置,這樣才能做出一個圓形的運(yùn)動。第一個時間段是CircleX,他將會應(yīng)用在對象的X軸向的振幅。第二個時間段CircleY,會產(chǎn)生一個同樣幅度的作用效果在Y軸上。
如果我們不更改CircleY
的相位,是不會發(fā)生圓形的運(yùn)動。
現(xiàn)在假設(shè)一個正弦曲線,在初始值是相位0,準(zhǔn)備增加
在相位0。25的時候,到達(dá)中間點(diǎn),將會繼續(xù)增加
在相位0.5的時候,到達(dá)最高值,準(zhǔn)備下降
在相位0.75的時候,回到中間點(diǎn),繼續(xù)下降
在相位1.0的時候,就跟相位0是一樣的了
注意:這段描述正弦曲線的工作過程也同樣適用于三角形,但是卻不適用于線形。
我們將略過大多數(shù)其他的特效,因?yàn)槟抢餂]有什么我們不知道的新知識了。
但是我們還是要迅速的看一眼翻轉(zhuǎn)的特效,他將會向我們展示如何翻轉(zhuǎn)一個對象。
[FlipFX]

SlotList = Flip


[Flip@Wobble]

EndTime = 0.5

Period = 1.0

Amplification = 1.0

EndValue = (-1.0, 1.0, 1.0)

看到了吧,我們很簡單的使用負(fù)值完成了這個效果。
同時也注意到,我們給周期設(shè)了一個明確的值。
我們選了一個兩倍于定義的正弦曲線的周期,這樣我們就只使用了正弦曲線的上升的那一半。同時,我們也將振幅改回了1
資源
源代碼: 07_FX.c
配置文件: 07_FX.ini