夜深了 ,明早起 來 在 這 下 面 寫個 小 程序玩下 .
隨筆分類
隨筆檔案
收藏夾
C++
- 專門解決各種C++疑難雜癥
常用鏈接留言簿(1)我參與的團隊隨筆分類隨筆檔案收藏夾C++
搜索最新評論
閱讀排行榜評論排行榜 |
晚上 抽風 ,折騰電腦 ,安 了 個 UBUNTU.
夜深了 ,明早起 來 在 這 下 面 寫個 小 程序玩下 . 綜述參看前面的教程基礎, 對象創建, 時鐘 , 框架層次結構, 動畫, 視口與攝像機,和 聲音與音樂 。 特效在配置文件中設置,僅僅只需要一行代碼就可以在對象上使用這些特效。 特效可以使用絕對值或者相對值,這取決于配置文件中Absolute標簽。 這也就允許我們創造極其拉風的視覺特效。 除非特效已經緩存在內存中,否則特效參數全部在配置文件中進行調整,并且使用退格鍵來即時重載。 (cf.通過 通常說來,隨機值的使用可以給特效帶來更多的變化。 就像顯示事件一樣,我們也可以注冊特效的開始播放和停止的事件。因為循環時間是永遠不會停下來的,所以對應的停止事件( 詳細內容通常,我們先載入配置文件,創建一個時鐘,然后注冊更新函數,最后,創建我們的士兵和盒子對象。請在之間的教程中獲取更多信息。 . 然后,我們注冊輸入和特效事件 orxEvent_AddHandler(orxEVENT_TYPE_FX, EventHandler); orxEvent_AddHandler(orxEVENT_TYPE_INPUT, EventHandler); 大家可以看到,在這兩個事件中,我們使用了同一個回調函數(EventHandler). 現在我們迅速的掃一眼自己的“對象”數據結構。 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); 現在看看如何在Update函數中使用特效 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()這個函數得到了我們想要的數據,向solder里添加特效的方法跟添加聲音的方法如出一轍,用的都是這個函數orxObject_AddFX()。 接下來,看看EventHandler這個函數 首先是輸入方面,這里只展示了每次輸入時哪個按鍵被使用了。 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])); } } } 正如你所見,我們通過按下的是一個單鍵還是一個組合鍵來判斷展示不同的信息。 我們僅使用了兩個首次輸入點,因為我們知道,我們的配置文件中沒有超過兩個的組合鍵。盡管orx支持最多四個組合鍵來做為一個單鍵。 orxInput_GetBindingName() 函數給了我們一個輸入的文字顯示。 注意:這些名稱在配置文件中也綁定到了對應的按鍵上面。 現在來看下如何處理這個事件 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上的動畫開始的時候,我們用自己的數據結構來鎖定它,相應的,停止的時候解鎖。 看完了代碼部分,我們再去看看配置文件。 首先看個簡單的特效 :盒子上旋轉的特效。 [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 看到了吧,特效是在它創建之初直接應用在盒對象上面的,而不是在代碼中。 RotateLoopFX包含僅包含一個時間段(Rotate)并且一直循環(attribute Loop) 然后定義Rotates時間段。時間的單位都是秒,角度的單位都是度。 定義這個旋轉動畫的時候,我們使用了一個正弦曲線,讓他每兩秒旋轉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屬性,并賦予它一個 也就是說,它的X和Y部分可能是完全統統的隨機值! 除此之外,我們使用了一個簡單的周期為0.2 秒的正弦曲線,它將會播放1秒鐘。 看到了吧,我們將Amplification(增幅) 的值設為0,這就是說,隨著時間的推進,曲線的振幅會逐漸變低。注意:默認的Amplification是1,表示不隨時間變化,保持穩定,當值大于1時,振幅就會加大;當值小于1時,振幅就會減少。 看看圓是如何運動的。 [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) Here we need to use 2 slots that affects the position so as to be able to have a circle motion. 我們使用兩個時間段來控制它的位置,這樣才能做出一個圓形的運動。第一個時間段是CircleX,他將會應用在對象的X軸向的振幅。第二個時間段CircleY,會產生一個同樣幅度的作用效果在Y軸上。 如果我們不更改CircleY的相位,是不會發生圓形的運動。 現在假設一個正弦曲線,在初始值( 在相位0。25的時候,到達中間點,將會繼續增加 在相位0.5的時候,到達最高值( 在相位0.75的時候,回到中間點,繼續下降 在相位1.0的時候,就跟相位0( 注意:這段描述正弦曲線的工作過程也同樣適用于三角形,但是卻不適用于線形。 我們將略過大多數其他的特效,因為那里沒有什么我們不知道的新知識了。 但是我們還是要迅速的看一眼翻轉的特效,他將會向我們展示如何翻轉一個對象。就像Paper Mario Wii4)的風格. [FlipFX] SlotList = Flip [Flip@Wobble] EndTime = 0.5 Period = 1.0 Amplification = 1.0 EndValue = (-1.0, 1.0, 1.0) 看到了吧,我們很簡單的使用負值完成了這個效果! 資源
摘要: 綜述
這篇教程介紹了什么是特效以及如何創建它們
特效是建立在曲線集(線、三角形、矩形、)之上的,它們具有不同參數如:大小、旋度、位置、速度、顏色等。
特效在配置文件中設置,僅僅只需要一行代碼就可以在對象上使用這些特效。
8條任意類型的曲線組合在一起就可以形成一個特效。
在同一時間,可以有多達4個特效應用于同一個對象上面。
特效可以使用絕對... 閱讀全文
原文:http://orx-project.org/wiki/en/orx/tutorials/anim
綜述 這篇教程只涉及了orx中最基本的動畫使用。 更多關于動畫的東西在這里 猛擊我. 圖定義了動畫間所有可能的切換方式。動畫通過一個唯一的字符串來引用。所有的切換和動畫都是通過配置文件來創建的。 當一個動畫被請求的時候,引擎會計算從當前動畫到請求動畫之間的鏈路 如果這個鏈路存在,它會自動執行。用戶將通過事件被告知動畫何時開始、停止、刪節或者循環。 如果我們不能具體制定任何目標動畫,引擎就會很自然的沿著屬性中定義的線路(走下去)。 也有一個方法來越過這個尋路過程并且迅速的指向一個動畫。 詳細內容 通常,我們先載入config file(配置文件),創建一個viewport,創建一個clock(時鐘)并且注冊Update(更新)函數,最后創建一個主對象。 請從之前的教程中獲得更多的信息。 現在我們開始從代碼入手,我們將會從本頁的底部看到數據是如何組織的。 在Update函數中,當輸入GoLeft激活的時候會觸發WalkLeft動畫;GoRight激活的時候會觸發WalkRight函數. 當沒有激活態的輸入時,我們會移除目標動畫,讓這個圖保持一個自然的狀態 ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() 就是這樣!如何從任意當前動畫切換到目標動畫將會通過這個矢量圖來計算。如果需要切換,他們將會自動播放。 注意:有很多的函數可以用高級的方法來控制動畫,但是99%的時候,這兩個函數是最常用的(orxObject_SetCurrentAnim() 和 orxObject_SetTargetAnim())。 讓我們來看一下,動畫是如何通知我們發生了什么的(比如,就像同步語音一樣)。 首先,我們要向動畫事件注冊回調函數。 ![]() 好了!讓我們看下現在可以做什么了。 我們說我們想要打印出對象中哪個動畫被播放、停止、剪切或者循環。需要寫一下的回調函數。 ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() 先得到了事件的payload指針,因為我們只是在這里傳遞動畫事件,所以我們可以安全的將payload 轉化為orxANIM_EVENT_PAYLOAD類型,它在 orxAnim.h中定義。 如果我們在不同的事件(譯者注:原文是even 根據上下文推斷是作者拼寫錯誤)類型中調用了同一個回調函數,我們首先將會查看是否得到了一個動畫事件,可以這樣做: ![]() 最后,事件接收者(_pstEvent→hRecipient)通常是播放動畫的那個對象。將其用宏orxOBJECT()來轉化為orOBJECT類型的對象。 現在讓我們來看一眼數據方面的東西吧。 首先,我們需要定義一個動畫集,它將會包含指定對象的動畫的整個矢量圖。 動畫集在不會再內存中重復,并且它與矢量圖相對應的多有動畫和鏈路。 在上面這個例子中,我們又4個動畫和10條可以用來切換的鏈路。 ![]() ![]() ![]() ![]() 現在我們來開始定義動畫! 在這之前,為了減少文章篇幅,我們將要使用orx 配置文件的集成特性。 先錨點的位置定義一項。 也許你可能在對象教程中看到了錨點的相關知識,錨點的位置信息將會匹配世界中的對象。如果沒有確定的話,將會把左上角做為默認值。 錨點可以通過語義關鍵字來確定,如: top, bottom, center, left and right也可以通過實際的值來確定。 ![]() ![]() 現在,我們來定義從錨點繼承過來的圖像對象。在我們這個例子中,它是一個位圖,,包含了對象中所有的幀。因此基本的屬性就是 位圖文件的名字和一幀的大小。 ![]() ![]() ![]() 創建幀的準備工作都做好了。 讓我們定義所有都是right-oriented的動畫。一共6個。 ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() 看到了吧,他們全都繼承于FullGraphic,唯一能區分他們的屬性就是TextureCorner. 好,我們已經定義完了所有的圖形對象(他們載入的時候會轉變為orxGraphic結構),下面定義動畫本身。讓我們從ideright動畫開始說起,它包含一個單幀并持續0.1秒。 ![]() ![]() ![]() 太簡單了,來嘗試下第二個: ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() 當我們使用DefaultKeyDuration屬性同時為所有的幀定義時并不是很難。我們可以像idleright動畫中所做的那樣,通過一個確定的鍵值來覆蓋任意一幀。我們如法炮制做出left-oriented動畫。通常我們使用翻轉圖形對象時,我們將會在代碼運行中做這件事。但是那不是我們的目的!讓我們來用與前面那個完全不同的方法來實現它!只有鏈路沒有提到了讓我們添上它。基本的鏈路結構非常簡單,我們指定源動畫和目的動畫。 ![]() ![]() ![]() 這里,我們有跟之前一樣的基本信息,但是多了一個immediate屬性做為鍵值。這就是說,當我們處于IdleRight動畫時,并且目標是WalkRight,我們不必等到IdleRight完成,將直接完成這個動作,這就給了我們一個剪切動畫的方法。 正如在代碼中看到的一樣。當我們已經開始行走的時候,沒有顯式的調用空閑動畫,這是怎么做到的?看下從WalkRight到IdleRight的鏈路。 ![]() ![]() ![]() ![]() 當我們再WalkRight狀態并且移除了目標動畫,引擎不得按照自然的路線走下去。這個意思是說,它會選取高優先級的鏈路。默認的優先級是8,它的范圍是0到15.在這里,優先級是9,也就是說當我們沒有目標的時候,就會選取它。它將會帶我們回到IdleRight狀態。這里也加了immdiate屬性,這樣,我們就不必等“走”這個循環完事再回到“空閑” 注意:這只是一個非常基本的圖,用來闡述基本的動畫切換過程,但是這個系統的擴展性很高。比如假設這樣一個場景:你想從坐的狀態變為走的狀態,中間沒有別的過度。隨著游戲的開發,你可能覺得在這兩個狀態間加一個站立的狀態會比較好。這時,你只需要再配置文件中添加這多出來的一步,而整個代碼文件都不用更改。 資源: 源文件: 04_Anim.c 配置文件: 04_Anim.ini |