首先做配置文件
在log4j.xml里面
加下面的配置
<appender class="org.apache.log4j.RollingFileAppender" name="jp.webgis.action">
<param value="true" name="Append"/>
<param value="'.'yyyy-MM-dd" name="DatePattern"/>
<param value="/home/trial/Log/webgis/log/ACTION.LOG" name="File"/>
<layout class="org.apache.log4j.PatternLayout">
</layout>
</appender>
<appender class="org.apache.log4j.RollingFileAppender" name="jp.webgis.user">
<param value="true" name="Append"/>
<param value="'.'yyyy-MM-dd" name="DatePattern"/>
<param value="/home/trial/Log/webgis/log/USER.LOG" name="File"/>
<layout class="org.apache.log4j.PatternLayout">
</layout>
</appender>
<logger name="user.log">
<level value="info"></level>
<appender-ref ref="jp.webgis.user"/>
</logger>
<logger name="action.log">
<level value="info"></level>
<appender-ref ref="jp.webgis.action"/>
</logger>
JAVA程序调用:
org.apache.log4j.Logger logger1;
logger1 = org.apache.log4j.Logger.getLogger("action.log");
org.apache.log4j.Logger logger2;
logger2 = org.apache.log4j.Logger.getLogger("user.log");
logger1.info("Action.Log");
logger2.info("user.log");
“action.log”和"user.log" 和上面的配置一一对应。
logger1.info(写自己想记录的内容)
moving th image 跟display差不多,也不翻译了
游戏循环式每个游戏的心跳。我们用过一次非常基础的,它没有控制游戏状态速度的更新,也没有控制哪些帧要渲染。简单的说,大部分的游戏循环都是在循环里面执行一些指令,知道我们发信号通知结束,通常是设置running为false
1 boolean running = true; 2 while (!running) 3 { 4 updateGameState(); 5 displayGameState(); 6 }
上面的代码完全没有关注时间和资源。如果是快的设备,它会运行的很快,如果设备很慢,运行的也会很慢
有两个指标是我们必须要关注的 FPS和UPS
FPS 帧每秒 ---displayGameState每秒被调用的次数
UPS 更新每秒 updateGameState每秒被调用的次数
理想情况下 update和render方法每秒被调用的次数英爱是相当的,每秒不少于20-25帧。25帧对于手机来说已经够用了,通常就不会感觉到动画的迟钝了
比如 如果我们目标是25帧,那么意味着我们要每40m调用一次displayGameState方法。我们要知道updateGameState方法是在display方法之前调用的,为了达到25帧,我们必须要保证update-display序列的执行时间是40ms,如果小于40ms,那么FPS会高一点,否则会慢一点
为了更好理解,看几个例子
下面的图示 正好是1FPS,update-render 正好用了1秒来执行。这就意味着我们一秒就会看到一次更新屏幕
1 Frame per Second
The following diagram shows 10FPS. An update – render cycle takes 100ms. This means every tenth of a second the image changes.
下面的图显示的10FPS,update-render花费了100ms,这就意味着0.1秒看到图片发生改变
10 FPS
但是上面的场景意味我们每次的执行时间都是0.1秒吗?上图只是个假设,我们不能控制游戏的循环时间,如果有200个敌人,每个敌人都向我们射击,我们需要更新每个敌人和子弹的状态,还要检测碰撞,这当然是和两个人敌人的更新时间是不同的,同样也适用于渲染方法。
那么真实的场景是什么?我们有循环时间少于100ms的,等于100ms,和大于100ms的,高富帅的机器比屌丝的机器要给力的多,让我们看图
这次循环小于我们设计的时间帧,所以我们有一点休息的时间 然后再干活
Frame with time to spare
下图有点落后了,时间超过了预订的时间,如果花了12ms,就意味我们落后2ms了,然后认为是10FPS,这个可以叠加,每个循环我们的时间都不准确,我们的游戏会很慢
Overdue Frame
第一种情况很好,下次干活之前 给了我们一点休息时间。我们啥也不要干就直接告诉循环休息一会,下次干活的时间醒来就行了,如果不这么干 游戏会运行的快一些,下面介绍我们要获得睡眠时间
不变的帧率
第二种落后的情况,我们需要点其他的办法
为了完成游戏不变的帧率,想象一下,敌人以常速靠近你,如果一秒走了半屏,那么下一秒就会走完一个屏幕,为了计算位置,我们需要知道时间的增量和速率,或者直接更新敌人的位置,我选择后者,因为前者很复杂。为了完成不变的游戏速度,我们会丢掉一些显示帧,游戏速度不等于帧率。
看下面的图,循环时间超过了设计的时间,所以我们要赶上,我们跳过这帧,做另外一个update,游戏速度就不会受影响,我们会有一个正常帧,甚至可以让CPU休息一会
Constant Game Speed with Variable FPS
上面场景有很多的变量,想象一下游戏的更新超过了一整个帧,这种情况下我们没有办法让游戏速度保持不变。我们不能让跳过的帧太多,否则的游戏就不能玩了
The MainThread.java‘s run() looks like this:
01 // desired fps 02 private final static int MAX_FPS = 50; 03 // maximum number of frames to be skipped 04 private final static int MAX_FRAME_SKIPS = 5; 05 // the frame period 06 private final static int FRAME_PERIOD = 1000 / MAX_FPS; 07 @Override 08 public void run() { 09 Canvas canvas; 10 Log.d(TAG, "Starting game loop"); 11 long beginTime; // the time when the cycle begun 12 long timeDiff; // the time it took for the cycle to execute 13 int sleepTime; // ms to sleep (<0 if we're behind) 14 int framesSkipped; // number of frames being skipped 15 sleepTime = 0; 16 while (running) { 17 canvas = null; 18 // try locking the canvas for exclusive pixel editing 19 // in the surface 20 try { 21 canvas = this.surfaceHolder.lockCanvas(); 22 synchronized (surfaceHolder) { 23 beginTime = System.currentTimeMillis(); 24 framesSkipped = 0; // resetting the frames skipped 25 // update game state 26 this.gamePanel.update(); 27 // render state to the screen 28 // draws the canvas on the panel 29 this.gamePanel.render(canvas); 30 // calculate how long did the cycle take 31 timeDiff = System.currentTimeMillis() - beginTime; 32 // calculate sleep time 33 sleepTime = (int)(FRAME_PERIOD - timeDiff); 34 if (sleepTime > 0) { 35 // if sleepTime > 0 we're OK 36 try { 37 // send the thread to sleep for a short period 38 // very useful for battery saving 39 Thread.sleep(sleepTime); 40 } catch (InterruptedException e) {} 41 } 42 while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) { 43 // we need to catch up 44 // update without rendering 45 this.gamePanel.update(); 46 // add frame period to check if in next frame 47 sleepTime += FRAME_PERIOD; 48 framesSkipped++; 49 } 50 } 51 } finally { 52 // in case of an exception the surface is not left in 53 // an inconsistent state 54 if (canvas != null) { 55 surfaceHolder.unlockCanvasAndPost(canvas); 56 } 57 } // end finally 58 } 59 }
看一下上面的code,它对应图形中的逻辑
还有另外一种方法,最大帧率的不变游戏速率,它 用插值法来画状态,在快速的硬件上被使用,它可以加强游戏效果,使动画更平滑,因为我们是移动设备,给CPU一点休息,还是可以省不少电的
异常:
org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session
:一个不同的对象与相同的标识符值已经与会话关联起来
代码片段:
注:以下为session打开的状态
* 我手动构造了一个Photo对象
Photo photo=new Photo();
photo.setId(1);
*然后我用load加载同一ID的photo对象
Photo p=session.load(Photo.class,1);
现在一级缓存里已经有了id为1的p对象
*然后我执行删除photo对象
session.delete(photo);
当我直行这句删除的时候抛出了异常,为什么呢?
因为当我执行删除photo对象的时候,它会去先删除一级里找有没有这个photo的id的Photo的对象,这个photo是我手动创建的,它的id为1,那么好,它去一级缓存里刚好找到了为1的Photo类型的对象但是它引用的是p,不是photo,所以异常被抛出,这个异常的意思就是:有两个标识一样但不是同一个引用的对象了。所以它无法执行删除。
*改动代码
session.delete(p);
测试 通过。
如果你也遇到了同样的异常,不知所措,你可以用session.clean清一下缓存。呵呵。