Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Движение больших слоев фона (http://www.flasher.ru/forum/showthread.php?t=173464)

FieryWall 03.01.2012 22:31

Движение больших слоев фона
 
Все нет сил :wacko: было бы все супер, если бы не унылая оптимизация :( Перерыл интернет превратив браузер и рабочий стол в мусорку.
Ситуация такая:
Входные данные: контейнеры размером примерно 3000х1000 с векторной графикой.
Инициализация: создаю новые контейнеры с предыдущих но уже с растерезированным вектором и добавляю их на сцену. Старые контейнеры с их начинкой сравниваем с null.
Итерация: контейнеры стоят на своих местах, с помощью clear(), Matrix() и beginBitmapFill() перерисовываю сохраненную битмапку в свой контейнер.

При таком раскладе фпс падает до 16, если контейнеры убрать - получаю необходимые 28-31.
Если при итерации ничего не перерисовывать и даже не двигать сцену - те же 16 (и область перерисовки - весь экран).
Пробовал ограничить drawRect() размерами флешки, получил в ответ 14 фпс (((
Помогите, буду признателен.

carrotoff 03.01.2012 22:49

Цитата:

Итерация: контейнеры стоят на своих местах, с помощью clear(), Matrix() и beginBitmapFill() перерисовываю сохраненную битмапку в свой контейнер.
А вот про это можно подробней

undefined 03.01.2012 23:04

если нужен только скроллинг без изменения фона, рекомендую копать в сторону scrollRect, мега быстрая фича.

FieryWall 03.01.2012 23:09

Код AS3:

//fonMtx - матрица, определяю для сдвига картинки
fonMtx.tx = fon.x - par.x / speed;
fonMtx.ty = fon.y - par.y / speed;
//чищу предыдущую
graphics.clear();
//рисую новую
graphics.beginBitmapFill(fonDat, fonMtx, false, true);
//прямоугольник, обязательно
graphics.drawRect(fon.x - par.x / speed, fon.y - par.y / speed, temp.x, temp.y);
graphics.endFill();
//собственно вся итерация


carrotoff 03.01.2012 23:13

Я поддержу, попробуйте scrollRect

crazyone 03.01.2012 23:32

Не уверен, но мне кажется, что bitmapData.draw будет быстрее, чем beginBitmapFill.

Причем если есть возможность отрисовывать содержимое контейнеров в одну битмапдату, то скорость должна сильно повыситься, т.к. плееру не прийдется обрабатывать наложение сложных дисплейобджектов.

СлаваRa 03.01.2012 23:40

по поводу
Цитата:

Не уверен, но мне кажется, что bitmapData.draw будет быстрее, чем beginBitmapFill.
BitmapData.draw x Graphics.beginBitmapFill

FieryWall 04.01.2012 00:10

Всем большущее спасибо!!! Пошел пробовать :)

crazyone 04.01.2012 01:19

Цитата:

Сообщение от СлаваRa (Сообщение 1054860)

Это конечно интересно, но его бенчмарки ни о чем не говорят. Он не рендерит контейнеры, в которые рисует, так что по сути все что происходит при beginBitmapFill() + drawRect() - разметка территории - где и что нарисовать. А сама отрисовка будет происходить только если добавить контейнеры на стейдж.

Либо попытаться отрисовать дисплейобджекты в какую-нибудь битмапу:

Код AS3:

package {
        import flash.display.Bitmap;
        import flash.display.BitmapData;
        import flash.display.Shape;
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.MouseEvent;
        import flash.utils.getTimer;
 
        /**
        * ...
        * @author DoctorSTaL
        */

        public class Main extends Sprite {
                private var arr:Array;
                private var phase:int;
                private var _testMethods:Array;
                private var container:Sprite;
 
                public function Main():void {
                        super.addEventListener(Event.ADDED_TO_STAGE, this.addedToStage);
                }
 
                private function addedToStage(event:Event = null):void {
                        super.removeEventListener(Event.ADDED_TO_STAGE, this.addedToStage);
 
                        // entry point
 
                        _testMethods = new Array();
                        _testMethods.push(testDraw);
                        _testMethods.push(testBitmapFill);
 
                        arr = new Array();
 
                        container = new Sprite();
                        for (var i:int = 0; i < 3000; i++) {
                                var s:Shape = new Shape();
                                s.graphics.beginFill(0xffffff * Math.random(), 1);
                                s.graphics.drawEllipse(0, 0, 200, 100);
                                s.graphics.endFill();
                                var bdata:BitmapData = new BitmapData(200, 100, true, 0);
                                bdata.draw(s);
                                arr.push([s, bdata]);
 
                                s.graphics.clear();
                                container.addChild(s);
                        }
                        stage.addEventListener(MouseEvent.CLICK, this_clickHandler);
                }
                private function testDraw():void {
                        var bdata:BitmapData = new BitmapData(200, 100);
                        for (var i:int = 0; i < arr.length; i++) {
                                bdata.draw(arr[i][1]);
                        }
                }
 
                private function testBitmapFill():void {
                        var s:Shape;
 
                        for (var i:int = 0; i < arr.length; i++) {
                                s = arr[i][0];
                                s.graphics.clear();
                                s.graphics.beginBitmapFill(arr[i][1]);
                                s.graphics.drawRect(0,0,200, 100);
                                s.graphics.endFill();
                        }
 
                        new BitmapData(200, 100, true, 0).draw(container);
                }
 
 
                private function this_clickHandler(event:MouseEvent):void {
                        var time:uint = getTimer();
 
                        _testMethods[phase]();
                        trace("phase "+phase+":"+(getTimer() - time));
                        phase = (phase + 1) % _testMethods.length;
                }
        }
}


Цитата:

phase 0:146
phase 1:3142

artcraft 04.01.2012 01:43

если фон не масштабируется, не поворачивается, и сдвигается на целые пиксели, то bitmapData.copyPixels даст наилучшую производительность

crazyone 04.01.2012 02:04

Цитата:

Сообщение от artcraft (Сообщение 1054883)
если фон не масштабируется, не поворачивается, и сдвигается на целые пиксели, то bitmapData.draw даст наилучшую производительность

Я проверял - масштабирование, повороты и сдвиги через параметр matrix в методе draw на скорость не влияют. То же самое и с другими параметрами метода. На скорость draw влияет только количество пикселей, которые нужно отрисовать в битмапу, так что если повернуть исходное изображение таким образом, что количество пикселей, попадающих в битмапу уменьшится, - скорость отрисовки пропорционально увеличится.

Мне уже лень делать тесты, но, насколько я знаю, быстрее draw только copyPixels.

artcraft 04.01.2012 12:51

Цитата:

Сообщение от crazyone (Сообщение 1054885)
Я проверял - масштабирование, повороты и сдвиги через параметр matrix в методе draw на скорость не влияют. То же самое и с другими параметрами метода. На скорость draw влияет только количество пикселей, которые нужно отрисовать в битмапу, так что если повернуть исходное изображение таким образом, что количество пикселей, попадающих в битмапу уменьшится, - скорость отрисовки пропорционально увеличится.

Мне уже лень делать тесты, но, насколько я знаю, быстрее draw только copyPixels.

действительно я выжил из ума и написал draw когда имел в виду copyPixels

FieryWall 04.01.2012 13:31

copyPixels() действительно хорош, попробовал - появились впечатляющие результаты, scrollRect - вообще не вариант.
Но было бы неплохо если бы мне подсказали как избежать эффекта "победа пасьянс ХР" (наложение новых пикселей на старые) :(

crazyone 04.01.2012 14:22

Конечно же, нужно очистить изображение. Например так:
Код AS3:

bdata.fillRect(bdata.rect,0x00000000);


artcraft 04.01.2012 14:25

bitmapData.fillRect() то что надо для очистки экрана
но очистка нужна только если фон прозрачный, если фон без альфаканала, то достаточно нарисовать новаый фон прямо поверх старого.

FieryWall 04.01.2012 18:50

Когда я рисую в основной битмап через copyPixels() то следующее изображение режет все те что на уровень ниже прозрачными пикселями, как это обойти?

artcraft 04.01.2012 19:34

если я не ошибаюсь, то последний пареметр copyPixels - mergeAlpha отвечает за это


Часовой пояс GMT +4, время: 11:02.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.