I know that android will automatically scale Bitmaps loaded from res/drawable by dpi. I manually shut that off with BitmapFactory options when I load the resources for my game, such as the tileset.
//Loads Bitmaps for the tileset
public void loadTiles(int s) {
Bitmap subimage = null;
BitmapFactory.Options o = new BitmapFactory.Options();
o.inScaled = false;
Bitmap tileset = BitmapFactory.decodeResource(activity.getResources(), s, o);
try {
numTilesAcross = tileset.getWidth() / tileSize;
tiles = new Tile[3][numTilesAcross];
for(int col = 0; col < numTilesAcross; col++) {
subimage = Bitmap.createBitmap(tileset,
col * tileSize,
0,
tileSize,
tileSize
);
tiles[0][col] = new Tile(subimage, Tile.UNBLOCKED);
subimage = Bitmap.createBitmap(tileset,
col * tileSize,
tileSize,
tileSize,
tileSize
);
tiles[1][col] = new Tile(subimage, Tile.BLOCKED);
subimage = Bitmap.createBitmap(tileset,
col * tileSize,
2 * tileSize,
tileSize,
tileSize
);
tiles[2][col] = new Tile(subimage, Tile.TRIGGER);
}
}
catch(Exception e) {
e.printStackTrace();
}
}
The problem is when I draw them to my Canvas (which is then drawn to a Surface View) if I test the game on any dpi lower than mdpi the tiles are scaled too small with space between, and if I test on anything higher they are drawn too big and overlap.
The main question is what methods scale using the dpi factor. I draw my images using
//tiles[r][c].getImage() returns a Bitmap
canvas.drawBitmap(
tiles[row][col].getImage(),
(int)x + col * tileSize,
(int)y + row * tileSize,
null
);
Does canvas.drawBitmap() scale using the dpi? Or is the scaling happening with the way I am getting subimages in my loadTiles(int s) method? I checked the width/height of the bitmaps loaded in loadTiles and they are the size I wanted.
NOTE: I am scaling the final image to the screen myself, size of all bitmaps drawn to the canvas should be dpi independent.
EDIT: Here are some pictures of what is going on... This is mdpi, it is how it is SUPPOSED to look http://cdn.img42.com/e9359c298455d505c3317bd705372030.png
This is hdpi, notice how things are overscaled and overlap the tile drawn before them http://cdn.img42.com/540b7896947049250fea3f3fa5a08331.png
This is ldpi, notice how the tiles are too small and they leave space inbetween img42/420e938b3eebc503247cd0181b779402fe.png
I figured it out. I was reading the documentation for Canvas and I have to set the density on both the canvas AND the bitmaps when they are loaded by calling
canvas.setDensity(DisplayMetrics.DENSITY_MEDIUM);
bitmap.setDensity(DisplayMetrics.DENSITYMEDIUM);
Relevant Documentation:
https://developer.android.com/reference/android/graphics/Canvas.html#setDensity%28int%29
https://developer.android.com/reference/android/graphics/Bitmap.html#setDensity%28int%29
I also could just set all images pixel density back to the system pixel density after I load their subimages out of their sheets so that the game will look nicer and less scaled/skewed