【发布时间】:2018-11-05 15:10:18
【问题描述】:
我正在开发的应用是 Flappy Bird 克隆。 我正在使用一个 surfaceView 对象,其中我有一个 gameThread 并且在它的 run 方法内部,我在画布上绘制了游戏的各种组件。
只要我只绘制 Rects 来表示对象,一切都会顺利进行,但是当我添加第一个 Drawables 时,我注意到平滑度有一点损失。如果我尝试将背景绘制为可绘制对象,游戏会遭受非常严重的帧速率损失。
我尝试了什么:
- 使用 png 和所有不同类型的位图作为资产
- 调整资源大小以完美适合画布,从而避免重新缩放
这些都没有任何实际影响。
基本上:
- 如果我只使用drawRect:60fps
- 如果我用 drawRect 绘制背面,而用 drawable.draw(canvas) 绘制其他组件:57fps
- 如果我使用 drawable.draw(canvas) 绘制所有内容(包括背景):15fps
有点相关的代码:
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);
}
}
}
}
}
【问题讨论】:
-
请在您的问题中添加drawGameElements代码,以便我们知道您的代码可以优化的部分。
-
其实是包含在内的,你可以在第15行找到。我省略了除背景之外的元素的绘制,因为根据我的测试,它们只会造成一小部分的帧丢失。跨度>
-
似乎有点奇怪。我建议您将
Drawable预渲染为Bitmap(参见here),然后使用Bitmap进行渲染,因为很难知道Drawable在onDraw()中做了多少工作. -
这帮了大忙,游戏现在达到了 ~42 fps。尽管如此,对于一个总共只包含 5 个精灵的游戏来说,以 60fps 运行应该没有问题。
-
@fasiume 有几个想法:它可能在软件中进行 alpha 计算。
Bitmap.setHasAlpha(false)可能会有所帮助。而且,专业人士可能会使用 OpenGL,以获得最大的精灵性能。除此之外,我想知道这是否是drawGameElements()的时间和屏幕刷新率之间的交互。只是好奇,你是如何测量fps的?我假设您已经确定drawGameElements()每秒执行 42 次,这意味着从开始到结束大约需要 23 毫秒?
标签: android canvas background android-drawable frame-rate