在SurfaceView Canvas上平铺位图

时间:2013-08-24 19:30:06

标签: android bitmap android-canvas surfaceview tile

我无法平铺Bitmap。我希望将Bitmap绘制到2D Array中定义的坐标。

我希望能够将“草”描绘到某些坐标,并将“水等等”绘制到其他坐标。

我花了好几天试图解决这个问题,并且非常感谢任何见解。我只能让Canvas绘制1“草”Bitmap,所以我觉得我的for循环中有错误。我看过herehere等等,并不希望每个瓷砖都是一样的。这是我的代码:

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

}
}

非常感谢任何帮助或建议(甚至是有效方法的链接)!

谢谢,

马特

2 个答案:

答案 0 :(得分:4)

要理解你想要做什么并不容易......

如何将坐标编码为grassCoords数组?作为其当前形式,它具有5x5个元素。

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 } };

由于名称中有grass,我假设您只想绘制草,然后您可以像这样定义

int[][] grassCoords = new int[][] { {0, 0}, {16, 16}, {32, 32} };

{0, 0}之类的每个元素上方都是草瓦的单个坐标。

第二个问题在于你的循环,除了数组长度之外你没有从grassCoords读取任何数据,当你递增索引时,你用grass.getWidth()增加它,这实际上没有用。< / p>

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

    }

您应该正确迭代数组并从中获取数据。

    int x = 0;
    for (x = 0; x < grassCoords.length; x++) {
        c.drawBitmap(grass, grassCoords[x][0], grassCoords[x][1], null);
    }

如果我是你,我会至少研究一次Java tutorial的相关部分。

答案 1 :(得分:2)

for (x = 0; x < grassCoords.length; x += grass.getWidth()) {
    for (y = 0; y < grassCoords.length; y += grass.getHeight()) {
        c.drawBitmap(grass, x, y, null);
    }
}

它只吸引一次的原因就在这里。 grassCoords.length5。在第一次绘制后将草宽添加到x时,它会超过5,并且循环结束。您需要为两者使用单独的变量。 y也是如此。正如auselen指出的那样,还存在其他问题,但这就是它开始只吸引一次的原因。

但是,如果要使用一个位图无缝平铺矩形,则可以完全取消坐标数组。你甚至不需要知道它有多少瓷砖宽/高。如果你在其他瓷砖下面使用草的基础层,如果你为背景图像平铺图案等,这尤其有用。你可以这样做:

for(int x = startX; x < endX; x += grass.getWidth()){
    for(int y = startY; y < endY; y += grass.getHeight()){
        c.drawBitmap(grass, x, y, null);
    }
}

请记住,如果您只想定期填充图块,则无需定义坐标。它们都是倍数,因此定义坐标数组并没有多大意义。只需将每个图块点视为网格点并乘以图块的高度/宽度。