Flash AS3(形状类)CPU使用和优化

时间:2014-03-01 11:43:57

标签: actionscript-3 flash line shape

我是Flash ActionScript 3.0和对象编程的新手。我正在尝试创建一个基于转向绘制形状的简单游戏。

public class Player extends Shape
{
    public var X,Y,v,vX,vY,size,a,r:Number;
    public var k,counter,leftKey,rightKey,_color:uint;  
    public var line:Shape = new Shape();
    public var dot:Shape = new Shape(); 

  /*...*/
  /*constructor, giving values to variables here, not important*/       
  /*...*/

   public function Move():void
    {

        a=a+0.05*k; 
       //player controls k parameter k=0 by default 
       //k=1 when right key pressed
       //k=-1 when left key pressed

        vX=v*Math.cos(a);
        vY=v*Math.sin(a);

        X=X+vX;
        Y=Y+vY;

        dot.x=X+vX*size/(2*v);
        dot.y=Y+vY*size/(2*v);

        if (counter==0)
        {
            line.graphics.lineTo(X,Y);
            if (Math.random()<0.008) counter=12;
        } else 
        {
            line.graphics.moveTo(X, Y);
            counter--;
        }
    }

}

函数Move在我的Player类中,从我的Main Class中的无限TimerEvent函数调用

public function mainLoop(TimerEvent:Event):void
{           
    for (var i:uint=0; i<players; i++) player[i].Move();
}

一开始似乎运行良好但经过一段时间后CPU使用量大幅增加,游戏变得无法播放。我相信它是由我的形状(线)变得越来越复杂造成的。

有没有合理的方法来优化它?我能以某种方式以较少的消费方式划清界限吗?我试图将其转换为位图,但这看起来很难看,并没有真正的帮助。

谢谢和欢呼!

2 个答案:

答案 0 :(得分:0)

