Простое тестовое приложение Flash работает очень медленно по сравнению с точно таким же апплетом Processing.

Так что я постепенно, мучительно перехожу от Processing к Flash, чтобы, надеюсь, разрабатывать игры для более широкой аудитории. В конце концов, я получил работающее приложение на Flash, которое просто позволяет пользователю щелкать, чтобы создавать блоки, которые впоследствии тяготеют к мыши. Я сделал то же самое в Processing, просто чтобы сравнить скорости. Однако, когда я запускаю Flash-версию и добавляю около 15-20 блоков, частота кадров падает до 5-10 FPS. В версии Processing я могу добавить ~60 без заметного замедления. В чем дело, Флэш?

Ссылки на источник каждой версии:

Flash-версия

Версия обработки

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

Флэш-версия:

блоки.fla

import flash.events.Event;
import flash.display.MovieClip;

stage.addEventListener( Event.ENTER_FRAME, onenter );
stage.addEventListener( MouseEvent.MOUSE_DOWN, onclick );

var main = this;

var lastFrame:Number;

var Blocks:Array = new Array();

function onenter( e:Event ):void
{
    var time:Number = getTimer();
    for( var i = 0; i < Blocks.length; i++ )
    {
        Blocks[ i ].run();
    }
    FrameRate.text = String( Blocks.length ) + "\n" + String( 1000 / ( time - lastFrame ) );
    lastFrame = time;
}

function onclick( e:MouseEvent ):void
{
    var block1 = new Block( Blocks, main, mouseX, mouseY );
}

Блокировать как

package  {

    import flash.display.MovieClip;
    import flash.geom.Vector3D;

    public class Block extends MovieClip {

        var velocity:Vector3D = new Vector3D( 0, 0 );
        var position:Vector3D = new Vector3D( x, y );
        var acceleration:Vector3D = new Vector3D( 0, 0 );

        public function Block( Blocks:Array, This, x:Number, y:Number ) {
            Blocks.push( this );
            This.addChild( this );
            position.x = x;
            position.y = y;
        }

        public function run()
        {
            x = position.x;
            y = position.y;
            //position.incrementBy( velocity );
            position.x += velocity.x;
            position.y += velocity.y;
            acceleration.x = stage.mouseX - position.x;
            acceleration.y = stage.mouseY - position.y;
            acceleration.normalize();
            //velocity.incrementBy( acceleration );
            velocity.x += acceleration.x;
            velocity.y += acceleration.y;
            velocity.x *= 0.95;
            velocity.y *= 0.95;
            this.graphics.beginFill( 0 );
            this.graphics.moveTo( -10, -10 );
            this.graphics.lineTo( 10, -10 );
            this.graphics.lineTo( 10, 10 );
            this.graphics.lineTo( -10, 10 );
            this.graphics.lineTo( -10, -10 );
            this.graphics.endFill();
        }

    }

}

Версия обработки:

sketch_mar02b.pde

Block[] blocks = new Block[ 0 ];

void setup()
{
  frameRate( 60 );
  size( 550, 400 );
  textFont( createFont( "Verdana", 20 ) );
}

void draw()
{
  background( 255 );
  for( int i = 0; i < blocks.length; i++ )
  {
    blocks[ i ].run();
  }
  text( blocks.length + "\n" + frameRate, 0, 20 );
}

void mousePressed()
{
  new Block( mouseX, mouseY );
}

Блок.pde

class Block
{
  PVector position = new PVector( 0, 0 );
  PVector velocity = new PVector( 0, 0 );
  PVector acceleration = new PVector( 0, 0 );
  Block( float x, float y )
  {
    position.set( x, y, 0 );
    blocks = ( Block[] ) append( blocks, this );
  }
  void run()
  {
    position.add( velocity );
    acceleration.set( mouseX - position.x, mouseY - position.y, 0 );
    acceleration.normalize();
    velocity.add( acceleration );
    velocity.mult( 0.95 );
    pushMatrix();
    translate( position.x, position.y );
    fill( 0 );
    rect( -10, -10, 20, 20 );
    popMatrix();
  }
}

Спасибо за помощь!


person Zane Geiger    schedule 03.03.2011    source источник


Ответы (1)


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

Но что, если по какой-то причине вам ДЕЙСТВИТЕЛЬНО приходится перерисовывать каждый кадр? Может быть, чтобы изменить цвет коробки с течением времени? Ну, вы пренебрегаете очисткой своего старого изображения... поэтому с каждым кадром вы просто добавляете все больше и больше векторных точек к графическим объектам. Таким образом, на самом деле, несмотря на то, что у вас есть только один черный квадрат, на самом деле всего за несколько секунд у вас есть данные на тысячи черных квадратов. Вы можете очистить графический объект следующим образом...

this.graphics.clear();

В качестве микрооптимизации вы можете назначить this.graphics локальной переменной...

var g:Graphics = this.graphics
g.moveTo(0); // and so on...

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

Так как это блок, с которым вы имеете дело, вы также можете использовать graphics.drawRect() вместо рисования блока построчно.

В моем собственном тестировании вариант 1 работал лучше всего. Если вам нужно перерисовать, убедитесь, что вы используете graphics.clear(), так как это работает почти так же хорошо даже для большого количества блоков.

РЕДАКТИРОВАТЬ, чтобы добавить...

Ваш пример после добавления вызовов функций .clear() работает очень хорошо. Однако я должен предупредить вас, что JVM наверняка будет иметь лучшую производительность, чем Flash Player. Это не означает, что люди не могут создавать высокопроизводительные Flash-приложения, но верхний предел производительности Flash Player при работе с процессорным рендерингом намного ниже, чем у Java. Конечно, если вы хотите жить на переднем крае, вы можете проверить новый 3D-API "Molehill", который способен на такие вещи...

3D-игра на Wii, перенесенная на Flash с использованием кротовины, работающая со скоростью 60 кадров в секундуhttp://blog. theflashblog.com/?p=2593

person scriptocalypse    schedule 03.03.2011
comment
Ах, спасибо. У меня сложилось впечатление, что графический буфер по умолчанию очищался каждый кадр. Я все еще не привык к тому, что каждый объект имеет свой собственный графический слой... Изменить: попробовал ваше решение (перемещение графического кода в конструктор), и оно сработало как шарм. Благодаря тонну! - person Zane Geiger; 03.03.2011