我正在尝试提高绘制位图的速度。我读到我可以尝试使用 RGB_565 选项而不是 ARGB_8888 当涉及到
createBitmap(...)
最后一个参数时。我还在自定义 SurfaceView 类的构造函数中设置了getHolder().setFormat(PixelFormat.RGB_565)
。
问题是,当我在所有这些地方设置这个 RGB_565 时,位图没有绘制,我得到空白屏幕,但是当设置了 ARGB_8888 时,我的位图正确显示但速度很慢。根据带有 RGB_565(空屏幕)的 TinyDancer 库,我得到 60FPS,而使用 ARGB_8888 我只得到 20FPS,所以我想尽可能地改进它。
编辑
这是我的代码。
GameMainSurface.java
public class GameMainSurface extends GameSurface implements SurfaceHolder.Callback {
(...)
public GameMainSurface(Context context) {
super(context);
this.context = context;
getHolder().setFormat(PixelFormat.RGB_565);
getHolder().addCallback(this);
setWillNotDraw(false);
}
public GameMainSurface(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
getHolder().setFormat(PixelFormat.RGB_565);
getHolder().addCallback(this);
setWillNotDraw(false);
}
public GameMainSurface(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.context = context;
getHolder().setFormat(PixelFormat.RGB_565);
getHolder().addCallback(this);
setWillNotDraw(false);
}
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
Loader.drawTmxMaps(canvas, getContext());
invalidate();
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
this.holder = holder;
(...)
initMaps();
}
protected void initMaps() {
TileMapData tileMainMapData = TmxLoader.readTMX("map_main4.tmx", context);
TmxLoader.createBitmaps(tileMainMapData, 0, 4, this);
}
}
Loader.java
public class Loader {
private static final String TAG = TmxLoader.class.getSimpleName();
private static final Map<Integer, Bitmap[]> framesMap = new HashMap<>();
private static final Map<Integer, Canvas[]> canvasesMap = new HashMap<>();
private static final Map<Integer, Long> animsDuration = new HashMap<>();
private static final List<Runnable> runnables = new ArrayList<>();
private static final Handler handler = new Handler();
private static boolean isIterStarted = false;
(...)
public static TileMapData readTMX(String filename, Context c) {
TileMapData tileMapData = null;
// Initialize SAX
try {
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser parser = spf.newSAXParser();
XMLReader reader = parser.getXMLReader();
// Create an instance of the TMX XML handler
// that will create a TileMapData object
TmxHandler handler = new TmxHandler();
reader.setContentHandler(handler);
AssetManager assetManager = c.getAssets();
reader.parse((new InputSource(assetManager.open(filename))));
// Extract the created object
tileMapData = handler.getData();
} catch (ParserConfigurationException pce) {
Log.e(TAG, "SAX XML parse error", pce);
} catch (SAXException se) {
Log.e(TAG, "SAX XML error", se);
} catch (IOException ioe) {
Log.e(TAG, "SAX XML parse io error", ioe);
}
return tileMapData;
}
public static void createBitmaps(TileMapData t, int startLayer, int endLayer, GameSurface gameSurface) {
try {
AssetManager assetManager = gameSurface.getContext().getAssets();
Bitmap[] tilesets = new Bitmap[t.tilesets.size()];
for (int i = 0; i < tilesets.length; i++) {
tilesets[i] = BitmapFactory.decodeStream(assetManager.open(t.tilesets.get(i).ImageFilename));
}
long currentGID;
Long localGID;
Integer currentTileSetIndex;
Rect source = new Rect(0, 0, 0, 0);
Rect dest = new Rect(0, 0, 0, 0);
boolean isAfterInit = false;
List<Integer> animFrames = new ArrayList<>();
for (int i = startLayer; i < endLayer; i++) {
// endlessblow_main4.tmx = 12
for (int j = 0; j < t.layers.get(i).height; j++) {
// endlessblow_main4.tmx = 8
for (int k = 0; k < t.layers.get(i).width; k++) {
currentGID = t.getGIDAt(k, j, i);
localGID = t.getLocalID(currentGID);
currentTileSetIndex = t.getTileSetIndex(currentGID);
if (!isAfterInit) {
animFrames = Stream.of(t.tilesets.get(currentTileSetIndex).tileAnimations).map(tileAnimation -> tileAnimation.getTileFrames().size()).collect(Collectors.toList());
for (int l = 0; l < t.tilesets.get(currentTileSetIndex).tileAnimations.size(); l++) {
for (int m = 0; m < t.tilesets.get(currentTileSetIndex).tileAnimations.get(l).getTileFrames().size(); m++) {
animsDuration.put(l, t.tilesets.get(currentTileSetIndex).tileAnimations.get(l).getTileFrames().get(m).getDuration());
}
}
init(animFrames, t);
isAfterInit = true;
}
if (localGID != null) {
if (i == startLayer) {
source.top = (((localGID).intValue()) / ((t.tilesets.get(currentTileSetIndex).imageWidth) / t.tilewidth)) * t.tileheight;
source.left = (((localGID).intValue()) % ((t.tilesets.get(currentTileSetIndex).imageWidth) / t.tilewidth)) * t.tilewidth;
source.bottom = source.top + t.tileheight;
source.right = source.left + t.tilewidth;
dest.top = j * t.tileheight;
dest.left = k * t.tilewidth;
dest.bottom = dest.top + t.tileheight;
dest.right = dest.left + t.tilewidth;
for (Canvas canvas : canvasesMap.get(0)) {
canvas.drawBitmap(tilesets[currentTileSetIndex], source, dest, null);
}
} else {
for (int l = 0; l < t.tilesets.get(currentTileSetIndex).tileAnimations.size(); l++) {
if (localGID == t.tilesets.get(currentTileSetIndex).tileAnimations.get(l).getLocalGID()) {
for (int frame = 0; frame < t.tilesets.get(currentTileSetIndex).tileAnimations.get(l).getTileFrames().size(); frame++) {
source.top = (int) ((t.tilesets.get(currentTileSetIndex).tileAnimations.get(l).getTileFrames().get(frame).getTileId() / ((t.tilesets.get(currentTileSetIndex).imageWidth) / t.tilewidth)) * t.tileheight);
source.left = (int) ((t.tilesets.get(currentTileSetIndex).tileAnimations.get(l).getTileFrames().get(frame).getTileId() % ((t.tilesets.get(currentTileSetIndex).imageWidth) / t.tilewidth)) * t.tilewidth);
source.bottom = source.top + t.tileheight;
source.right = source.left + t.tilewidth;
dest.top = j * t.tileheight;
dest.left = k * t.tilewidth;
dest.bottom = dest.top + t.tileheight;
dest.right = dest.left + t.tilewidth;
canvasesMap.get(l)[frame].drawBitmap(tilesets[currentTileSetIndex], source, dest, null);
}
}
}
}
}
}
}
}
for (int i = 0; i < framesMap.size(); i++) {
for (int j = 0; j < animFrames.get(i); j++) {
framesMap.get(i)[j] = Bitmap.createScaledBitmap(framesMap.get(i)[j], gameSurface.getCellWidth() * t.width, gameSurface.getCellHeight() * t.height, false);
}
}
} catch (IOException e) {
Log.e(TAG, e.getMessage());
}
}
private static void init(List<Integer> animFrames, TileMapData t) {
for (int i = 0; i < animFrames.size(); i++) {
runnables.add(new FrameDurationRunnable(animFrames.get(i), animsDuration.get(i)));
framesMap.put(i, new Bitmap[animFrames.get(i)]);
canvasesMap.put(i, new Canvas[animFrames.get(i)]);
for (int j = 0; j < animFrames.get(i); j++) {
framesMap.get(i)[j] = Bitmap.createBitmap(t.width * t.tilewidth, t.height * t.tileheight, Bitmap.Config.RGB_565);
canvasesMap.get(i)[j] = new Canvas(framesMap.get(i)[j]);
}
}
}
public static void drawTmxMaps(Canvas canvas, Context context) {
for (int i = 0; i < framesMap.size(); i++) {
canvas.drawBitmap(framesMap.get(i)[((FrameDurationRunnable) runnables.get(i)).iter], 0, 0, null);
}
if (!isIterStarted) {
iterTmxFrames();
isIterStarted = true;
}
}
private static void iterTmxFrames() {
for (int i = 0; i < runnables.size(); i++) {
handler.postDelayed(runnables.get(i), animsDuration.get(i));
}
}
private static class FrameDurationRunnable implements Runnable {
private final int animMaxIter;
private final long frameDuration;
private int iter;
FrameDurationRunnable(final int animMaxIter, final long frameDuration) {
this.animMaxIter = animMaxIter;
this.frameDuration = frameDuration;
}
public void run() {
iter++;
if (iter == animMaxIter) iter = 0;
handler.postDelayed(this, frameDuration);
}
}
}
你能看到什么解决方案?