我在Android上用OpenGL(-es)制作一个简单的突破游戏。最初我在同一个循环中更新了游戏的状态和绘图调用:onDrawFrame。现在我决定拆分两个,只将渲染调用留在onDrawFrame中,游戏状态在另一个线程中管理:
public void run() {
Log.d("GameLogicThread", "GameLogicThread started");
final long UPDATE_INTERVAL = 1000000000 / 30;
long endingTime;
int timeElapsed;
long startingTime = System.nanoTime();
while (!running) {// wait for it...
}
while (running) {
endingTime = System.nanoTime();
timeElapsed = (int) (endingTime - startingTime);
Log.d("timeElapsed",Integer.toString(timeElapsed));
if (timeElapsed < UPDATE_INTERVAL-timeElapsed){
try {
Thread.sleep(timeElapsed);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
startingTime = System.nanoTime();
Game.updateGame(timeElapsed);
}
EDIT
我现在已经改变了这样的代码^^,但它仍然无法正常工作..
循环中的某些东西是错误的,还是我应该向外看(可能不是,因为它在移动代码之前效果很好)。我该怎么办?
答案 0 :(得分:1)
循环对我来说看起来不会受到影响。分离线程的移动肯定是一个好的,或者当帧的渲染时间太长时你会遇到严重的问题。
您是否尝试过使用nanoTime()以获得更高的准确度?
答案 1 :(得分:1)
以下评论中指出/讨论了一些逻辑错误:
endingTime = System.currentTimeMillis();
timeElapsed = (int) (endingTime - startingTime);
// Why is the "elapsed" time being waited? Hmm.
// If *any* wait is being done (I'd recommend sleep(0) for starters)
// it should be the MAXIMUM desired cycle time MINUS the
// currently used cycle time (MINUS some fudge factor).
if (timeElapsed < UPDATE_INTERVAL) // I dislike hanging blocks...
try {
Thread.sleep(timeElapsed);
} catch (InterruptedException e) {
e.printStackTrace();
}
startingTime = System.currentTimeMillis();
// The game needs to know the TOTAL time elapsed since
// the last update, not the time "until before the yield".
// This will likely be passed fictitiously small values as
// it is only time the the LAST updateGame took to run.
Game.updateGame(timeElapsed);
我永远不会期望看到timeElapsed(传递给updateGame)下面说{10} sleep(...)
和更正的时间计算。
然而,它可能没有所需的精度(增加最小循环长度,比如说1/30秒,这是固定数学的结果,会使更少重要):见Cristian Vrabie's回答有关更高分辨率计时器的建议。 (可能有一些更好的第三方替代方案专门为此设计 - 存在“普通”Java - 我不编程Android; - )
快乐的编码。