写得少,保持良好的表现,有可能吗?

时间:2015-10-13 01:27:59

标签: performance actionscript-3 loops design-patterns

过去几天,我一直在考虑一种方法,以避免需要编写大量代码,并且仍然保持我正在开发的Air桌面游戏的良好性能,作为业余爱好。

游戏是一种垂直射击游戏,由几个移动和检查碰撞的实体组成。有很多不同类型的单位。每一帧我有类似的东西:

entity.execute();

更简单的方法是让所有不同的实体继承Entity类,并手动自定义它们。这是缓慢而繁琐的,并且难以维护。但它快速,性能明智。

另一种方法是只有一个Entity类,只使用某种组合来简单地添加“行为”。因此,例如,我有一个大师类,其中包含类型的移动,攻击等,并且不同的实体使用它们。

这种方法的问题是,调用函数很慢,根据我的测试,它比只需要代码(在execute()内部)慢约3倍。

我处于两难境地,我无法找到重用代码块来装饰通用实体实例的方法,并保持良好的性能。好像我必须使用其中一个。

我尝试使用[内联],但我读过它不是一个稳定的功能,我没有看到任何明显的性能提升,但我没有测试它。

感谢任何见解。

3 个答案:

答案 0 :(得分:2)

通过继承进行抽象是一种很好的面向对象模式,我认为维护它并不缓慢或繁琐。关注点的分离会增加继承基本Entity类的类的清晰度;同样,减少复制的代码。接口将进一步抽象具体类型。

ActionScript不支持您可能在C#等语言中找到的强大的面向对象语言功能 - 没有抽象基类,没有部分类,有限的模板/泛型,有限的多态性。组合和装饰器模式可能会强制使用动态类,这也会因类型检查而减慢运行时间。

也许更大的问题是Entity类中的业务逻辑太多。我认为一些世界容器或控制器将负责碰撞检测。

你可以考虑的是像Box 2D这样的物理引擎。

Box2D的端口采用CrossBridge(以前称为Alchemy,FlasCC)构建,它是AVM2的C ++编译器,能够通过精益优化的字节码运行Flash,速度高达10倍,该字节码具有Flash的高性能内存访问操作码(称为域内存。)

这就是Angry BotsNeverball之类的游戏。

如果使用AS3物理引擎听起来很有趣,请查看Jesse Sternberg的Box2d Flash Alchemy Port + World Construction Kit

wck

答案 1 :(得分:1)

在游戏开发中有一些加速闪存的常用方法。其中之一是避免使用显示对象,而选择简单的位图。在这种情况下,您将舞台作为位图,并将所有游戏状态保存在轻量级对象中,然后定期将游戏状态快照绘制到该阶段位图数据(带copyPixels)中(在输入框架上,或者在计时器上)

示意图:说你有一个单位游戏

class PseudoSprite {
    public var x:uint;
    public var y:uint;
    public var currentAnimFrame:uint;
    protected var snapshotCreator:AbstractSnapshotCreator;

    public function makeSnapshot():BitmapData {
        return snapshotCreator.createSnapshot(currentAnimFrame);
    }
    ....
}

class Unit extends PseudoSprite {
    public var directionAngle:Number = 0;
    public var speed:uint = 0;

    function Unit() {
         snapshotCreator = UnitSnapshotCreator.instance;
    }

    public function doStep():void {
        x = //count x by speed and direction
        y = //count y by speed and direction
        animationFrame++;
    }
}

class Game {
    public var stage:Bitmap; 
    private var objects:Vector.<PseudoSprite> = new <PseudoSprite>[
        new Unit(), new Unit()];

    public function step() {
        for each (var unit:PseudoSprite in objects) {
            unit.doStep();
            //draw unit.snapshot() to the stage bitmap data
        }
    }
}

所以,您可以看到:您可以使用普通OOP构建整个单元(或所有游戏对象)层次结构,并获得一些合适的性能。

答案 2 :(得分:-2)

经过一些测试后,我发现我可以做以下事情:

public var foo:Function;

然后当我创建实体时,我可以:

entity.foo = myCustomFoo;

然后在主循环中我可以:

entity.foo();

这与在Entity实例中调用本机成员函数一样高效。警告,不要创建一个getter来访问你的函数,它变得慢很多。