我正在开发的应用是Flappy Bird克隆。 我正在使用 surfaceView 对象,在其中有一个gameThread,并在其run方法内部在画布上绘制了游戏的各个组件。
只要我绘制矩形代表对象,一切就可以顺利进行,但是当我添加了第一个Drawables时,我注意到平滑度有所降低。如果我尝试将背景绘制为Drawable,则游戏会遭受非常明显的帧频损失。
我尝试过的事情:
这些都没有任何实质性的影响。
基本上:
一些相关代码:
public class CannonView extends SurfaceView
implements SurfaceHolder.Callback {
private CannonThread cannonThread; // controls the game loop
private Drawable background;
// constructor
public CannonView(Context context, AttributeSet attrs) {
super(context, attrs); // call superclass constructor
getHolder().addCallback(this);
background= ResourcesCompat.getDrawable(getResources(), R.drawable.background, null);
}
public void newGame() {
background.setBounds(0,0, getScreenWidth(),getScreenHeight());
}
public void drawGameElements(Canvas canvas) {
background.draw(canvas);
}
public void stopGame() {
if (cannonThread != null)
cannonThread.setRunning(false); // tell thread to terminate
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
if (!dialogIsDisplayed) {
newGame(); // set up and start a new game
cannonThread = new CannonThread(holder); // create thread
cannonThread.setRunning(true); // start game running
cannonThread.start(); // start the game loop thread
}
}
private class CannonThread extends Thread {
private SurfaceHolder surfaceHolder; // for manipulating canvas
private boolean threadIsRunning = true; // running by default
// initializes the surface holder
public CannonThread(SurfaceHolder holder) {
surfaceHolder = holder;
setName("CannonThread");
}
// changes running state
public void setRunning(boolean running) {
threadIsRunning = running;
}
// controls the game loop
@Override
public void run() {
Canvas canvas = null; // used for drawing
while (threadIsRunning) {
try {
// get Canvas for exclusive drawing from this thread
canvas = surfaceHolder.lockCanvas(null);
synchronized(surfaceHolder) {
drawGameElements(canvas);
}
}
finally {
if (canvas != null)
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
}
}
答案 0 :(得分:0)
很明显,低帧频的主要原因是background.draw()
。切换到Bitmap
可能会有所改善,这可能是因为它缓存了draw()
的输出,并且因为它可以与保证不需要缩放的Canvas
函数一起使用(例如,{{ 3}})
您还发现,切换为RGB_565作为中间格式会大大提高性能,大概是因为它丢弃了alpha。 (否则,我原以为这样做会慢一些,因为b / c格式必须将其转换为RGBA_8888,因为它被切成SurfaceView
。)
很明显,Android不会让您超过60fps。这几乎可以肯定是因为lockCanvas()
参与了drawBitmap( Bitmap, float, float, Paint)方案,该方案会限制绘图速率,以防止您提交无法显示的帧(由于设备的固定屏幕刷新率为60Hz)。
这留下了一个问题,为什么您没有获得完整的60fps,但是接近它。如果drawGameElements()
每次运行都花费相同的时间,并且少于16ms,那么lockCanvas()
应该限制您,并且绝对不会丢帧(连续60fps)。线程调度程序中似乎有麻烦,并且在三重缓冲方案需要triple buffering之前,CannonThread
经常执行得不够快,无法提供帧。在这种情况下,必须延迟帧直到下一个屏幕刷新。您可以尝试增加CannonThread's
page-flip,删除drawGameElements()
中绝对不需要在CannonThread
上进行的任何额外处理,或关闭设备上正在运行的其他应用。 / p>
如上所述,OpenGL是获得此类游戏最大Sprite性能的标准方法,因为它能够将许多操作转移到硬件上。您可能正在接近基于drawBitmap()
的游戏的性能极限。