Flash 在OpenFL中创建多个精灵实例?

Flash 在OpenFL中创建多个精灵实例?,flash,sprite,haxe,openfl,Flash,Sprite,Haxe,Openfl,我正在使用SVG图像加载我的精灵图像,以便它们平滑地缩放以匹配设备分辨率。目前,我只是简单地为每个sprite渲染SVG数据,但我希望通过跨多个sprite实例共享渲染图像来减少内存开销并提高性能 如何使用OpenFL/Haxe实现这一点 例如: 下面的磁贴实现是浪费的,因为SVG图像是在创建时为每个磁贴渲染的 // Each of the following tile sprites contain copies of the same image. var xyz1:Tile = new T

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

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

例如:

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

// 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;
    }

}
包;
导入flash.display.Shape;
导入format.SVG;
导入openfl.资产;
类平铺扩展形状{
//SVG数据的静态缓存,避免每次加载资产。
私有静态变量tileImageMap:Map=newmap();
私有静态函数lookupSVG(tile:String):SVG{
var svg:svg=tileImageMap.get(tile);
if(svg==null){
svg=newsvg(Assets.getText(“img/”+tile+”.svg”);
tileImageMap.set(tile,svg);
}
返回svg;
}
公共变量tile(get,set):字符串;
私有变量:字符串;
私有函数get_tile():字符串{
返回瓦片;
}
私有函数集_tile(值:String):String{
如果(值!=\u平铺){
_瓷砖=价值;
//将平铺SVG渲染为平铺精灵。
//多个磁贴实例如何缓存和重用这些内容?
graphics.clear();
lookupSVG(值).render(图形,0,0,56,56);
}
返回瓦片;
}
公共函数新建(平铺:字符串){
超级();
cacheAsBitmap=true;
this.tile=tile;
}
}

关于一个好问题和你的方法,我个人觉得它太复杂,不必要复杂

如果您从未调整磁贴大小,为什么不制作一个bitmapData,可以无限次地重复使用,并具有良好的渲染性能?只需先渲染SVG一次,然后生成位图数据:

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属性在位图对象中设置动画

如果你真的打算调整它的大小,我会做一些大小变化的瓷砖集和规模。
如果要使用此方法,请注意,如果位图数据被调整大小或/或旋转,则使用AllowMooting将有助于渲染位图数据,但会减慢渲染速度,因为smooting计数作为一个过滤器。

这一答案是由于以下原因而实现的

我已将
平铺
形状
更改为
位图
,它引用了共享的
位图数据
实例。这是有益的,因为它避免了多次复制相同的图像数据(每个sprite实例一次)

当特定类型的磁贴第一次被实例化时,它的位图数据是从SVG数据生成的,然后被缓存。然后,可以仅通过调整其对另一个磁贴的插图的
位图数据
引用来更改磁贴图像:

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;
    }

}
包;
导入flash.display.Bitmap;
导入flash.display.BitmapData;
导入flash.display.Sprite;
导入format.SVG;
导入openfl.资产;
//平铺现在是位图
类扩展位图{
//位图数据的静态缓存,避免每次加载资源。
私有静态变量tileImageMap:Map=newmap();
私有静态变量tempsrite:Sprite=new Sprite();
//查找磁贴位图的缓存版本。
私有静态函数lookupBitmapData(平铺:字符串):BitmapData{
变量数据:BitmapData=tileImageMap.get(平铺);
如果(数据==null){
//将SVG中的平铺渲染为临时精灵。
var svg:svg=newsvg(Assets.getText(“img/”+tile+.svg”);
tempsrite.graphics.clear();
render(tempsrite.graphics,0,0,56,56);
//从临时精灵和缓存中提取位图数据。
数据=新的位图数据(56,56,true,0x00FFFFFF);
data.draw(tempsrite);
tileImageMap.set(平铺,数据);
}
返回数据;
}
公共变量tile(get,set):字符串;
私有变量:字符串;
私有函数get_tile():字符串{
返回瓦片;
}
私有函数集_tile(值:String):String{
如果(值!=\u平铺){
_瓷砖=价值;
//只需调整位图数据的引用。
bitmapData=lookupBitmapData(值);
}
返回瓦片;
}
公共函数新建(平铺:字符串){
超级();
this.tile=tile;
}
}

使用SVG的酷方法。。。也有兴趣听到答案是bd.draw(tile)将位图数据复制到平铺精灵的图像缓冲区?有没有一种方法可以让精灵的所有实例共享一个单一的图像缓冲区?到目前为止,似乎每个精灵都有自己的内部图像缓冲区,这对于我的需要来说似乎是不必要的。不确定是否可以在屏幕上添加相同的对象两次,同时保留两个对象。可以通过渲染一次并传递渲染数据来逃避渲染过程。我不知道该对象是自己复制了传递的渲染还是只保留了指向它的指针;s、 图形填充(0xFF00F0);s、 绘图圈(15,15,15);s、 graphics.endFill();var bd:BitmapData=新的BitmapData(30,30,true,0x00000000);bd.draw(s);变量s1:Sprite=新Sprite();s1.graphics.beginBitmapFill(bd);s1.graphics.drawRect(0,0,30,30);s1.graphics.endFill();addChild(s1);变量s2:Sprite=新Sprite();s2.graphics.beginBitmapFill(bd);s2.graphics.drawRect(0,0,30,30);s2.graphics.endFill();s2.x=200;addChild(s2);有趣的是,解决方案似乎是像您演示的那样创建位图数据,然后为每个引用完全相同的图块创建一个实例