亚洲免费av电影一区二区三区,日韩爱爱视频,51精品视频一区二区三区,91视频爱爱,日韩欧美在线播放视频,中文字幕少妇AV,亚洲电影中文字幕,久久久久亚洲av成人网址,久久综合视频网站,国产在线不卡免费播放

        ?

        以固定幀率更新畫面的C語言編程方法

        2017-03-24 12:02:28耿植
        電腦知識與技術(shù) 2017年1期

        耿植

        摘要:用C語言實現(xiàn)計算機動畫時,往往使用一個大概時長作為畫面之間的延時。該做法會使得不同畫面的幀時長不相等,從而無法實現(xiàn)對動畫速度的準(zhǔn)確控制。針對該問題,對延時函數(shù)進行了改進,能按指定的幀時長進行自適應(yīng)延時。以該理論為基礎(chǔ),進一步提出一種以固定幀率更新畫面的編程方法,適用于編寫需要按時更新畫面的動畫、游戲和應(yīng)用程序。最后,以C語言編寫控制臺窗口文本界面下的“英文對話動態(tài)演示”應(yīng)用程序為例,展示了該方法的應(yīng)用。

        關(guān)鍵詞:計算機動畫;幀率;延時;C語言;編程方法

        中圖分類號:TP311 文獻標(biāo)識碼:A 文章編號:1009-3044(2017)01-0046-03

        Abstract: To implement computer animation with C language, often use approximate duration as the delay between the frames. This will make the different time length between different frames, making it impossible to achieve accurate control over the speed of the animation. To solve this problem, the sleep function is improved and the adaptive delay can be carried out according to the specified frame time length. On this basis, further proposed a programming method to update frames with fixed frame rate, suitable for animation, games and applications. Finally, the application of this method is demonstrated by the example of "English Dialogue Dynamic Demonstration" under textual interface of the windows console in C language.

        Key words: computer animation; frame rate; delay; C language; programming method

        1 背景

        利用人類視覺系統(tǒng)的視覺殘留特性[1],計算機動畫中采用:“繪制一幀畫面”、“延時”、“繪制下一幀畫面”、“延時”的方式,在短時間內(nèi)快速切換畫面,能使人產(chǎn)生“畫面是連續(xù)變化”的感覺。有大量的文章探討了使用C語言在圖形界面下進行畫面繪制、擦除與切換的技術(shù)手段,如:屏幕重畫、雙緩沖、異或、調(diào)色板[2]、圖形頁面、掩膜[3]等。但卻都只是簡單地使用如delay(10)[3]、delay(200)[4]等大概延時作為控制動畫速度的手段。這僅能實現(xiàn) “按某個大概速度動起來”,而無法實現(xiàn)“按一個指定的速度動起來”和“從某時開始動起來,一直到某時為止”;也沒有討論一個畫面中若同時存在多個不同速度變化的畫面元素如何處理。以下提出一種以固定幀率更新畫面的編程方法,可用于實現(xiàn)圖形界面和文本界面下的各種類型的動畫[6]、游戲和應(yīng)用程序。下文中的C源代碼均在Windows系統(tǒng)中Visual C++編譯環(huán)境調(diào)試通過。

        2 幀率

        幀率(frame rate)是影視、動畫和游戲領(lǐng)域中的概念,表示畫面切換的速度,單位為fps(frames per second,即每秒幀數(shù))。fps數(shù)值越大則畫面連貫性越強,但同時數(shù)據(jù)量也越大,不同場合下需要綜合考慮容量與視覺效果的平衡。通常,電影的幀率為24fps(高幀率電影[5]可以達到48fps),電視(PAL制)為25fps,游戲?qū)Ξ嬅媪鲿承浴⒉僮鞣磻?yīng)靈敏性要求較高,通常需要高于30fps。

        幀時長是指兩幀畫面先后出現(xiàn)的間隔時間長度,其值是幀率的倒數(shù)。為敘述方便,下文以Tfps=n表示幀率為n時的理想幀時長,單位為毫秒。即:

        Tfps=n = 1000/n (ms)

        在幀率確定后,即可通過幀時長來計算動畫所需的幀數(shù)、同時控制畫面元素的變化速度。

        3 控制畫面變化速度

        以幀率為25fps的動畫為例,其理想幀時長為:

        Tfps=n = 1000/25 = 40(ms) (n=25)

        若在繪制一幀畫面后立刻更新下一幀畫面,如下代碼所示:

        //程序段1:無延時畫面更新

        while (!kbhit())

        DrawOneFrame(); //更新1幀畫面

        此時,第i幀的實際幀時長Tf(fi)等于該幀的代碼執(zhí)行時長Tr(fi),由于現(xiàn)代電腦性能強勁,Tr(fi)通常小于Tfps=25,即:

        Tf(fi) = Tr(fi) < Tfps=n (n=25)

        因此,上面代碼生成的動畫幀率大于25fps,畫面會像快進的視頻一樣飛速播放。為控制畫面更新速度,需要在更新完一幀畫面后,進行適當(dāng)時長的延時。

        3.1 使用等時長延時粗略控制幀時長

        要使動畫的時長與速度準(zhǔn)確,實際幀時長應(yīng)等于理想幀時長,這需要為每一幀增加一個延時Td(fi),即:

        Tfps=n = Tf(fi) = Tr(fi) + Td(fi)

        如引言中所述,許多文章討論動畫實現(xiàn)時忽略代碼執(zhí)行耗時Tr(fi),將Td(fi)簡化為一個固定時長的Td,即:

        Tfps=n = Tf(fi) = Tr(fi) + Td ( Tr(fi)>0, 0

        加入Td延時后程序段1改寫為:

        //程序段2:等時長延時畫面更新

        #define FPS 25 /* 使用宏定義指定幀率,以25fps為例 */

        #define FRAME_TIME (1000/FPS) /* 按幀率換算理想幀時長,單位為ms */

        #define DELTA_T 0 /* Tr(fi)的一個粗略值,大部分文章取0值 */

        #include //Sleep()函數(shù)頭文件

        while (!kbhit())

        {

        DrawOneFrame(); //更新1幀畫面

        Sleep(FRAME_TIME - DELTA_T); //等時長延時FRAME_TIME-DELTA_T ms

        }

        顯然,由于每幀畫面的Tr(fi)的都不相同,Td無論取何值也無法使任意兩幀的實際幀時長相等,即:

        Tf(fi) ≠ Tf(fj) (1≤i,j≤m,且i≠j,m為動畫最大幀數(shù))

        因此,使用等時長延時控制動畫速度有兩個無法解決的問題:

        第一, 同一段動畫,無論Td取何值也無法得到穩(wěn)定的幀率。如圖1所示,電腦A無論采用40ms延時和25ms延時(或其他任何值)均無法使每一幀都得到40ms的幀時長;

        第二, 采用相同延時的同一段動畫,在不同性能的電腦上播放時幀率也不同。如圖1所示,性能較弱的電腦B使用25ms延時,相比電腦A,其幀時長更長(即動畫速度更慢)。

        3.2 使用等幀長延時準(zhǔn)確控制幀時長

        為解決等時長延時的兩個問題,必須知道第i幀畫面的代碼執(zhí)行時長Tr(fi),計算得到第i幀的Td(fi)值,使得:

        Tfps=n = Tf(fi) (1≤i≤m, m為動畫最大幀數(shù))

        如圖2所示。

        為此,必須要記錄每次延時執(zhí)行時的具體時刻,作為計算Td(fi)的依據(jù),這可以通過使用clock()函數(shù)實現(xiàn)。以下為庫函數(shù)clock()的函數(shù)原型。

        clock_t clock(void);

        clock()函數(shù)返回自本程序運行起到調(diào)用此函數(shù)為止,CPU產(chǎn)生的clock tick(CPU時鐘計時單元)數(shù)。在VC++6.0的time.h里,對每秒clock tick數(shù)有如下宏定義:

        #define CLOCKS_PER_SEC 1000

        由此可知1個clock tick時長為1毫秒。因此,使用clock()可以實現(xiàn)計時精度為±1ms的自適應(yīng)等幀長延時函數(shù)。代碼如下:

        //程序段3:改進的自適應(yīng)等幀長延時函數(shù)

        #include //clock()函數(shù)頭文件

        int pastFrames = 0 ; //全局變量,記錄從程序運行到目前已經(jīng)過的幀數(shù)

        void FixedFrameTimeSleep(int frameTime)

        {

        static clock_t endClock = 0; //存放本次延時結(jié)束時刻的clock tick數(shù)

        pastFrames++; //經(jīng)過的幀數(shù)加1

        endClock += frameTime * CLOCKS_PER_SEC / 1000; //計算本幀結(jié)束時刻

        if (clock() > endClock) //若已超時則不延時

        endClock = clock(); //以當(dāng)前時刻為本幀的結(jié)束時刻

        else

        while (clock() < endClock) //循環(huán)1ms的延時至本幀結(jié)束,實現(xiàn)Td(fi) ms的延時

        Sleep(1); //延時并降低CPU占用率

        }

        使用此函數(shù)替換程序段1中的Sleep()函數(shù),即得到以固定幀率FPS運行的畫面更新程序框架:

        //程序段4:自適應(yīng)等幀長延時函數(shù)實現(xiàn)固定幀率更新畫面

        while (!kbhit())

        {

        DrawOneFrame();

        FixedFrameTimeSleep(FRAME_TIME);

        }

        4 實現(xiàn)畫面元素按時更新的函數(shù)框架

        在實現(xiàn)了固定幀率后,畫面元素的更新頻率可以換算為每幾幀更新一次,出現(xiàn)時刻、結(jié)束時刻可以通過pastFrames來控制。如下函數(shù)框架實現(xiàn):以指定fps(fps≤FPS),從startTime時刻到endTime時刻更新畫面元素。

        //程序段5:畫面元素按時更新函數(shù)框架

        void DrawAnimation(int fps,int startTime, int endTime)

        {

        int curTime, updateFrames ;

        curTime = pastFrames * FRAME_TIME ; //計算當(dāng)前時間

        if ( curTime >= startTime && curTime <= endTime ) //判斷是否在指定的動畫時間段

        {

        updateFrames = FPS / fps ; //將畫面元素的fps換算成每幾幀更新一次

        if ( pastFrames % updateFrames == 0 ) //判斷是否應(yīng)在本幀更新

        {

        //更新畫面元素的代碼

        }

        }

        }

        6 實現(xiàn)多個畫面元素按時更新的程序框架

        若畫面中有多個畫面元素,只需為它們分別編寫合適的DrawAnimation()函數(shù),再依次加到程序循環(huán)中即可,如下所示:

        //程序段6:多個畫面元素按時更新的程序框架

        while (!kbhit())

        {

        DrawAnimation1(fps1,ts1,te1);

        DrawAnimation2(fps2,ts2,te2);

        ……

        FixedFrameTimeSleep(FRAME_TIME);

        }

        7 編程方法應(yīng)用演示

        使用C編寫一個控制臺窗口文本界面下循環(huán)動態(tài)演示Tom和Jerry進行“英文對話”的程序。為演示編程方法中以固定幀率對多個畫面元素分別按時更新的特性,對此應(yīng)用程序做如下設(shè)定:

        1)一輪對話分為“問”和“答”;

        2)Tom從問候語中隨機選擇一句發(fā)問,Jerry根據(jù)問候語進行相應(yīng)的回答;

        3)發(fā)問前、回答前均停頓1秒,回答完成后停頓2秒,使得問答停頓自然;

        4)Tom和Jerry的語速不同:Tom為10字符/秒,Jerry為20字符/秒;

        5)有一個按“mmss””格式顯示的數(shù)字時鐘。

        若設(shè)定幀率為40fps(幀時長為25ms),則根據(jù)應(yīng)用程序設(shè)定可知:

        1)數(shù)字時鐘的更新頻率fps為1,每40幀更新一次;

        2)Tom、Jerry所說的話更新頻率fps分別為10、20,每4幀、2幀更新1次;

        3)一輪對話的時間順序為:1秒+發(fā)問者說話字符數(shù)/語速+1秒+發(fā)問者說話字符數(shù)/語速+2秒。

        為數(shù)字時鐘、Tom(說的話)和Jerry(說的話)這三個畫面元素按照DrawAnimation()函數(shù)框架分別編寫更新函數(shù),并依序放入程序框架,以下為部分代碼。

        //程序段7:“英文對話演示”部分代碼

        #define MAX_TIME 3600 /* 設(shè)定最長演示時間3600秒 */

        int ts1 = 0, te1 = 0; //Tom說話的開始時間與結(jié)束時間

        int ts2 = 0, te2 = 0; //Jerry說話的開始時間與結(jié)束時間

        while (!kbhit())

        {

        CalculateTime(); //在上一輪對話完成后,計算下一輪對話的時間安排

        DrawTom(10,ts1,te1);

        DrawJerry(20,ts2,te2);

        DrawDigitalClock(1,0,MAX_TIME);

        FixedFrameTimeSleep(FRAME_TIME);

        }

        最終實現(xiàn)的效果如圖3所示。

        8 結(jié)束語

        改進的等幀長延時將每幀中代碼執(zhí)行、數(shù)值計算、界面更新等消耗的時長計算在內(nèi),動態(tài)增減剩余延時,保證每幀的時長相同。通過等幀長延時獲得的固定幀率是一條時間軸,可以驅(qū)動程序流程準(zhǔn)確地按時間運行。在確定幀率和幀時長后,可用之計算畫面中每一個動態(tài)元素在此時間軸上的起始幀、結(jié)束幀以及需要更新的關(guān)鍵幀。這樣就能保證畫面中所有動態(tài)元素都能按各自速度和時間準(zhǔn)確更新。但是,當(dāng)畫面元素之間、畫面元素與用戶操作之間存在比較復(fù)雜的交互邏輯時(比如:RPG游戲中的戰(zhàn)斗場景[7]),使用面向過程的編程方式難以實現(xiàn)。因此,需要在此方法基礎(chǔ)上引入事件驅(qū)動機制[8],以降低程序交互邏輯實現(xiàn)的難度。

        參考文獻:

        [1] 朱蓉, 鄭建華. C語言實現(xiàn)動畫技術(shù)的探討[J]. 電腦知識與技術(shù), 2005(35): 145-147.

        [2] 趙艷忠, 王鴻銘. C語言平臺下動畫技術(shù)實現(xiàn)方法淺析[J]. 科技信息, 2008(22): 402-421.

        [3] 王進華, 章云, 曾歆懿. 基于掩模技術(shù)的C語言動畫設(shè)計與實現(xiàn)[J]. 科技廣場, 2005(10): 39-41.

        [4] 韓潔. 用C語言實現(xiàn)圖形動畫技術(shù)[J]. 計算機時代, 1999(3): 14-15.

        [5] 陳曉悅. 淺析高幀率電影制作流程[J]. 現(xiàn)代電影技術(shù), 2016(5): 36-39.

        [6] 和青芳. 計算機圖形學(xué)原理及算法教程(Visual C++版)[M]. 北京: 清華大學(xué)出版社出版, 2006: 202-220.

        [7] 張向娟, 李忠. 一種角色扮演類游戲軟件設(shè)計方法及應(yīng)用[J]. 電腦知識與技術(shù), 2012(19): 4641-4644.

        [8] 韓志強. 關(guān)于C#實現(xiàn)事件驅(qū)動機制的研究[J]. 赤峰學(xué)院學(xué)報:自然科學(xué)版, 2010(12): 50-51.

        亚洲日本一区二区在线| 中文人妻无码一区二区三区信息| 欧洲AV秘 无码一区二区三| 天涯成人国产亚洲精品一区av| 国产97色在线 | 国产| 亚洲av综合色区无码一二三区| 98国产精品永久在线观看| 日韩黄色大片免费网站| 无遮挡1000部拍拍拍免费| 在线精品一区二区三区| 亚洲人成人一区二区三区| 99视频偷拍视频一区二区三区| 日韩 无码 偷拍 中文字幕| 成人黄色网址| 91精品日本久久久久久牛牛| 日日噜噜噜夜夜狠狠久久蜜桃 | 夜夜夜夜曰天天天天拍国产| av无码免费永久在线观看| 精品午夜一区二区三区久久| 男女一区视频在线观看| 成人欧美一区二区三区在线观看| 日韩精品人妻系列无码专区免费| 国内精品91久久久久| 日韩女同在线免费观看| 成 人 免费 在线电影| 亚洲片一区二区三区| 一区二区国产视频在线| 日日摸夜夜添夜夜添高潮喷水| 亚洲欧洲巨乳清纯| 水蜜桃一二二视频在线观看免费| 熟女一区二区中文字幕| 国产精品亚洲欧美大片在线看| 精品人妻无码中文字幕在线| 亚洲av大片在线免费观看| 色婷婷五月综合激情中文字幕 | 亚洲欧美日韩精品中文乱码| 国产精品夜色视频久久| 轻点好疼好大好爽视频| 国产爽爽视频在线| 精品色老头老太国产精品| 国产精品 无码专区|