2013-08-13 3 views
4

Я загружаю изображения спрайтов с помощью SVG-изображений, чтобы они плавно масштабировались в соответствии с разрешениями устройства. В настоящее время я наивно передаю SVG-данные для каждого спрайта, но я хотел бы уменьшить накладные расходы памяти и повысить производительность за счет совместного использования отображаемого изображения через несколько экземпляров спрайтов.Создание нескольких экземпляров спрайтов в OpenFL?

Как это можно достичь с помощью 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

Классного способ использования SVG ... Также интересно услышать ответ –

ответ

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. Вы можете даже оживить объект Bitmap, изменив свойство bitmapData!

Если вы планируете изменить его размер, я бы сделал несколько вариантов размеров плитки и масштабировал ее. Если вы будете использовать этот метод, обратите внимание, что использование allowSmooting поможет рендерить bitmapData, если оно будет изменено или/или повернуто, но будет замедлять рендеринг, поскольку сглаживание считается фильтром.

+0

ли 'bd.draw (плитка); 'скопировать данные растрового изображения в буфер изображения для спрайта с черепицей? Есть ли способ иметь сингулярный буфер изображений, который используется всеми экземплярами спрайта? До сих пор кажется, что каждый спрайт заканчивается собственным буфером внутреннего изображения, который кажется ненужным для моих нужд. –

+0

Не уверен, что вы можете добавить один и тот же объект на экран дважды, сохраняя оба объекта. Вы можете избежать процесса рендеринга, сделав его один раз и передав визуализированные данные. Я не знаю, создает ли объект его собственную копию переданного рендеринга или просто удерживает указатель на него. –

+0

следующий код в Haxe (OpenFL) работал отлично: var s: Sprite = new Sprite(); s.graphics.beginFill (0xFF00F0); s.graphics.drawCircle (15, 15, 15); s.graphics.endFill(); var bd: BitmapData = new BitmapData (30, 30, true, 0x00000000); bd.draw (s); var s1: Sprite = new Sprite(); s1.graphics.beginBitmapFill (bd); s1.graphics.drawRect (0, 0, 30, 30); s1.graphics.endFill(); addChild (s1); var s2: Sprite = new Sprite(); s2.graphics.beginBitmapFill (bd); s2.graphics.drawRect (0, 0, 30, 30); s2.graphics.endFill(); s2.x = 200; addChild (s2); –

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

} 
Смежные вопросы