Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/actionscript-3/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance AS3:使用环绕(graph)将许多相同的形状向左移动--我的尝试太慢了_Performance_Actionscript 3_Graph_Air_Scroll - Fatal编程技术网

Performance AS3:使用环绕(graph)将许多相同的形状向左移动--我的尝试太慢了

Performance AS3:使用环绕(graph)将许多相同的形状向左移动--我的尝试太慢了,performance,actionscript-3,graph,air,scroll,Performance,Actionscript 3,Graph,Air,Scroll,在Flash Pro(AS3)中开发一个简单的教育应用程序时,我陷入了尴尬的停顿 我试图制作一个简单的图表,在发生某些事情时显示垂直峰值(空闲时显示一条平线)。图形是实时的,因为它从程序开始,每隔一帧更新一次。这条线从“图形”对象的一端开始,一直延伸到另一端(例如,超过60秒)。到达末尾后,整个图形开始向左滚动,以便为添加到末尾的更多数据腾出空间。它被设计为永远保持滚动和记录数据(直到用户停止/暂停) 下面是一个例子: 实现这种图形的最佳方式是什么?一个由基线和刻度组成的简单滚动图形 不应该这么

在Flash Pro(AS3)中开发一个简单的教育应用程序时,我陷入了尴尬的停顿

我试图制作一个简单的图表,在发生某些事情时显示垂直峰值(空闲时显示一条平线)。图形是实时的,因为它从程序开始,每隔一帧更新一次。这条线从“图形”对象的一端开始,一直延伸到另一端(例如,超过60秒)。到达末尾后,整个图形开始向左滚动,以便为添加到末尾的更多数据腾出空间。它被设计为永远保持滚动和记录数据(直到用户停止/暂停)

下面是一个例子:

实现这种图形的最佳方式是什么?一个由基线和刻度组成的简单滚动图形

不应该这么难。。。至少我是这么想的。我尝试了4种不同的方法(其中两种证明100%有效,但速度太慢)。外面一定有更好的东西!也许矩阵变换+位图填充


问题结束;简化代码如下


