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

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

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

    Java游戲學習

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

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

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

    FPS
    --------
    ? 一個測量animation速度的常用指標就是楨速(每秒顯示楨的數量:frames per second),簡稱FPS.在下面的
    代碼中,做一次gameUpdate和gameRender的循環就對應一個楨.
    ? 比如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
    ? 連續調用兩次timer中間必需的最小時間.這樣才能保證每次調用返回不同的時間.
    ? 比如:
    ?? ?????? long t1 = System.currentTimeMillis( );
    ?? ??? ?long t2 = System.currentTimeMillis( );
    ?? ??? ?long diff = t2 - t1;? // 實際輸出是0,單位是ms

    ? 在win95和win98上,resolution值是55ms,說明只有在每隔55ms后調用timer才會返回不同的值.
    ? 在animation loop中,resolution的會導致animation比期望的要慢而且減小了FPS.因為如果gameUpdate
    和gameRender的時間小于55ms,那么timeDiff變量就會設為0,那么sleepTime就會比實際需要的時間要大.
    ? 為了防止這個問題,每個循環周期時間必須大于55ms,表示最高限制是大約18FPS.這個frame rate被廣泛接
    受,因為屏幕刷新過慢會表現得象閃屏(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;
    ?? ??? ??? ??? ??? ?//轉換成納秒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循環依賴一個好的timer和精確的sleep方法調用.現在在前面的基礎上改進代碼,以保證需要
    的楨速.
    //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 或 連續運行了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,而是一直循環,一定次數后調用Thread.yield(),
    這樣來節省時間而又保證其它線程有機會運行.

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

    ? 除了FPS,還有一個有用的測量animation速度的指標:UPS. 在現在的animation循環中每次迭代擁有一次
    update和render.但是這個對應不是必需的.在循環中,可以每一次render前做兩次updates.
    ?
    //code example:
    ?
    public void run() {
    ? ...
    ? running = true;
    ? while(running) {
    ??? gameUpdate();//update 游戲狀態
    ??? gameUpdate();//再一次update 游戲狀態
    ?
    ??? 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的次數.
    但是注意,如果增加gameUpdate的次數過多的話會造成游戲不連續,因為有許多游戲狀態沒有顯示出來.

    新的代碼:

    //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,
    所以可能會更小一點).額外的執行時間被加到excess變量中.
    ? 當excess達到period大小時,那么相當于丟失了一個楨,在while循環中,為每次丟失執行gameUpdate.但是限制在
    MAX_FRAME_SKIPS里.
    ? 這樣做的優點是,如果一個游戲的update/render速度不能滿足期望的FPS時,那么就會另外執行gameUpdate.
    這樣改變了游戲的狀態但是沒有馬上顯示出來,最后用戶會看見游戲移動更"快"了,雖然每秒鐘顯示的楨數并沒有
    改變.

    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 ! !
    主站蜘蛛池模板: 亚洲中文无码永久免费| 67194国产精品免费观看| 日本免费电影一区| 99久久婷婷国产综合亚洲| 免费观看国产网址你懂的| 久久综合亚洲色一区二区三区| 久艹视频在线免费观看| 久久精品亚洲精品国产色婷| 久久精品成人免费观看| 亚洲AV无码1区2区久久| 性xxxx视频免费播放直播| 亚洲综合色一区二区三区小说| 国产成人精品免费视频大全麻豆| 亚洲国产美女在线观看| 成年午夜视频免费观看视频| 亚洲欧美中文日韩视频| 亚洲av成人一区二区三区在线观看| 猫咪免费人成在线网站| 国产亚洲视频在线播放| 免费无遮挡无码永久视频| 亚洲国产成人99精品激情在线| 午夜成人免费视频| 免费人成又黄又爽的视频在线电影| 国产亚洲情侣一区二区无码AV | 免费无码一区二区三区蜜桃大| 亚洲日本天堂在线| 亚洲人成网站观看在线播放| 日批视频网址免费观看| 亚洲国产成人精品久久| 国产免费人成在线视频| 国产免费无码AV片在线观看不卡| 亚洲成人免费在线观看| 国产一级大片免费看| 免费一级不卡毛片| 亚洲欧洲无码AV不卡在线 | 亚洲国语精品自产拍在线观看| 青青青国产在线观看免费网站| 青娱乐在线视频免费观看| 亚洲a在线视频视频| 免费观看理论片毛片| 黄网站色视频免费在线观看的a站最新|