I am loading my sprite images using SVG images so that they smoothly scale to match device resolutions. Currently I am naively rendering the SVG data for each sprite, but I would like to reduce memory overhead and improve performance by sharing the rendered image across multiple sprite instances.
How can this be achieved using OpenFL / Haxe?
For example:
The tile implementation below is wasteful since SVG image is rendered for each tile upon creation.
// 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");
Tile Implementation
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;
}
}
With all regard to a good question and your approach, I personally find it too complex and unnecessary sophisticated.
If you never resize the tile, why not make a bitmapData that you could reuse unlimited number of times with great rendering performance? Just render the SVG once before and make a 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
It's later easy to reuse it with the graphics object (bitmapFill) or by making a Bitmap object. You can even animate in Bitmap object by changing the bitmapData property!
If you do plan to resize it, I would make a few size variations of the tile set and scale it. If you'll use this method please note that using allowSmoothing will help rendering the bitmapData if it's resized or/and rotated, but will slow down the rendering as smoothing counts as a filter.