4

我正在使用 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;
    }

}
4

2 回答 2

4

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

如果您从不调整图块的大小,为什么不制作一个可以无限次重复使用且具有出色渲染性能的 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) 或通过制作 Bitmap 对象轻松重用它。您甚至可以通过更改 bitmapData 属性在 Bitmap 对象中设置动画!

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

于 2013-08-14T02:05:19.213 回答
2

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

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

当第一次实例化特定类型的图块时,它的位图数据是从 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;
    }

}
于 2013-08-14T02:49:54.943 回答