Creating multiple instances of sprites in OpenFL?

I upload sprite images using SVG images so that they smoothly scale according to device resolutions. Currently, I naively transmit SVG data for each sprite, but I would like to reduce the memory overhead and improve performance by sharing the displayed image across multiple sprite instances.

How can this be achieved with OpenFL / Haxe?

For instance:

Below is some bitmap implementation, since the SVG image is rendered for each fragment when created.

// 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; } } 
+4
source share
2 answers

As for the good question and your approach, I personally find it too complex and unnecessarily complex.

If you never resize the tiles, why not make bitmapData so that you can reuse an unlimited number of times with excellent rendering performance? Just visualize SVG once and make 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 

Later it will be easy to reuse it with a graphic object (bitmapFill) or by creating a Bitmap object. You can even animate a Bitmap object by changing the bitmapData property!

If you plan to resize it, I would make several options for the size of the tile set and scale it. If you use this method, note that using allowSmooting will help render bitmapData if it is resized or rotated, but it will slow down the rendering, since anti-aliasing is considered a filter.

+4
source

This answer has been made possible thanks to @Creative Magic .

I changed the Tile from Shape to a Bitmap , which refers to a shared instance of BitmapData . This is useful because it avoids duplication of the same image data several times (once for each instance of the sprite).

When a particular fragment type is created for the first time, its raster data is generated from SVG data, which is then cached. You can change the image of a tile by simply adjusting the BitmapData link to an image of another tile:

 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; } } 
+2
source

Source: https://habr.com/ru/post/1496927/


All Articles