【问题标题】:Tile a Bitmap on SurfaceView Canvas在 SurfaceView 画布上平铺位图
【发布时间】:2013-08-24 19:30:05
【问题描述】:

我无法平铺Bitmap。我想让Bitmap 绘制到二维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);

}
}

任何帮助或建议(甚至是有效方法的链接)都将不胜感激!

谢谢,

马特

【问题讨论】:

    标签: android bitmap android-canvas surfaceview tile


    【解决方案1】:

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

    如何将坐标编码到 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() 增加它,这实际上没有意义。

        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 的相关部分。

    【讨论】:

    • 感谢您的链接和解释。一开始我很难理解二维数组。这两个答案都非常有帮助,并且教会了我很多。谢谢你和@Geobits!
    【解决方案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);
        }
    }
    

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

    【讨论】:

      猜你喜欢
      • 2011-06-17
      • 2013-03-15
      • 2020-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-21
      相关资源
      最近更新 更多