对于我目前正在为Android设备编写的游戏,我有一个名为RenderView的类,它是一个Thread并更新并呈现所有内容。有时,类会记录消息“游戏线程只是更新更新方法而不呈现任何内容”。我的nexus游戏以30 fps的速度运行。我在整个会话期间都收到了几次这样的消息。有人可以告诉我如何优化课程,或者我忘了什么或者说这是完全正常的吗?
这是我的代码:
public class RenderView extends SurfaceView implements Runnable {
public final String classTAG = this.getClass().getSimpleName();
Game game;
Bitmap framebuffer;
Thread gameloop;
SurfaceHolder holder;
boolean running;
int sleepTime;
int numberOfFramesSkipped;
long beginTime;
long endTime;
long lastTime;
int differenceTime;
int framePeriod;
Canvas canvas;
int frameCount;
WSLog gameEngineLog;
public RenderView(Game game, Bitmap framebuffer) {
super(game);
this.game = game;
this.framebuffer = framebuffer;
this.holder = getHolder();
framePeriod = 1000/game.getFramesPerSecond();
lastTime = System.currentTimeMillis();
gameEngineLog = game.getGameEngineLog();
}
@Override
public void run() {
while(running == true) {
if(holder.getSurface().isValid()) {
beginTime = System.currentTimeMillis();
numberOfFramesSkipped = 0;
game.getCurrentScreen().update();
game.getCurrentScreen().render(); // Draw out everything to the current virtual screen (the bitmap)
game.getGraphics().renderFrameBuffer(); // Actually draw everything to the real screen (combine both bitmaps)
canvas = holder.lockCanvas();
if(canvas != null) { // Fix for mysterious bug ( FATAL EXCEPTION: Thread)
// The viewing area of our virtual screen on our real screen
canvas.drawBitmap(framebuffer, null, game.getWSScreen().getGameScreenextendeddst(), null);
holder.unlockCanvasAndPost(canvas);
}
else {
gameEngineLog.e(classTAG, "Surface has not been created or otherwise cannot be edited");
}
endTime = System.currentTimeMillis();;
differenceTime = (int) (endTime - beginTime);
sleepTime = (int) (framePeriod - differenceTime);
if(sleepTime > 0) {
try {
Thread.sleep(sleepTime);
} catch (InterruptedException exception) {
exception.printStackTrace();
}
}
else {
while(sleepTime < 0 && numberOfFramesSkipped < game.getMaxFrameSkippes()) {
gameEngineLog.d(classTAG, "Game thread is only updating the update method and is not rendering anything");
try {
Thread.sleep(5);
}
catch (InterruptedException exception) {
exception.printStackTrace();
}
game.getCurrentScreen().update();
sleepTime += framePeriod;
numberOfFramesSkipped++;
}
}
// Frame Per Second Count
frameCount++;
if(lastTime + 1000 < System.currentTimeMillis()) {
game.getGameEngineLog().d(classTAG, "REAL FPS: " + frameCount);
lastTime = System.currentTimeMillis();
frameCount = 0;
}
}
}
}
public void resume() {
running = true;
gameloop = new Thread(this);
gameloop.start();
}
public void pause() {
running = false;
while(running == true) {
try {
gameloop.join();
running = false;
}
catch (InterruptedException e) {
}
}
gameloop = null;
}
}
这是Graphics类的代码(getGraphics()只返回一个图形对象):
public class Graphics {
public final String classTAG = this.getClass().getSimpleName();
Game game;
Canvas frameBuffer;
Canvas canvasGameScreenextended;
Canvas canvasGameScreen; // Used for customeScreen
Bitmap gameScreenextended;
Bitmap gameScreen;
Rect gameScreendst;
Rect gameScreenextendeddst;
WSLog gameEngineLog;
Graphics(Game game, Bitmap framebuffer, Bitmap gameScreen) {
this.game = game;
// Initialize canvases to render to
frameBuffer = new Canvas(framebuffer);
canvasGameScreen = new Canvas(gameScreen);
// Initialize images to be rendered to our composition
this.gameScreen = gameScreen;
// Set up the Log
gameEngineLog = game.getGameEngineLog();
}
public void resetCanvasGameScreenextended() {
// This method has to be called each time the screen scaling type changes
canvasGameScreenextended = new Canvas(game.getWSScreen().getGameScreenextended());
gameScreenextended = game.getWSScreen().getGameScreenextended();
}
public Canvas getCanvasGameScreenextended() {
return canvasGameScreenextended;
}
public Canvas getCanvasGameScreen() {
return canvasGameScreen;
}
public void renderFrameBuffer() {
// Composition
// First layer (bottom)
frameBuffer.drawBitmap(gameScreen, null, game.getWSScreen().getGameScreendst(), null);
// Second layer (top)
frameBuffer.drawBitmap(gameScreenextended, null, game.getWSScreen().getGameScreenextendeddst(), null);
}
public void clearFrameBuffer() {
canvasGameScreen.drawColor(Color.BLACK);
//canvasGameScreenextended.drawColor(Color.BLACK);
gameScreenextended.eraseColor(Color.TRANSPARENT); // Make top layer transparent
}
}
这是屏幕类的代码(getCurrentScreen()方法返回一个屏幕对象):
public class Screen {
public final String classTAG = this.getClass().getSimpleName();
protected final Game game;
protected final Graphics graphics;
protected Screen(Game game) {
this.game = game;
this.graphics = game.getGraphics();
//game.getInput().reset();
}
public void update() {
}
public void render() {
}
/** Initialize all the sensory that should be used within this screen.*/
public void resume() {
}
public void pause() {
game.getInput().useAccelerometer(false);
game.getInput().useKeyboard(false);
game.getInput().useTouchscreen(false);
}
public void onDispose() {
game.getGraphics().clearFrameBuffer();
}
public void setScreenResizeType(int screenResizeType) {
}
扩展了Screen类,并使用以下方法对render()方法进行了阴影处理:
graphics.getCanvasGameScreen().drawRect(play, red);
有趣的是,当我覆盖render()方法并且不在其中放置任何代码时,记录器会不断触发消息:“游戏线程只更新更新方法并且不呈现任何内容”。这是什么样的巫术?!
非常感谢帮助!
答案 0 :(得分:0)
据我所知,从您更新的帖子中,实际上没有渲染问题。相反,您的代码错误地打印了该消息。
这是因为你检查if(sleepTime > 0)
,所以如果渲染非常快并且sleepTime为零,你就会得到那条消息。只需将其更改为if(sleepTime >= 0)
。