我正在使用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;
}
}
答案 0 :(得分: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对象中设置动画!
如果您计划调整大小,我会对图块集进行一些尺寸变化并进行缩放。 如果您将使用此方法请注意,使用allowSmooting将有助于渲染bitmapData(如果它已调整大小或/和旋转),但会降低渲染速度,因为smooting计为过滤器。
答案 1 :(得分:2)
感谢@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;
}
}