你是正确的假设你的形状代码减速 - 矢量数据在flash中每一帧重绘一次,所以它越复杂,绘制的时间就越长。一些解决方案,取决于您愿意做的事情:

  • 你的忠诚度很高 - 你每帧都会调用你的Move功能;你可能不需要那么高,因为自上一帧以来的移动差异可能小于一个像素。改为每隔X帧取样一次(其中X是您愿意接受的保真度)。这可以通过输入框架中的简单计数器来完成
  • 如果您不需要保留绘图的整个历史记录,请将所有点放入数组/向量中,根据需要剔除长度。然后每一帧,做一个line.graphics.clear()并只绘制数组中的点
  • 如果您 需要保留整个历史记录,请在您的线下保留BitmapData(例如,舞台的大小)。每隔一段时间,将line绘制到BitmapData并在图形上调用clear()以获得向量数据的正确性。您不应该注意到质量的任何损失(在您绘图时将smoothing设置为true

在任何情况下我都会做第一点,然后在第二点和第三点之间进行选择,具体取决于你的用例

答案 1 :(得分:0)

扩展我的评论,尝试这样的事情:

public class Player extends Shape
{
    public var X,Y,v,vX,vY,size,a,r:Number;
    public var k,counter,leftKey,rightKey,_color:uint;  
    public var line:Shape = new Shape();
    public var dot:Shape = new Shape(); 

  /*...*/
  /*constructor, giving values to variables here, not important*/       
  /*...*/
    public function Player(){
        //draw shapes
        graphics.lineStyle(1);
        graphics.drawCircle(0,0,r);
        graphics.lineTo(size,0);//can't test this now, but make sure the line is in the same direction as rotation 0 (guessing it's to the right)
        //your other constructor code here
    }
   public function Move():void
    {

        a=a+0.05*k; 
       //player controls k parameter k=0 by default 
       //k=1 when right key pressed
       //k=-1 when left key pressed

        vX=v*Math.cos(a);
        vY=v*Math.sin(a);

        X=X+vX;
        Y=Y+vY;

        x=X+vX*size/(2*v);
        y=Y+vY*size/(2*v);
        rotation = a * 57.2957795;//quick'n'dirty radians to degrees
    }

如果你想绘制小径,你可以试试这样的东西:

var canvas:Bitmap = new BitmapData(state.stageWidth,stage.stageHeight,true,0xFF000000);
var ct:ColorTransform = new ColorTransform(1,1,1,.1);   
public function mainLoop(TimerEvent:Event):void
{           
    for (var i:uint=0; i<players; i++) {
        player[i].Move();
        canvas.draw(player[i],player[i].transform.concatenatedMatrix,ct);
    }
}

希望这是有道理的。

<强>更新 这是一个独立的代码片段,用于说明上述想法(具有未经测试的语法):

package {
    import flash.display.Bitmap;
    import flash.geom.ColorTransform;
    import flash.display.BitmapData;
    import flash.text.TextField;
    import flash.ui.Keyboard;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.utils.Dictionary;
    import flash.display.Sprite;
    public class PlayerMoveTest extends Sprite {
        private var keys:Dictionary = new Dictionary();
        private var players:Vector.<Player> = new Vector.<Player>();
        private var trails:BitmapData;
        private var fade:ColorTransform = new ColorTransform(1,1,1,.1);
        public function PlayerMoveTest() {
            addEventListener(Event.ADDED_TO_STAGE,init);
        }
        private function init(e:Event):void{
            trails = new BitmapData(stage.stageWidth,stage.stageHeight,true,0x00FFFFFF);
            addChild(new Bitmap(trails));
            for(var i:int = 0 ; i < 2; i++){
                var p:Player = addChild(new Player(10+i*10)) as Player;
                p.x = stage.stageWidth * .5;
                p.y = stage.stageHeight * .5;
                players.push(p);
            }
            stage.addEventListener(KeyboardEvent.KEY_DOWN,onKeyDown);
            stage.addEventListener(KeyboardEvent.KEY_UP,onKeyUp);
            stage.addEventListener(Event.ENTER_FRAME,update);
        }
        private function onKeyDown(e:KeyboardEvent):void{
            keys[e.keyCode] = true;
        }
        private function onKeyUp(e:KeyboardEvent):void{
            keys[e.keyCode] = null;
        }
        private function update(e:Event):void{
            if(keys[Keyboard.LEFT] != undefined)  {players[0].a -= .05;players[1].a += .05;}
            if(keys[Keyboard.RIGHT] != undefined) {players[0].a += .05;players[1].a -= .05;}
            if(keys[Keyboard.UP] != undefined)    {players[0].s += .15;players[1].s -= .15;}
            if(keys[Keyboard.DOWN] != undefined)  {players[0].s -= .15;players[0].s += .15;}
            for(var i:int = 0 ; i < players.length; i++) {
                players[i].move();
                trails.draw(players[i],players[i].transform.concatenatedMatrix,fade);
            }
        }
    }

}
import flash.display.*;
class Player extends Shape{
    public var vx:Number,vy:Number,a:Number,size:Number,r:Number,s:Number;
    public function Player(size:Number){
        init(size);
    }
    private function init(size:Number):void{
       vx = vy = a = s = 0;
       this.size = size;
       this.r = size * .25;
       graphics.lineStyle(1);
       graphics.drawCircle(0,0,r);
       graphics.lineTo(size,0);     
    }
    public function move():void{
        rotation = a * 57.2957795;
        vx = Math.cos(a) * s;
        vy = Math.sin(a) * s;
        x += vx;
        y += vy;
        if(x < 0) x = 0;
        if(y < 0) y = 0;
        if(x > stage.stageWidth) x = stage.stageWidth-width;
        if(y > stage.stageHeight) y = stage.stageHeight-height;
    }
}

您可以测试此代码here,这是预览:

preview

使用箭头键驱动(向上箭头加速,左/右转向)。 第一个玩家是较小的玩家,拥有正确的控制,另一个玩家只是镜像以前的控件)