代码之家  ›  专栏  ›  技术社区  ›  MattMatt

在SurfaceView画布上平铺位图

  •  5
  • MattMatt  · 技术社区  · 12 年前

    我在铺瓷砖时遇到问题 Bitmap 。我想要 位图 绘制到二维中定义的坐标 Array .

    我希望能够在某些坐标上画出“草”,在其他坐标上画“水等”。

    我花了好几天的时间试图弄清楚这一点,如果有任何见解,我将不胜感激。我只能得到 Canvas 绘制1个“草” 位图 ,所以我觉得我的for循环中有一个错误。我看了 here here ,等等,并且不希望每个瓦片都是相同的。这是我的代码:

    地图加载器.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);
    
        }
    
    }
    
    }
    

    活动类.java

    public class Test extends Activity {
    
    MapLoader mapLoader;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        mapLoader = new MapLoader(this);
        setContentView(mapLoader);
    
    }
    }
    

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

    谢谢

    马特

    2 回复  |  直到 8 年前
        1
  •  4
  •   auselen    12 年前

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

    你如何将坐标编码成 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} 将是草地瓷砖的单个坐标。

    第二个问题是你的循环,你没有从中读取任何数据 草地坐标 除了数组长度,当你增加索引时,你会用它来增加 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 至少一次。

        2
  •  2
  •   Geobits    12 年前
    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.length 5 。将草的宽度添加到 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);
        }
    }
    

    请记住,如果您只想以规则的间隔填充瓷砖,则无需定义坐标。它们都是倍数,所以定义一个坐标数组根本没有多大意义。只需将每个平铺点视为一个网格点,然后乘以平铺的高度/宽度。