I am having trouble tiling a Bitmap
. I want to have the Bitmap
drawn to coordinates defined in a 2D Array
.
I would like to be able to draw let's say "grass" to certain coordinates, and "water,etc.." to other coordinates.
I have spent days trying to figure this out, and would very greatly appreciate any insight. I can only get the Canvas
to draw 1 "grass" Bitmap
, So I feel I have an error in my for loop. I have looked here and here, amongst many others, and do not want every tile to be the same. Here is my code:
MapLoader.java
public class MapLoader extends SurfaceView implements SurfaceHolder.Callback,
Runnable {
SurfaceHolder holder;
Thread thread;
Bitmap grass = BitmapFactory.decodeResource(getResources(),
R.drawable.grass);
boolean running = false;
int[][] grassCoords = new int[][] { { 0, 16, 32, 48, 64 },
{ 0, 16, 32, 48, 64 }, { 0, 16, 32, 48, 64 },
{ 0, 16, 32, 48, 64 }, { 0, 16, 32, 48, 64 } };
public MapLoader(Context context) {
super(context);
holder = getHolder();
holder.addCallback(this);
}
public MapLoader(Context context, AttributeSet attrs) {
super(context, attrs);
holder = getHolder();
holder.addCallback(this);
}
public MapLoader(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
holder = getHolder();
holder.addCallback(this);
}
public void pause() {
running = false;
while (running) {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
break;
}
thread = null;
}
public void resume() {
running = true;
thread = new Thread(this);
thread.start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
running = true;
thread = new Thread(this);
thread.start();
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
Canvas c = holder.lockCanvas();
draw(c);
holder.unlockCanvasAndPost(c);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
@Override
public void run() {
while (running == true) {
// performs drawing to the canvas
if (!holder.getSurface().isValid()) {
continue;
}
Canvas c = holder.lockCanvas();
int x = 0;
int y = 0;
for (x = 0; x < grassCoords.length; x += grass.getWidth()) {
for (y = 0; y < grassCoords.length; y += grass.getHeight()) {
c.drawBitmap(grass, x, y, null);
}
}
holder.unlockCanvasAndPost(c);
}
}
}
ActivityClass.java
public class Test extends Activity {
MapLoader mapLoader;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mapLoader = new MapLoader(this);
setContentView(mapLoader);
}
}
Any help or suggestions (even a link to an effective method) would be greatly appreciated!
Thanks,
Matt
Use the Canvas method public void drawBitmap (Bitmap bitmap, Rect src, RectF dst, Paint paint) . Set dst to the size of the rectangle you want the entire image to be scaled into. EDIT: Here's a possible implementation for drawing the bitmaps in squares across on the canvas.
There is no way to extract the Bitmap out of a Canvas . The only way you can access it is to pass it yourself when creating the canvas like this new Canvas(myBitmap) and keep the reference.
android.graphics.drawable.BitmapDrawable. A Drawable that wraps a bitmap and can be tiled, stretched, or aligned. You can create a BitmapDrawable from a file path, an input stream, through XML inflation, or from a Bitmap object. It can be defined in an XML file with the <bitmap> element.
Android App Development for Beginners This example demonstrates how do I convert Bitmap to drawable in android. Step 1 − Create a new project in Android Studio, go to File ⇒ New Project and fill all required details to create a new project. Step 2 − Add the following code to res/layout/activity_main. xml.
It isn't easy to understand what you are trying to do...
How do you encode coordinates into that grassCoords
array? As its current form it has 5x5
elements.
int[][] grassCoords = new int[][] { { 0, 16, 32, 48, 64 },
{ 0, 16, 32, 48, 64 }, { 0, 16, 32, 48, 64 },
{ 0, 16, 32, 48, 64 }, { 0, 16, 32, 48, 64 } };
Since it has grass
in its name I assume you want to draw only grass, then you could define it like this
int[][] grassCoords = new int[][] { {0, 0}, {16, 16}, {32, 32} };
Above each element like {0, 0}
would be a single coordinate for a grass tile.
Second issue is with your loop, you don't read any data from grassCoords
except arrays length and when you increment the index you increment it with grass.getWidth()
which doesn't really make sense.
int x = 0;
int y = 0;
for (x = 0; x < grassCoords.length; x += grass.getWidth()) {
for (y = 0; y < grassCoords.length; y += grass.getHeight()) {
c.drawBitmap(grass, x, y, null);
}
}
You should iterate array correctly and fetch the data from it.
int x = 0;
for (x = 0; x < grassCoords.length; x++) {
c.drawBitmap(grass, grassCoords[x][0], grassCoords[x][1], null);
}
If I were you I would study related parts of Java tutorial at least once.
for (x = 0; x < grassCoords.length; x += grass.getWidth()) {
for (y = 0; y < grassCoords.length; y += grass.getHeight()) {
c.drawBitmap(grass, x, y, null);
}
}
The reason it only draws once is this bit right here. grassCoords.length
is 5
. When you add the grass width to x
after the first draw, it goes over 5, and the loop ends. You need to use a separate variable for the two. Same for y
. There are other issues with this, as auselen points out, but this is the reason it only draws once to begin with.
However, you can do away with the coordinates array altogether if you want to seamlessly tile a rectangle with one bitmap. You don't even need to know how many tiles wide/tall it is. This is especially useful if you're using a base layer of grass below other tiles, if you're tiling a pattern for a background image, etc. You could do that like this:
for(int x = startX; x < endX; x += grass.getWidth()){
for(int y = startY; y < endY; y += grass.getHeight()){
c.drawBitmap(grass, x, y, null);
}
}
Remember, if you just want to fill with tiles at regular intervals, there is no need to define the coordinates. They will all be multiples, so defining a coordinates array at all doesn't make much sense. Just consider each tile spot as a grid point and multiply by the tile's height/width.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With