我刚发现了一些东西,我想知道如何以及为什么。 我正在为Android开发一款小型街机游戏。我决定忽略OpenGL并使用标准的SurfaceView和Drawables来做它,因为它假设很轻(10个精灵左右)。 我有加载的drawable,我使用Draw方法并将它们传递给我的画布。这是每个精灵如何绘制到屏幕上的。 事实证明,绘制4-5个大精灵(200X400左右)需要花费很长时间才能使用不那么全新的手机型号。足够长的时间让我的游戏无法播放。我们谈论使用这种方法绘制单帧的时间为50-60毫秒。除了画画之外我真的不做任何事情,无处可削减成本。所以我决定尝试使用Bitmaps。但是,我需要预先设置大小,因为位图中没有'setBounds'方法。没问题,我调整它们以适应当前屏幕的负载,问题解决了。
行。所以我得到了位图。我现在使用Canvas.DrawBitmap进行绘制。我采用了新的绘制方法......我得到了一个强烈的 400%的性能提升!而不是50-60ms,整个绘制循环现在需要8-12ms。 到底是什么? 为了排除它,我也计时了setBounds,它需要< 1ms所以它不应该受到责备。这是实际的Drawable.Draw,减慢了速度。
对我来说这是个好消息,因为我真的不想学习OpenGL来让我的游戏可玩,但我不禁想知道它 - 它没事吗?我的方法有问题吗?为什么不在任何地方提到它?
答案 0 :(得分:4)
SurfaceView
的{{1}}意味着在您应该不断迭代并且Canvas
不是为此目的时使用。
答案 1 :(得分:1)
Canvas.drawBitmap
的工作量远远少于Drawable.draw
,因此速度更快。
Drawable.draw
由于Drawable
是一个抽象类,让我们看一下BitmapDrawable
:
public void draw(Canvas canvas) {
final Bitmap bitmap = mBitmapState.mBitmap;
if (bitmap == null) {
return;
}
final BitmapState state = mBitmapState;
final Paint paint = state.mPaint;
if (state.mRebuildShader) {
final Shader.TileMode tmx = state.mTileModeX;
final Shader.TileMode tmy = state.mTileModeY;
if (tmx == null && tmy == null) {
paint.setShader(null);
} else {
paint.setShader(new BitmapShader(bitmap,
tmx == null ? Shader.TileMode.CLAMP : tmx,
tmy == null ? Shader.TileMode.CLAMP : tmy));
}
state.mRebuildShader = false;
}
final int restoreAlpha;
if (state.mBaseAlpha != 1.0f) {
final Paint p = getPaint();
restoreAlpha = p.getAlpha();
p.setAlpha((int) (restoreAlpha * state.mBaseAlpha + 0.5f));
} else {
restoreAlpha = -1;
}
final boolean clearColorFilter;
if (mTintFilter != null && paint.getColorFilter() == null) {
paint.setColorFilter(mTintFilter);
clearColorFilter = true;
} else {
clearColorFilter = false;
}
updateDstRectAndInsetsIfDirty();
final Shader shader = paint.getShader();
final boolean needMirroring = needMirroring();
if (shader == null) {
if (needMirroring) {
canvas.save();
// Mirror the bitmap
canvas.translate(mDstRect.right - mDstRect.left, 0);
canvas.scale(-1.0f, 1.0f);
}
canvas.drawBitmap(bitmap, null, mDstRect, paint);
if (needMirroring) {
canvas.restore();
}
} else {
updateShaderMatrix(bitmap, paint, shader, needMirroring);
canvas.drawRect(mDstRect, paint);
}
if (clearColorFilter) {
paint.setColorFilter(null);
}
if (restoreAlpha >= 0) {
paint.setAlpha(restoreAlpha);
}
}
您可以看到它甚至在内部调用canvas.drawBitmap
。
Canvas.drawBitmap
将其与Canvas.drawBitmap
进行比较。它要短得多。
public void drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint) {
throwIfCannotDraw(bitmap);
native_drawBitmap(mNativeCanvasWrapper, bitmap, left, top,
paint != null ? paint.getNativeInstance() : 0, mDensity, mScreenDensity, bitmap.mDensity);
}
有一些不同的drawBitmap
方法,但它们都比Drawable.draw
方法短。注意陷阱like this以保持位图快速绘制。