【问题标题】:Creating multiple instances of sprites in OpenFL?在 OpenFL 中创建多个精灵实例?
【发布时间】:2013-08-13 23:05:27
【问题描述】:

我正在使用 SVG 图像加载我的精灵图像,以便它们可以平滑地缩放以匹配设备分辨率。目前我很天真地为每个精灵渲染 SVG 数据,但我想通过在多个精灵实例之间共享渲染图像来减少内存开销并提高性能。

如何使用 OpenFL / Haxe 实现这一点?

例如:

下面的 tile 实现是浪费的,因为 SVG 图像是在创建时为每个 tile 渲染的。

// Each of the following tile sprites contain copies of the same image.
var xyz1:Tile = new Tile("xyz");
var xyz2:Tile = new Tile("xyz");
var xyz3:Tile = new Tile("xyz");

平铺实现

package;

import flash.display.Shape;
import format.SVG;
import openfl.Assets;

class Tile extends Shape {

    // Static cache of SVG data to avoid loading asset each time.
    private static var tileImageMap:Map<String, SVG> = new Map<String, SVG>();

    private static function lookupSVG(tile:String):SVG {
        var svg:SVG = tileImageMap.get(tile);
        if (svg == null) {
            svg = new SVG(Assets.getText("img/" + tile + ".svg"));
            tileImageMap.set(tile, svg);
        }
        return svg;
    }

    public var tile(get,set):String;

    private var _tile:String;

    private function get_tile():String {
        return _tile;
    }

    private function set_tile(value:String):String {
        if (value != _tile) {
            _tile = value;

            // Render tile SVG to tile sprite.
            // How can this be cached and reused by multiple tile instances?
            graphics.clear();
            lookupSVG(value).render(graphics, 0, 0, 56, 56);
        }
        return _tile;
    }

    public function new(tile:String) {
        super();

        cacheAsBitmap = true;

        this.tile = tile;
    }

}

【问题讨论】:

  • 使用 SVG 的酷方法...也有兴趣听到答案

标签: flash sprite haxe openfl


【解决方案1】:

考虑到一个好问题和你的方法,我个人觉得它太复杂了,没有必要复杂。

如果您从不调整图块的大小,为什么不制作一个可以无限次重复使用并具有出色渲染性能的 bitmapData?只需在之前渲染一次 SVG 并制作一个 bitmapData:

var bd:BitmapData = new BitmapData( tileWidth, tileHeight );
bd.draw(tile);
// add the bd to some array of your tile set or assign it to a tile skin variable

以后很容易将其与图形对象 (bitmapFill) 或通过制作位图对象重用。您甚至可以通过更改 bitmapData 属性在 Bitmap 对象中设置动画!

如果您确实打算调整它的大小,我会对图块集进行一些大小变化并对其进行缩放。 如果您将使用此方法,请注意,如果调整大小或/和旋转 bitmapData,使用 allowSmooting 将有助于渲染它,但会减慢渲染速度,因为 smooting 算作过滤器。

【讨论】:

  • bd.draw(tile); 是否将位图数据复制到瓦片精灵的图像缓冲区中?有没有办法让一个精灵的所有实例共享一个单一的图像缓冲区?到目前为止,似乎每个精灵最终都有自己的内部图像缓冲区,这似乎对我的需求来说是不必要的。
  • 不确定是否可以在屏幕上添加相同的对象两次,同时保留两个对象。您可以通过渲染一次并传递渲染数据来逃避渲染过程。我不知道该对象是否会生成它自己的传递渲染的副本,或者只是保留一个指向它的指针。
  • Haxe (OpenFL) 中的以下代码运行良好: var s:Sprite = new Sprite(); s.graphics.beginFill(0xFF00F0); s.graphics.drawCircle(15, 15, 15); s.graphics.endFill(); var bd:BitmapData = new BitmapData(30, 30, true, 0x00000000); bd.draw(s); var s1:Sprite = new Sprite(); s1.graphics.beginBitmapFill(bd); s1.graphics.drawRect(0, 0, 30, 30); s1.graphics.endFill(); addChild(s1); var s2:Sprite = new Sprite(); s2.graphics.beginBitmapFill(bd); s2.graphics.drawRect(0, 0, 30, 30); s2.graphics.endFill(); s2.x = 200; addChild(s2);
  • 有趣,看起来解决方案是像您演示的那样创建位图数据,然后为每个引用相同 BitmapData 实例的图块创建一个 Bitmap 实例,从而节省内存.
  • 很高兴我能帮上忙。我确实查看了 SVG 的 render() 方法,但我发现它没有返回任何值,因此我无法像使用 BitmapData 一样保存此过程的产品以供使用。
【解决方案2】:

感谢@Creative Magic,让这个答案成为可能。

我已将 TileShape 更改为 Bitmap,它引用了共享的 BitmapData 实例。这是有益的,因为它避免了多次复制相同的图像数据(每个精灵实例一次)。

当第一次实例化特定类型的图块时,它的位图数据是从 SVG 数据生成的,然后被缓存。然后,只需将其bitmapData 引用调整为另一个图块的图稿即可更改图块图像:

package ;

import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import format.SVG;
import openfl.Assets;

// Tile is now a Bitmap
class Tile extends Bitmap {

    // Static cache of bitmap data to avoid loading asset each time.
    private static var tileImageMap:Map<String, BitmapData> = new Map<String, BitmapData>();
    private static var tempSprite:Sprite = new Sprite();

    // Lookup cached version of tile bitmap.
    private static function lookupBitmapData(tile:String):BitmapData {
        var data:BitmapData = tileImageMap.get(tile);
        if (data == null) {
            // Render tile from SVG into temporary sprite.
            var svg:SVG = new SVG(Assets.getText("img/" + tile + ".svg"));
            tempSprite.graphics.clear();
            svg.render(tempSprite.graphics, 0, 0, 56, 56);

            // Extract bitmap data from temporary sprite and cache.
            data = new BitmapData(56, 56, true, 0x00FFFFFF);
            data.draw(tempSprite);
            tileImageMap.set(tile, data);
        }
        return data;
    }

    public var tile(get,set):String;

    private var _tile:String;

    private function get_tile():String {
        return _tile;
    }

    private function set_tile(value:String):String {
        if (value != _tile) {
            _tile = value;
            // Merely adjust reference of bitmap data.
            bitmapData = lookupBitmapData(value);
        }
        return _tile;
    }

    public function new(tile:String) {
        super();

        this.tile = tile;
    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-20
    • 2012-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多