I've been working on a simple tile-based terrain generator for fun, and have run into a bit of a problem.
First, info:
Device: Acer Iconica a500
OS: ICS
Target version: 3.1+
Usable Screen Resolution: 1280x752
Programmed in: Eclipse / AIDE
So, now the issue:
All the tiles I am using are being drawn larger than they should be. Tehy are all 32x32 .png files, but they are all being drawn on the screen at 43 x 43. From what I've read this probably has something to do with the density of the canvas they are being drawn to, so I attempted to fix it by adding
canvas.setDensity(0x0000000); //density int value for DENSITY_NONE
Unfortunately, this didn't solve the problem. I also attempted the same for the individual bitmaps, but to no avail.
I tried to find a solution here on Stack, and elsewhere, but have not had any luck so far.
Does anyone know how to fix this?
Thank you in advance. Here is the complete code for my draw class: (I know there are probably a number of issues with this code, I'm an amateur programmer. Constructive criticism is welcomed)
package com.psstudio.hub.views;
import java.util.Random;
import com.psstudio.hub.R;
import com.psstudio.hub.R.drawable;
import com.psstudio.hub.gen.PocketDimension;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.view.Display;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.util.AttributeSet;
import android.util.Log;
public class DrawWorld extends SurfaceView implements SurfaceHolder.Callback {
private WorldThread wThread;
PointF playerPos = new PointF();
PocketDimension dim = null; //Holder for the dimension
int screenW = 0; //this.getWidth();
int screenH = 0; //this.getHeight();
int dimType = 1; //Which type of dimension is it?
int curType = -1;
int r;
int g;
int b;
int numTilesX;
int numTilesY;
float curX = 0.0f;
float curY = 0.0f;
float curXOffset = 0.0f;
float curYOffset = 0.0f;
private boolean run = false;
Random rand = new Random(255-0);
Paint heightPaint = new Paint();
Paint black = new Paint();
Paint colorPaint = new Paint();
Bitmap grassBMP = BitmapFactory.decodeResource(getResources(), R.drawable.grass);
Bitmap dirtBMP = BitmapFactory.decodeResource(getResources(), R.drawable.dirt);
Bitmap mountainBMP = BitmapFactory.decodeResource(getResources(), R.drawable.mountain);
Bitmap treeBMP = BitmapFactory.decodeResource(getResources(), R.drawable.tree);
Bitmap stoneBMP = BitmapFactory.decodeResource(getResources(), R.drawable.stone);
Bitmap oceanBMP = BitmapFactory.decodeResource(getResources(), R.drawable.ocean);
Bitmap nothingBMP = BitmapFactory.decodeResource(getResources(), R.drawable.nothing);
Bitmap bTemp = null;
double curElevation = 0.0;
boolean drawHeight = false;
boolean drawContour = false;
boolean drawTerrain = false;
boolean minimap = false;
MiniMap mMap;
public void init(){
getHolder().addCallback(this);
wThread = new WorldThread(getHolder(), this);
}
public DrawWorld(Context context) {
super(context);
init();
}
public DrawWorld(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public DrawWorld(Context context, PocketDimension _dim) {
super(context);
dim = _dim;;
init();
}
@Override
protected void onSizeChanged(int xNew, int yNew, int xOld, int yOld){ //used to get the view dimensions.
screenW = xNew;
screenH = yNew;
Log.d("Hub", "Screen W x H : " + screenW + " x " + screenH + " | " + this.getWidth() + " x " + this.getHeight());
numTilesX = screenW / 32;
numTilesY = screenH / 32;
}
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stub
}
public void surfaceCreated(SurfaceHolder arg0) {
//Log.d("Hub","Surface Created");
wThread.setRunning(true);
wThread.start();
}
public void surfaceDestroyed(SurfaceHolder arg0) {
boolean retry = true;
wThread.setRunning(false);
while(retry){
try{
wThread.join();
retry=false;
} catch(InterruptedException e){
}
}
}
/*************************************************************
*
* Get Methods
*
************************************************************/
/*************************************************************
*
* Set Methods
*
************************************************************/
public void setPocketDimension(PocketDimension _dim, MiniMap mm, float pX, float pY){
dim = _dim;
mMap = mm;
playerPos.set(pX, pY);
//Log.d("Hub", "Dimension set, starting thread");
}
public void setPlayerPos(float pX, float pY){
playerPos.x = pX;
playerPos.y = pY;
}
class WorldThread extends Thread{ //Thread for handling tile selection and adjusting map to match character pos.
private SurfaceHolder surfaceHolder;
private DrawWorld dTV; //drawWorld View
public void setRunning(boolean isRun){
run = isRun;
}//end setRunning()
public WorldThread(SurfaceHolder surface, DrawWorld drawWorld) {
surfaceHolder = surface;
dTV = drawWorld;
}
public void run() {
Canvas canvas;
boolean first = false;
//Log.d("Hub", "mMap : " + mMap + " | nTX : " + numTilesX + " | nTY : " + numTilesY);
mMap.setMiniMapInfo(numTilesX, numTilesY);
/*while (run) {
canvas = null;
try {
canvas = surfaceHolder.lockCanvas();
synchronized (surfaceHolder){
if(canvas != null){
dTV.onDraw(canvas);
} else {
Log.d("Hub", "null canvas");
}
}
} finally {
// do this in a finally so that if an except is thrown
// during the above, we don't leave the Surface in an
// inconsistent state
if ( canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
/*******************************************************
*
* Put all things that happen here
*
******************************************************/
//Log.d("Hub", "Draw World Thread");
//} // end while (run)*
}//end run()
} //end WorldThread() class
public void onDraw(Canvas canvas){
//Log.d("Hub", "Starting onDraw()");
Bitmap toDraw = null;
Bitmap player = BitmapFactory.decodeResource(getResources(), R.drawable.player);
//Log.d("Hub", "numTilesX : " + numTilesX + " | numTilesY : " + numTilesY);
heightPaint.setColor(Color.WHITE);
black.setColor(Color.BLACK);
//Log.d("Hub", "onDraw();" + screenW + " | " + screenH); //Test successful, it is reaching onDraw()
//canvas.drawColor(Color.BLACK);
for(int x = -1; x < numTilesX + 2; x++){
for(int y = -1; y < numTilesY + 2 ; y++){
curType = -1;
curX = ((playerPos.x - (numTilesX / 2)) + x);
curY = ((playerPos.y - (numTilesY / 2)) + y);
curXOffset = (playerPos.x - ((int) playerPos.x));
curYOffset = (playerPos.y - ((int) playerPos.y));
// Log.d("Hub", "CurX : " + curX + " | CurY : " + curY);
if(curX >= 0 && curY >= 0 && curX < (200 - (numTilesX / 2)) && curY < (200 - (numTilesY/2))){
curType = dim.getType((int)curX, (int)curY); //get the tile for the current x position
} else {
curType = -1;
}
toDraw = getBMP(curType);
canvas.drawBitmap(toDraw, (x*32) - (curXOffset * 32), (y*32) - (curYOffset * 32), null);
//canvas.drawRect(624,384,624+32+11,384+32+11,heightPaint); //32x32 bitmaps are being drawn at 43x43
canvas.drawBitmap(player, 624, 384, null);
}
}
if(drawHeight || drawContour || drawTerrain){
for(int x = 0; x < 200; x++){ //Draw Heightmap, "Contour" map, and Terrain Map
for(int y = 0; y < 200; y++){
curType = dim.getType(x, y);
curElevation = dim.getElevation(x, y);
if(drawHeight){
heightPaint.setAlpha((int) (255*dim.getElevation(x, y)));
canvas.drawPoint(x + 20, y + 20, black);
canvas.drawPoint(x + 20, y + 20, heightPaint); //Heightmap
}
colorPaint.setColor(Color.WHITE);
if(drawContour){
if(curElevation >= 0.01 && curElevation <0.1) colorPaint.setColor(Color.BLACK);
else if(curElevation >= 0.1 && curElevation <0.2) colorPaint.setColor(Color.rgb(127, 0, 255));
else if(curElevation >= 0.2 && curElevation <0.3) colorPaint.setColor(Color.rgb(75, 0, 130));
else if(curElevation >= 0.3 && curElevation <0.4) colorPaint.setColor(Color.BLUE);
else if(curElevation >= 0.4 && curElevation <0.5) colorPaint.setColor(Color.GREEN);
else if(curElevation >= 0.5 && curElevation <0.6) colorPaint.setColor(Color.YELLOW);
else if(curElevation >= 0.6 && curElevation <0.7) colorPaint.setColor(Color.rgb(255,127,0));
else if(curElevation >= 0.7) colorPaint.setColor(Color.RED);
canvas.drawPoint(x + 20, y + 220, colorPaint); //"Contour" Map
}
if(drawTerrain){
if(curType == 1) colorPaint.setColor(Color.rgb(1, 166, 17));
else if(curType == 2) colorPaint.setColor(Color.rgb(207, 181, 144));
else if(curType == 3) colorPaint.setColor(Color.rgb(105, 108, 117));
else if(curType == 4) colorPaint.setColor(Color.rgb(0, 92, 9));
else if(curType == 5) colorPaint.setColor(Color.rgb(186, 173, 166));
else if(curType == 6) colorPaint.setColor(Color.BLUE);
canvas.drawPoint(x + 20, y + 420, colorPaint); //Terrain Map
}
}
}
}
r = rand.nextInt();
g = rand.nextInt();
b = rand.nextInt();
colorPaint.setColor(Color.rgb(r, g, b));
canvas.drawRect (0,0,10,10,colorPaint);
//Log.d("Hub", "Ending onDraw()");
}// end onDraw()
public Bitmap getBMP(int nBMP){
bTemp = nothingBMP; // image for areas beyond the map
switch (dimType){
case 1:
switch(nBMP){
case -1:
bTemp = nothingBMP;
break;
case 1 :
bTemp = grassBMP;
break;
case 2 :
bTemp = dirtBMP;
break;
case 3 :
bTemp = mountainBMP;
break;
case 4 :
bTemp = treeBMP;
break;
case 5 :
bTemp = stoneBMP;
break;
case 6 :
bTemp = oceanBMP;
break;
}
}
//Log.d("Hub", "getBMP() " + dimType + " | " + nBMP + " | " + bTemp );
//bTemp.setDensity(0x0000000);
return bTemp;
}//end getBMP();
}
The density-based scaling actually happens when you decode the bitmap with decodeResources
. You can use an overload with BitmapFactory.Options
specified. There are a number of options, but you probably just want to set inScaled
to false
.