Как показать растровое изображение, которое является только частью его BitmapData в AS3? - PullRequest
1 голос
/ 14 мая 2011

Я пишу скроллер для игры, которую делаю.Есть объект BitmapData, который содержит фоновый рисунок, но я не хочу показывать / отображать его на экране сразу.

Например, я хочу показать только раздел данных размером 500x500, но весь BitmapData равен 1000x1000.Я хотел использовать метод scroll () для прокрутки данных, но моя проблема в том, что я не могу ограничить объем BitmapData, отображаемого на растровом изображении.Я попытался установить свойства высоты / ширины BitmapData в 500x500 (и нарисовать все 1000x1000), но любые данные, нарисованные за пределами определенных мной границ, на самом деле не отображаются.

Другой вариант, который я рассмотрел, - это сохранить другой объект BitmapData, который содержит все данные, и затем использовать copyPixels () от него до того, который используется на самом растровом изображении, хотя тогда я не могуиспользуйте scroll () и используйте разные методы для достижения прокрутки.

Заранее благодарен всем, кто ответит.

Ответы [ 3 ]

4 голосов
/ 14 мая 2011

Лучший способ сделать это - перехватить, используя CopyPixels (). По сути, вы добавите растровый объект в размер сцены правильно, чтобы отразить область, которую вы хотите отобразить, а затем вы будете использовать CopyPixels для переноса только того, что вы хотите отобразить в любой момент времени.

var largeBitmap:Bitmap = yourLargeBitmap;
var displayBitmap:Bitmap = new Bitmap(new BitmapData(500, 500));
addEventListener(Event.ENTER_FRAME, loop);

function loop(e:Event):void {
displayBitmap.bitmapData.copyPixels(largeBitmap, new Rectangle(X, Y, 500, 500), new Point());
}

Заполните X и Y, и все готово!

Редактировать : Да, это требует удвоения памяти, потому что вы в сущности держите в памяти два объекта растровых данных в любой момент времени - но, честно говоря, это будет минимальной проблемой. Особенно, если ваши растровые изображения настолько малы, объем памяти незначителен. Что приятно, однако, это то, что вы обходите стороной любые манипуляции с объектами или шутки с отображаемым списком - и именно в этом и заключаются главные преимущества в производительности. при развертывании на мобильном устройстве или создании более крупного фона, или чего-то еще, вы увидите увеличение производительности от перехвата маскирования или масштабирования или любого другого трюка. Насколько я знаю, это обычно считается наилучшей практикой. / Edit

Обратите внимание, что во многих игровых инфраструктурах (например, Flixel) встроены движки бликования. Вы получаете гораздо лучшую производительность, если все стираете, а не используете список отображения.

1 голос
/ 14 мая 2011

Я бы сделал:

//the rectangle you would like to draw
var rectangle:Rectangle = new Rectangle(100,100,400,500);

var shape:Shape = new Shape();
var matrix:Matrix = new Matrix(1,0,0,1,-rectangle.x, -rectangle.y);
shape.graphics.beginBitmapFill(bitmapData, matrix);
shape.graphics.drawRect(0, 0, rectangle.width, rectangle.height);
shape.graphics.endFill();

Затем можно прокрутить, изменив положение прямоугольника или непосредственно изменив матрицу.

ОБНОВЛЕНИЕ: После проверки ответа МикаЯ был удивлен, обнаружив (после довольно быстрых и свободных тестов), что beginBitmapFill на самом деле быстрее, чем copyPixels.Я оставлю свои тестовые коды, поэтому, если вам интересно, попробуйте:

copyPixels (я получаю 15-20 кадров в секунду):

var bmp:BitmapData=new BitmapData(1000, 1000, true, 0);
bmp.perlinNoise(100, 100, 3, 1, true, true);

var arr:Array=new Array();
for (var i:uint = 0; i < 50; i++) {
    var clip:Bitmap = new Bitmap(new BitmapData(500, 500));
    addChild(clip);
    clip.alpha = .05;
    arr.push(clip);
}
var t1:uint = getTimer();
stage.addEventListener("enterFrame", function() {
    trace(getTimer() - t1);
    t1 = getTimer();
    for each(var clip:* in arr) {
        var x:uint=Math.random()*100;
        var y:uint=Math.random()*100;

        clip.bitmapData.copyPixels(bmp,new Rectangle(x,y,500,500), new Point);
    }
});

и beginBitmapFill (я получаю 55-60 кадров в секунду):

var bmp:BitmapData=new BitmapData(1000, 1000, true, 0);
bmp.perlinNoise(100, 100, 3, 1, true, true);

var arr:Array=new Array();
for (var i:uint = 0; i < 50; i++) {
    var clip:Shape = new Shape();
    addChild(clip);
    clip.alpha = .05;
    arr.push(clip);
}
var t1:uint = getTimer();
stage.addEventListener("enterFrame", function() {
    trace(getTimer() - t1);
    t1 = getTimer();
    for each(var clip:* in arr) {
        var x:uint=Math.random()*100;
        var y:uint=Math.random()*100;

        clip.graphics.clear();
        clip.graphics.beginBitmapFill(bmp,new Matrix(1,0,0,1,-x,-y),false,false);
        clip.graphics.drawRect(0,0,500,500);
        clip.graphics.endFill();
    }
});
0 голосов
/ 14 мая 2011

Создайте фигуру, нарисуйте в ней заполненный прямоугольник 500x500 и присвойте его свойству mask для растрового изображения - растровое изображение будет обрезано до этого размера.

...