Question

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();

}
Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top