我正在使用 SVG 图像加载精灵图像,以便它们可以平滑缩放以匹配设备分辨率。目前,我天真地为每个精灵渲染 SVG 数据,但我想通过在多个精灵实例之间共享渲染图像来减少内存开销并提高性能。
如何使用 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;
}
}
对于一个好问题和你的方法,我个人认为它太复杂且不必要的复杂。
如果您从不调整图块的大小,为什么不制作一个可以无限次重复使用且具有出色渲染性能的位图数据呢?只需之前渲染一次 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)或通过创建 Bitmap 对象来重用它。您甚至可以通过更改 bitmapData 属性在 Bitmap 对象中设置动画!
如果您确实计划调整它的大小,我会对图块集进行一些尺寸变化并缩放它。 如果您要使用此方法,请注意,如果调整大小或/和旋转位图数据,使用allowSmoothing将有助于渲染位图数据,但会减慢渲染速度,因为平滑计数作为过滤器。
感谢@Creative Magic,这个答案成为可能。
我已将
Tile
从 Shape
更改为 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;
}
}