<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Java游戲?qū)W習

    Posted on 2006-11-06 18:45 luosheng 閱讀(384) 評論(0)  編輯  收藏

    這幾天一直在看 <<Killer Game Programming in Java>>,非常經(jīng)典的好書,現(xiàn)在對游戲有了一個基本的認識,過幾天就寫個貪吃蛇出來.
    因為看得有點快,真正準備寫代碼的時候又發(fā)現(xiàn)自己對一些基本知識點還是比較模糊,又返回去看前面.邊看邊做筆記,感覺確實理解得要更加清楚了.

    *FPS 和 按時間準確的Sleeping*
    ============================

    FPS
    --------
    ? 一個測量animation速度的常用指標就是楨速(每秒顯示楨的數(shù)量:frames per second),簡稱FPS.在下面的
    代碼中,做一次gameUpdate和gameRender的循環(huán)就對應一個楨.
    ? 比如100FPS表示run()中的每次迭代應該用1000/100 == 10ms.這個迭代時間存在period變量中.

    //code example:

    public void run() {
    ? long beforeTime, timeDiff, sleepTime;
    ? beforeTime = System.currentTimeMillis();
    ? running = true;
    ? while(running) {
    ??? gameUpdate();//計算game中的model
    ??? gameRender();//畫一個image, "double buffer"
    ??? paintScreen();//在screen上顯示image
    ?? ?
    ??? timeDiff = System.currentTimeMillis() - beforeTime;
    ??? sleepTime = period - timeDiff;//計算需要sleep的時間

    ??? if (sleepTime <= 0)
    ????? sleepTime = 5;

    ??? try {
    ????? Thread.sleep(sleepTime);
    ??? }catch(InterruptedException e);

    ??? beforeTime = System.currentTimeMillis();
    ? }
    }

    --------
    Timer Resolution
    ? 連續(xù)調(diào)用兩次timer中間必需的最小時間.這樣才能保證每次調(diào)用返回不同的時間.
    ? 比如:
    ?? ?????? long t1 = System.currentTimeMillis( );
    ?? ??? ?long t2 = System.currentTimeMillis( );
    ?? ??? ?long diff = t2 - t1;? // 實際輸出是0,單位是ms

    ? 在win95和win98上,resolution值是55ms,說明只有在每隔55ms后調(diào)用timer才會返回不同的值.
    ? 在animation loop中,resolution的會導致animation比期望的要慢而且減小了FPS.因為如果gameUpdate
    和gameRender的時間小于55ms,那么timeDiff變量就會設為0,那么sleepTime就會比實際需要的時間要大.
    ? 為了防止這個問題,每個循環(huán)周期時間必須大于55ms,表示最高限制是大約18FPS.這個frame rate被廣泛接
    受,因為屏幕刷新過慢會表現(xiàn)得象閃屏(excessive flicker)一樣.
    ?
    ? 在Windows2000, NT和XP上, currentTimeMillis()的resolution是10到15ms,這樣就可以獲得67-100FPS.
    這個值對游戲來說是可以接受的.在Mac OS X和Linux上的resolution是1ms,相當好了.

    --------
    改進過的J2SE Timers

    ? J2SE 1.4.2有一個沒有被寫入到文檔的精確到微秒的timer class: sum.misc.Perf.
    ? Pref計算diff的方法:

    ??? ? Pref perf = Perf.getPerf();
    ?? ?long countFrep = perf.highResFrequency();
    ?? ?
    ?? ?long count1 = perf.highResCounter();
    ?? ?long count2 = perf.highResCounter();
    ?? ?long diff = (count2 - count1) * 1000000000L / countFreq;
    ?? ??? ??? ??? ??? ?//轉(zhuǎn)換成納秒nanoseconds
    ? nanoseconds:十憶分之1秒

    ? J2SE 5.0中解決了這個timer的問題,System.nanoTime(),可以象Pref timer一樣來計算時間.
    ?? ?? long count1 = System.nanoTime();
    ?? ?long count2 = System.nanoTime();
    ?? ?long diff = (count1 - count2);//單位是納秒

    --------
    Non-J2SE Timers

    ? Java 3D timer的計算方法:
    ?? ?? long t1 = J3DTimer.getValue();
    ?? ?long t2 = j3DTimer.getValue();
    ?? ?long diff = t2 - t1;//單位是納秒


    *更好的Sleeping*
    ================
    ? animation循環(huán)依賴一個好的timer和精確的sleep方法調(diào)用.現(xiàn)在在前面的基礎上改進代碼,以保證需要
    的楨速.
    //code example:

    private static final int NO_DELAYS_PER_YIELD = 16;

    public void run() {
    ? long beforeTime, afterTime, timeDiff, sleepTime;
    ? long overSleepTime = 0L;
    ? int noDelays = 0;

    ? beforeTime = J3DTimer.getValue();
    ?
    ? running = true;
    ? while(running) {
    ??? gameUpdate();
    ??? gameRender();
    ??? paintScreen();

    ??? afterTime = J3DTimer.getValue();
    ??? timeDiff = afterTime - beforeTime;
    ??? sleepTime = (period - timeDiff) - overSleepTime;

    ??? if (sleepTime > 0) {
    ????? try{
    ??????? Thread.sleep(sleepTime/1000000L); //nano -> ms
    ????? }catch(InterrruptedException ex){}
    ????? overSleepTime = (J3DTimer.getValue() - afterTime) - sleepTime;
    ??? }else {?? ?//sleepTime <= 0; 楨的時間大于期望的period,
    ?? ??? ?//不sleep直到sleepTime > 0 或 連續(xù)運行了NO_DELAYS_PER_YIELD次
    ????? overSleepTime = 0L;
    ??? ?
    ????? if (++noDelays >= NO_DELAYS_PER_YIELD) {
    ??????? Thread.yield();
    ?? ? noDelays = 0;
    ????? }
    ??? }
    ?? ?
    ??? beforeTime = J3DTimer.getValue();

    ? }
    }

    ? 如果sleep()設置成sleep 10 ms,但是確用了12 ms,那么overSleepTime會被設置成2 ms,下次就會少
    sleep 2ms.
    ? 如果楨的時間大于期望的period,那么就不浪費時間sleep,而是一直循環(huán),一定次數(shù)后調(diào)用Thread.yield(),
    這樣來節(jié)省時間而又保證其它線程有機會運行.

    *FPS和UPS*
    ==========

    ? 除了FPS,還有一個有用的測量animation速度的指標:UPS. 在現(xiàn)在的animation循環(huán)中每次迭代擁有一次
    update和render.但是這個對應不是必需的.在循環(huán)中,可以每一次render前做兩次updates.
    ?
    //code example:
    ?
    public void run() {
    ? ...
    ? running = true;
    ? while(running) {
    ??? gameUpdate();//update 游戲狀態(tài)
    ??? gameUpdate();//再一次update 游戲狀態(tài)
    ?
    ??? gameRender();
    ??? paintScreen();

    ??? //sleep
    ? }
    ? System.exit(0);
    }
    ? 在上面的代碼中,如果游戲提供了50FPS,那么就每秒就會做100次updates.

    從Rendering中分離Updates
    --------

    ? 對于高FPS速率的一個限制是update和render所需要的時間.假設period = 5ms(1000/5 == 200FPS),如果
    update和render需要的時間大于5ms,那么200FPS就不可能達到.而它們所需要的時間中大部分是被render所消耗的.
    ? 在這種情況下,增加游戲速度的方法是增加UPS的速率.在編程中,也就是在每次迭代中增加gameUpdate的次數(shù).
    但是注意,如果增加gameUpdate的次數(shù)過多的話會造成游戲不連續(xù),因為有許多游戲狀態(tài)沒有顯示出來.

    新的代碼:

    //code example:

    private static int MAX_FRAME_SKIPS = 5;

    public void run() {
    ? long beforeTime, afterTime, timeDiff, sleepTime;
    ? long overSleepTime = 0L;
    ? int noDelays = 0;
    ? long excess = 0L;

    ? beforeTime = J3DTimer.getValue();
    ?
    ? running = true;
    ? while(running) {
    ??? gameUpdate();
    ??? gameRender();
    ??? paintScreen();

    ??? afterTime = J3DTimer.getValue();
    ??? timeDiff = afterTime - beforeTime;
    ??? sleepTime = (period - timeDiff) - overSleepTime;

    ??? if (sleepTime > 0) {
    ????? try{
    ??????? Thread.sleep(sleepTime/1000000L); //nano -> ms
    ????? }catch(InterrruptedException ex){}
    ????? overSleepTime = (J3DTimer.getValue() - afterTime) - sleepTime;
    ??? }else {?? ?
    ????? excess -= sleepTime;
    ????? overSleepTime = 0L;
    ??? ?
    ????? if (++noDelays >= NO_DELAYS_PER_YIELD) {
    ??????? Thread.yield();
    ?? ? noDelays = 0;
    ????? }
    ??? }
    ?? ?
    ??? beforeTime = J3DTimer.getValue();

    ??? int skips = 0;
    ??? while((excess > period) && (skips < MAX_FRAME_SKIPS)) {
    ????? excess -= period;
    ????? gameUpdate();
    ????? skips++;
    ??? }

    ? }
    }

    ? 如果update/render實際需要12ms,但是需要的period是10ms,那么sleepTime會是-2ms(由于引入overSleepTime,
    所以可能會更小一點).額外的執(zhí)行時間被加到excess變量中.
    ? 當excess達到period大小時,那么相當于丟失了一個楨,在while循環(huán)中,為每次丟失執(zhí)行gameUpdate.但是限制在
    MAX_FRAME_SKIPS里.
    ? 這樣做的優(yōu)點是,如果一個游戲的update/render速度不能滿足期望的FPS時,那么就會另外執(zhí)行gameUpdate.
    這樣改變了游戲的狀態(tài)但是沒有馬上顯示出來,最后用戶會看見游戲移動更"快"了,雖然每秒鐘顯示的楨數(shù)并沒有
    改變.

    from:http://blog.csdn.net/starshus/archive/2006/11/03/1364979.aspx

    ?

    posts - 4, comments - 0, trackbacks - 0, articles - 0

    Copyright © luosheng

    welcome to my blog ! !
    主站蜘蛛池模板: 中国china体内裑精亚洲日本| 9420免费高清在线视频| 激情亚洲一区国产精品| 亚洲无人区一区二区三区| 四虎成人免费影院网址| 最近免费mv在线电影| aa在线免费观看| 免费国产a理论片| 亚洲精品无码成人| 久久狠狠爱亚洲综合影院| 亚洲va无码va在线va天堂| 亚洲午夜AV无码专区在线播放 | 亚洲AV人无码综合在线观看| 亚洲国产成人久久一区久久| 成人毛片免费网站| 18禁免费无码无遮挡不卡网站| 国产精品99精品久久免费| XXX2高清在线观看免费视频| caoporn成人免费公开| 免费视频精品一区二区| 国产精品亚洲精品爽爽| 久久亚洲中文无码咪咪爱| 亚洲中文字幕无码中文| 国产成人精品日本亚洲专| 亚洲综合色一区二区三区小说| 亚洲AV人无码激艳猛片| 久久亚洲AV午夜福利精品一区 | 猫咪免费人成网站在线观看入口 | 成年18网站免费视频网站| 97在线观免费视频观看| 99re热免费精品视频观看| 无码永久免费AV网站| 扒开双腿猛进入爽爽免费视频| 免费下载成人电影| 99精品国产免费久久久久久下载| 三年片在线观看免费大全| 免费无码不卡视频在线观看| 岛国片在线免费观看| 日本一区二区三区日本免费| 国产一级一片免费播放| www国产亚洲精品久久久|