`

Java游戏学习转

    博客分类:
  • Java
阅读更多

软件编程牛人网

这几天一直在看 <<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.
这样改变了游戏的状态但是没有马上显示出来,最后用户会看见游戏移动更"快"了,虽然每秒钟显示的桢数并没有
改变.

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/starshus/archive/2006/11/03/1364979.aspx

分享到:
评论

相关推荐

    Java做游戏学习.zip

    Java做游戏学习.zipJava做游戏学习.zipJava做游戏学习.zip Java做游戏学习.zipJava做游戏学习.zipJava做游戏学习.zip Java做游戏学习.zipJava做游戏学习.zipJava做游戏学习.zip Java做游戏学习.zipJava做游戏学习....

    JAVA版旋转俄罗斯方块游戏

    JAVA游戏的开发通常涉及到图形用户界面(GUI)的设计、音频处理、动画效果以及游戏逻辑等多个方面。在这款游戏中,开发者需要考虑如何创建一个流畅的用户交互体验,包括方块的下落速度、旋转操作的响应以及得分计算...

    JAVA游戏大综合及各种特效

    2. AI算法:简单的如敌人的随机行为,复杂如路径规划、行为树,甚至机器学习技术都可以在Java游戏中应用。 五、用户界面和音效 1. 用户界面:使用JavaFX或Swing等库创建游戏菜单、选项设置等界面元素,确保用户友好...

    几十个java游戏源代码打包,仅供学习使用。

    这个压缩包包含了几十个用Java编写的源代码,是学习Java游戏编程的理想资源。这些小游戏不仅展示了基础的编程概念,还涵盖了Java语言的核心特性以及游戏开发的常用技术。 首先,让我们来看看Java语言在游戏开发中的...

    java技术学习-基于Java线程池技术实现Knock Knock游戏项目(包含服务端、客户端两部分)

    java技术学习——基于Java线程池技术实现Knock Knock游戏项目(包含服务端、客户端两部分) java技术学习——基于Java线程池技术实现Knock Knock游戏项目(包含服务端、客户端两部分) java技术学习——基于Java...

    16款java游戏源码

    Java游戏源码是一种学习和研究Java编程语言的好资源,它能帮助开发者理解游戏开发的底层逻辑,提升编程技能。在本资源包中,包含了16个不同的Java游戏源码,这意味着我们可以深入研究多种游戏类型的实现,例如可能...

    Java游戏高级编程.pdf

    同时,加入Java学习群***可能会提供一些学习资料和实时的老师指导,便于对Java游戏高级编程进行更深入的研究。由于提供的内容中强调了学习群的重要性,可以推断在学习的过程中,交流与实操同样重要。

    游戏编程游戏编程java游戏编程java

    Java游戏编程是一个不断发展和更新的领域,开发者需要不断学习新的库、框架和技术。参与开源项目,利用GitHub、Stack Overflow等社区资源,能加速学习进程。 总的来说,Java游戏编程涵盖了广泛的编程知识,从基础到...

    几个很不错的Java游戏源代码

    这些"几个很不错的Java游戏源代码"提供了一次深入理解Java编程、游戏逻辑以及核心Java知识的绝佳机会。下面,我们将详细探讨这些游戏源代码所涵盖的知识点。 首先,"3d坦克游戏"是一个展示Java 3D图形编程能力的...

    java游戏设计-Java版仙剑奇侠传游戏(画面仿真度非常高)

    java游戏设计——Java版仙剑奇侠传游戏(画面仿真度非常高)java游戏设计——Java版仙剑奇侠传游戏(画面仿真度非常高)java游戏设计——Java版仙剑奇侠传游戏(画面仿真度非常高)java游戏设计——Java版仙剑奇侠传...

    java小游戏源码集合

    Java小游戏源码集合是一个丰富的资源库,包含了八款经典的Java编程实现的小游戏,这些游戏能够帮助初学者理解和学习Java编程语言以及游戏开发的基本原理。以下是这些游戏的详细讲解: 1. **五子棋**:五子棋是一款...

    java 雷电游戏 雷霆战机 swing学习.zip

    java 雷电游戏 雷霆战机 swing学习.zipjava 雷电游戏 雷霆战机 swing学习.zip java 雷电游戏 雷霆战机 swing学习.zipjava 雷电游戏 雷霆战机 swing学习.zip java 雷电游戏 雷霆战机 swing学习.zipjava 雷电游戏 雷霆...

    java游戏俄罗斯方块

    《Java游戏俄罗斯方块》是一款非常适合Java初学者学习和实践的游戏项目。这个游戏的开发基于Java编程语言,展示了Java在游戏编程中的应用,尤其对于想要掌握Java GUI(图形用户界面)和事件处理的开发者来说,这是一...

    Java游戏编程原理与实践教程源码

    Java游戏编程原理与实践是计算机科学中的一个重要领域,它结合了Java编程语言的特性与游戏设计的技巧。...这些游戏源码不仅是学习工具,也是实践平台,可以帮助开发者逐步掌握Java游戏编程的精髓。

    java游戏源代码下载

    Java游戏源代码下载资源提供了三个不同的游戏项目,这对于学习Java编程和游戏开发的初学者以及经验丰富的开发者来说,都是宝贵的参考资料。这些游戏可能包括基础的命令行游戏到更复杂的图形界面游戏,涵盖了一系列的...

    一些JAVA小游戏代码 学习

    这些小游戏是学习和实践Java编程、尤其是Java Swing库的理想素材。Java Swing是Java AWT(Abstract Window Toolkit)库的扩展,主要用于创建桌面应用程序的用户界面。Swing提供了一组组件,如按钮、文本框和面板,...

    java小游戏jar

    【Java小游戏Jar】是一款基于Java编程语言开发的小型游戏,可能是为了学习和娱乐而创作的。在编程领域,Java是一种广泛使用的高级编程语言,以其“一次编写,到处运行”的跨平台特性著称。开发者通常使用Java来构建...

    java贪吃蛇小游戏代码java小游戏源码.zip

    【标题】:Java贪吃蛇小游戏是基于Java编程语言实现的一款经典休闲游戏,它通过源码的形式呈现,供学习者研究和改进。 【描述】:这个压缩包包含的Java源码详细展示了如何利用面向对象的设计思想,实现一个功能完整...

    Java小游戏Java雷电游戏Java小游戏Java雷电游戏Java小游戏Java雷电游戏Java小游戏Java雷电游戏

    Java雷电游戏是一款基于Java编程语言开发的小型游戏,它展示了Java在游戏开发中的应用,同时也为学习者提供了深入理解Java基础知识和实践编程技巧的机会。这款游戏的开发涉及到多个Java技术点,包括图形用户界面...

Global site tag (gtag.js) - Google Analytics