Рисование карты на основе плитки - PullRequest
2 голосов
/ 03 января 2012

Этот сценарий рисует элементы управления, героя, поверхность и карту:

public void render(Canvas canvas) {
        canvas.drawColor(Color.TRANSPARENT);

        Drawable myImage;

        int tileWidth = 50;
        int tileHeight = 50;

        int rowBaseX = 0;
        int rowBaseY = 0;

        int[][] board = new int[][] {
                {0,0,0,0,0,0,2,0,0,0,},
                {0,0,0,0,0,2,2,0,0,0,},
                {0,0,0,0,0,2,0,0,0,0,},
                {0,0,0,0,0,2,0,0,0,0,},
                {0,0,0,2,2,2,0,0,0,0,},
                {0,0,0,2,0,0,0,0,0,0,},
                {0,0,0,2,0,0,0,0,0,0,},
                {0,0,2,2,0,0,0,0,0,0,},
                {0,0,2,0,0,0,0,0,0,0,},
                {0,0,2,0,0,0,0,0,0,0,}
                };
        int mapWidth = 10;
        int mapHeight = 10;

        for (int row = 0; row < mapHeight; row++)
        {

        for (int col = 0; col < mapWidth; col++)
        {
        Resources res = this.getContext().getResources();

        switch(board[row][col])
        {
        case 0:
        myImage = res.getDrawable(R.drawable.tile1);
        break;
        case 1:
        myImage = res.getDrawable(R.drawable.tile2);
        break;
        default:
        myImage = res.getDrawable(R.drawable.tile3);
        break;
        }

        int curL = rowBaseX + (col * tileWidth);
        int curU = rowBaseY + (row * tileHeight);
        int curR = curL + tileWidth;
        int curD = curU + tileHeight;

        myImage.setBounds(curL,curU,curR,curD);
        myImage.draw(canvas);
        }
        }

        droid.draw(canvas);
        butt.draw(canvas);
        butt1.draw(canvas);
        butt2.draw(canvas);
        butt3.draw(canvas);
        buttz.draw(canvas);
        buttz1.draw(canvas);
        buttz2.draw(canvas);
        buttz3.draw(canvas);
        buttx.draw(canvas);
    }

Есть герой, который должен быть перерисован, когда игрок перемещает его с помощью элементов управления, и все другие элементы рисования такжебыть перерисованным.Проблема в том, что рисование карты - это долгий процесс, поэтому, чем большую карту я создаю, тем медленнее движется герой, потому что все плитки карты должны быть нарисованы.Есть ли способ поместить все плитки в одно растровое изображение в другом методе и нарисовать это одно растровое изображение в методе canvas?

Ответы [ 2 ]

3 голосов
/ 03 января 2012

Если создание статической карты вне вашего приложения не вариант, вы можете отделить рисование статического содержимого от динамического содержимого.

Создайте Bitmap, создайте Canvas с ним и нарисуйтеваша карта на этом Canvas.Вам нужно сделать это только один раз.Визуализируйте динамический контент один раз за кадр на другом Canvas.Затем нарисуйте оба Bitmap s на "реальном" Canvas вашего SurfaceView.Это может выглядеть следующим образом:

часть для каждой карты:

Bitmap mapBitmap = Bitmap.createBitmap(width, height, myConfig);
Canvas c = new Canvas(mapBitmap);
//draw map on c

... и часть для каждого кадра:

//draw dynamic stuff    
Canvas canvas = getHolder().lockCanvas();
    canvas.drawBitmap(mapBitmap, null, targetRect, null);
    canvas.drawBitmap(heroBitmap, null, targetRect, null);
    getHolder().unlockCanvasAndPost();

РЕДАКТИРОВАТЬ:

Вы рисуете свои плитки, как вы привыкли с myImage.draw(canvas), но передавая mapBitmap- Canvas в качестве аргумента вместо вашего "реального" холста.myConfig должно быть Bitmap.Config .Возьмите RGB_565 как внутренний формат.

2 голосов
/ 03 января 2012

Лучший вариант - нарисовать только ту часть карты, которая видна на экране.Таким образом, независимо от того, насколько большой общая карта становится чертежом, эта карта всегда постоянна.Поскольку вы находитесь в сетке, вы можете легко определить, в какой ячейке находится герой:

heroGridX = hero.x % mapWidth;
heroGridY = hero.y % mapHeight;

Отсюда вы можете рассчитать, сколько клеток вокруг игрока вы хотите нарисовать, используя ширину и высоту.холста и постоянный размер ширины и высоты ячейки вашей сетки:

leftGrid = heroGridX - (canvas.getWidth() / tileWidth) / 2;
topGrid = heroGridY - (canvas.getHeight() / tileHeight) / 2;
rightGrid = heroGridX + (canvas.getWidth() / tileWidth) / 2;
bottomGrid = heroGridY + (canvas.getHeight() / tileHeight) / 2;

Вы можете использовать структуру данных для хранения этих значений независимо от героя и перемещать их только после того, как игрок приблизится к краюпрокрутить карту.Таким образом, герой перемещается вверх и вниз, не прокручивая карту, пока не получит X или Y пикселей к краю плитки.Вместо того, чтобы вычислять их внутри процедуры рендеринга.

Это будет использовать гораздо меньше памяти, чем рисование всей карты в одном большом растровом изображении.Рисование в большом растровом изображении торгует большим использованием памяти за меньшее время процессора.По мере того, как ваша карта становится больше, увеличивается и память, необходимая для ее рисования.Этот алгоритм просто продолжает рисовать карту постоянной, потому что размер вашего экрана не изменяется во время выполнения.И, по сравнению с другим вариантом, использование вашей памяти не увеличивается по мере увеличения вашей карты (она становится очень маленькой по сравнению с рисованием большего количества плиток на холсте).Одним из важных фактов является то, что если вы получили больший экран (скажем, планшет против телефона).Этот алгоритм также будет правильно масштабироваться, чтобы игрок мог видеть больше окружающей местности на карте.

...