公共类图扩展了Sprite
{
包括“constants.as”;
常量像素因子:数字=(1/图形时间刻度)*1050;//60000ms
const amountToMove:Number=轮询速率*像素因子,inverseTS:Number=1.0/图形\时间刻度;
var graphHolder:graphHolder;//具有许多图形实例的简单(大型)精灵
变量基线:Shape=newshape(),拉伸:Boolean=false;
var apArray:Array=[],apRecycle:Vector.=new[];
var apLength:int=0,firstPeak:Shape;
//变量numberIndicator:TextField=newtextfield();
公共函数图(graphHolder:graphHolder)
{
//设置变量
this.graphHolder=graphHolder;
mouseEnabled=false;mouseChildren=false;
addChild(基线);
有(基线)
{
x=55;y=10;//基线。从55个像素开始,以便添加标签
graphics.lineStyle(2,0x000000);//厚度2,黑色
图形.lineTo(1050,0);
scaleX=0.0005;//基线以一个小点开始,随时间扩展
}
}
//不滚动时,绘制空闲基线。滚动时,向后拖动峰值。
函数drawIdle(timeappeased:int):void
{
if(时间经过图\时间刻度)?1050:(时间经过*像素因子))+54;//55-1
firstPeak.visible=true;
apArray[apArray.length]=第一峰值;
}
其他的
{
//从基线向上绘制7像素的线。
var peakShape:Shape=新形状();
//peakShape.cacheAsBitmap=true;
addChild(峰值形状);
带(峰值形状)
{
//cacheAsBitmap=true;
图形.线型(0x000000);
图形。移动到(1,10);
图形。lineTo(1,3);
x=((时间流逝>图形时间尺度)?1050:(时间流逝*像素因子))+54;//55-1
apArray[apArray.length]=峰值形状;
}
}
++长度;
}
/*将基线重置为小点,移除峰值,重置峰值阵列。
在下一个循环中,循环中的所有峰值仍需提取*/
函数resetGraph():void
{
baseLine.scaleX=0.0005;拉伸=false;
对于每个(var峰值:阵列中的形状)移除Child(峰值);
apArray.length=0;apLength=0;
}
}
因此,本质上,图表上应该有记号,指示实时发生的“动作”。图形到达屏幕末端后开始向左滚动(N秒)。换句话说,在到达指定空间的边缘后,它会无限期地滚动。以下是我尝试的三种实现方法——它们都不是很快,而且其中一些还存在其他问题

  • 在图形上相应的时间点创建并绘制一条新线段——基线线段(微小的水平线)和勾号(垂直线)。图形最多只会持续N秒,但在N+x的时间点上的所有记号仍会绘制,就好像图形永远向右移动一样。然后,我用一个遮罩覆盖图形的矩形区域,一旦图形达到N秒,我就把它移动到左边

    • 开始时速度很慢,但几分钟后速度就慢得令人难以置信,因为Flash显然仍在屏幕左侧处理整个图形
    • 将直线段直接绘制到图形对象是不好的,因为每个线段显然都是一个对象,而且这些无数对象中的每一个在绘制后都没有显式(或隐式)引用。(“眼不见,心不烦”=缓慢且错误。)
  • 创建一个bitmapdata对象,其中包含记号(小垂直线)和基线(小水平线)的形状,每帧复制一个像素,将下一个位图(线段)放置在图形对象上(现在也是位图)。ScrollRect可向左滚动。很简单,与#1非常相似,只是使用bitmapData和copyPixel而不是显示对象

    • 这是一个坏消息,因为2048像素之后,无法再将更多数据绘制到位图
    • 缩放应用程序会导致所有位图看起来粗糙、参差不齐,并引入间隙(尽管将每个位图标记为“平滑”),这可能是因为构成图形的线段数量过多,这些线段都是完全不同的,并且绘制在其他像素边界附近
    • GPU无法加速Scrollrect(应用程序需要在移动设备上运行)
    • 维护并发位图、将一个位图复制并粘贴到另一个位图上以刷新图形(“blitting”?)非常繁琐,但与矢量技术不同,它在亚像素级也非常不准确。此外,重新计算每帧或每帧的所有峰值所需的计算
      public class Graph extends Sprite
      {
          include "constants.as";
          const pixelFactor:Number = (1 / GRAPH_TIMESCALE) * 1050; //60,000ms
          const amountToMove:Number = POLLING_RATE * pixelFactor, inverseTS:Number = 1.0/GRAPH_TIMESCALE;
          var graphHolder:GraphHolder; // A simple (large) sprite with many Graph instances
          var baseLine:Shape = new Shape(), stretched:Boolean = false;
          var apArray:Array = [], apRecycle:Vector.<Shape> = new <Shape>[];
          var apLength:int = 0, firstPeak:Shape;
          //var numberIndicator:TextField = new TextField();
      
          public function Graph(graphHolder:GraphHolder) 
          {
              //Set variables
              this.graphHolder = graphHolder; 
              mouseEnabled = false; mouseChildren = false;
      
              addChild(baseLine);
              with (baseLine)
              {
                  x = 55; y = 10; // the base-line. Starts 55 pixels out so labels can be added
                  graphics.lineStyle(2,0x000000); // Thickness 2, color black
                  graphics.lineTo(1050,0);
                  scaleX = 0.0005; // base-line starts as a little dot, expands with time
              }
          }
      
          // When not scrolling, draws idle baseline. When scrolling, drags peaks backwards.
          function drawIdle(timeElapsed:int):void
          {
              if (timeElapsed <= GRAPH_TIMESCALE) baseLine.scaleX = inverseTS * timeElapsed;
              else 
              {
                  //if (graphNo < 1) graphHolder.scrollAxis(pixelFactor);
                  if (!stretched) { baseLine.scaleX = 1.001; stretched = true; }
      
                  // scroll all peaks
                  if (apLength)
                  {
                      for (var i:int = 0; i < apLength; i++)
                      {
                          apArray[i].x -= amountToMove;
                      }
                      firstPeak = apArray[0];
                      if (firstPeak.x < 55) 
                      { 
                          firstPeak.visible = false;
                          apRecycle[apRecycle.length] = firstPeak; // peaks are recycled instead of removed
                          apArray.shift(); // apArray is a linked-list Array; less shift cost
      
                          --apLength;
                      }
                  }
              }
              //lbd.copyPixels(graphHolder.baseCache,lbr,new Point(timeElapsed * pixelFactor,0), null, null, true);
              //line.graphics.lineTo(timeElapsed * pixelFactor,10);
          }
          function drawAP(timeElapsed:int):void
          {
              // Check for a peak in the recycle array
              if (apRecycle.length)
              {
                  firstPeak = apRecycle.pop();
                  firstPeak.x = ( (timeElapsed > GRAPH_TIMESCALE) ? 1050 : (timeElapsed * pixelFactor) ) + 54; //55-1
                  firstPeak.visible = true;
                  apArray[apArray.length] = firstPeak;
              }
              else
              {
                  // Line drawn from baseline up 7 pixels.
                  var peakShape:Shape = new Shape(); 
                  //peakShape.cacheAsBitmap = true;
                  addChild(peakShape);
                  with (peakShape)
                  {
                      //cacheAsBitmap = true;
                      graphics.lineStyle(2, 0x000000);
                      graphics.moveTo(1, 10);
                      graphics.lineTo(1, 3);
                      x = ( (timeElapsed > GRAPH_TIMESCALE) ? 1050 : (timeElapsed * pixelFactor) ) + 54; //55-1
                      apArray[apArray.length] = peakShape;
                  }
              }
              ++apLength;
          }
      
          /* Reset baseline as tiny dot, remove peaks, reset peak array. 
             All peaks in recycle remain to draw from during next cycle. */
          function resetGraph():void
          {
              baseLine.scaleX = 0.0005; stretched = false;
              for each (var peak:Shape in apArray) removeChild(peak);
              apArray.length = 0; apLength = 0;
          }
      }
      
      public class Graph extends Sprite
      
          private var container:Sprite;
      
          public function Graph():void {
              //create your baseline
      
              //create the container
              container = new Sprite();
              addChild(container);
      
              this.addEventListener(Event.ENTER_FRAME, drawIdle);
          }
      
          private function drawIdle(e:Event){
              //move your baseline?
      
              //scroll container
              container.x += scrollAmount;
      
      
              //iterate through all the ticks
              var i:int = container.numChildren;
              var tick:Shape;
      
              //iterate through the container children backwards (has to be backwards since your potentially removing items)
              while(i--){
                  tick = container.getChildAt(i);
                  //check if the tick is off screen to the left
                  if(container.x + tick.x < 0){
                      //if so, remove it so it can be garbage collected
                      container.removeChild(tick);
                  }
          }
      
          public function drawAp(timeElapsed):void {
              //create your tick
              var tick:Shape = new Shape(); 
      
              //draw your tick
              tick.graphics.beginFill(0);
              tick.graphics.drawRect(0,0,tickWidth,tickHeight);
              tick.graphics.endFill();
      
              //position your tick
              tick.x = whatever;
              tick.y = whatever;
      
              //add it to your tick container
              container.addChild(tick);
          }
      
      }