«Интересное» поведение Flash / Flex: увеличение времени рисования 10 000 треугольников - PullRequest
1 голос
/ 02 ноября 2009

Это тестовая программа для измерения времени, которое требуется Flash для рисования треугольника 10000 раз.

Приложение (код ниже) вызывает runTimeTest () каждые N секунд, которые рисуют треугольник 10000 раз.

Теперь о «интересной» части: каждый вызов требует все больше и больше процессоров, пока после 6-го или 7-го вызова он не перейдет в «бесконечность» (см. Снимок экрана TaskManager)

Странная ошибка или объяснение ??

// create a Canvas to draw on

var c:Canvas = new Canvas();

function onApplicationComplete(e:Event)
{
    c.width = width;
    c.height = height;

    c.x = 0;
    c.y = 0;

    addChild(c);

    // set up a timer to run every 10 seconds

    var timer:Timer = new Timer(10000);
    timer.addEventListener(TimerEvent.TIMER, runTimeTest);
    timer.start();
}

function runTimeTest(e:Event)
{
    // this is called every 10 seconds

    var x0:int, x1:int, x2:int;
    var y0:int, y1:int, y2:int;

    // set triangle vertices

    x0 = 100; y0 = 500;
    x1 = 120; y1 = 515;
    x2 = 155; y2 = 500;

    // draw a filled triangle 10,000 times

    for (var i:int = 0; i < 10000; ++i)
    {
        c.graphics.beginFill( 0xff0000, 1 );
        c.graphics.moveTo( x0, y0 );

        c.graphics.lineTo( x1, y1 );
        c.graphics.lineTo( x2, y2 );
        c.graphics.lineTo( x0, y0 );

        c.graphics.endFill();
    }
}

i34.tinypic.com / jutpwo.png

1 Ответ

3 голосов
/ 05 ноября 2009

"Как насчет того, чтобы вызвать c.graphics.clear () в начале runTimeTest?"
Джеймс Уорд

Да, добавление c.graphics.clear () исправило это.
Matt

Flash сохраняет все команды рисования (т.е. графику) до тех пор, пока вы не вызовете graphics.clear (). Это позволяет рисовать несколько кадров без необходимости рисовать все сразу.

Причина, по которой рисование треугольников занимает все больше и больше времени, заключается в том, что каждый раз, когда вы вызываете runTimeTest () Flash вынужден рисовать дополнительные 10 000 треугольников.

Таким образом, в первый раз, когда он называется Flash, он рисует 10 000 треугольников, во второй раз, когда вы вызываете runTimeTest (), он должен нарисовать первые 10000 треугольников (потому что вы не очистили холст), а затем вторые 10000 треугольников.

Решение, как указывает Гленн, состоит в том, чтобы очистить холст перед рисованием каждого набора треугольников. Таким образом, Flash должен только нарисовать текущий набор треугольников.

Если по какой-либо причине вам нужно нарисовать на экране абсурдное количество элементов, вы можете воспользоваться преимуществами кэширования растрового изображения: если вы каждый раз рисуете графику на другом Canvas / Sprite, тогда Flash должен рисовать только каждую графику. один раз (остальные кешируются в памяти за кулисами).

* * 1 022, например,
private function drawTriangles():void
{
    var x0:int, x1:int, x2:int;
    var y0:int, y1:int, y2:int;

    // set triangle vertices

    x0 = 100; y0 = 500;
    x1 = 120; y1 = 515;
    x2 = 155; y2 = 500;

    // This is the important part.
    // Draw 10,000 triangles only on this new sprite.
    var c:Sprite = new Sprite();
    c.cacheAsBitmap = true;
    addChild(c);


    for (var i:int = 0; i < 10000; ++i)
    {
        c.graphics.beginFill( 0xff0000, 1 );
        c.graphics.moveTo( x0, y0 );

        c.graphics.lineTo( x1, y1 );
        c.graphics.lineTo( x2, y2 );
        c.graphics.lineTo( x0, y0 );

        c.graphics.endFill();
    }

}

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

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

В общем, рисуйте только то, что вам нужно, и выполняйте graphics.clear (), если вам не нужно сохранять то, что было ранее на холсте.


В ответ на комментарий Мэтта:

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

Это не будет иметь никаких преимуществ в производительности, это просто изменит то, что нарисовано. Если вы рисуете над одной и той же областью в течение одного и того же раздела beginFill / endFill, он будет «инвертировать» нарисованный раздел каждый раз.

Немного сложно объяснить без примера ...

Позволяет изменить функцию треугольника, чтобы она рисовала два треугольника в одном и том же разделе beginFill / endFill:

    c.graphics.beginFill( 0xff0000, 1 );
    for (var i:int = 0; i < 2; ++i)
    {
        c.graphics.moveTo( x0, y0 );

        c.graphics.lineTo( x1, y1 );
        c.graphics.lineTo( x2, y2 );
        c.graphics.lineTo( x0, y0 );    
    }
    c.graphics.endFill();

Если вы запустите это, то вы ничего не увидите на экране!

Это потому, что вы дважды рисуете над одной и той же областью, и она переворачивается (делается прозрачной) - технически Flash все еще рисует, но вы просто не можете ее видеть.

Если вы измените количество итераций на 3, то вы снова увидите треугольник (потому что он каждый раз переключается с видимого -> невидимого -> видимого).

Эта страница объясняет это довольно хорошо (см. Раздел «Обмотка» примерно на треть пути вниз) - хотя речь идет именно о Flash Player 10, та же идея применялась в предыдущих версиях, мы просто не имели контроля над это тогда :) http://www.flashperfection.com/tutorials/Flash-Player-10-Drawing-API-10877.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...