前言
在开发游戏过程中,经常遇到图片达到4096的尺寸,如果去修改这个纹理集合分配成2048的话,会浪费不少的人力。所以,扩展了一个SuperTextureAtlas来支持大于4096的纹理集图片。
实现原理
其实原理很简单,也就是解析位图的大小,将超过尺寸的大图,切割成一个个2048的精灵表TextureAtlas。而SuperTextureAtlas正是重写了其获取方法,管理读取多个精灵表,所以能照常使用。此外,为了实现这个功能,特意修改了AssetsManager类的几个小地方。
SuperTextureAtlas.as源码
package zygame.utils
{
import flash.display.BitmapData;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.system.System;
import starling.textures.Texture;
import starling.textures.TextureAtlas;
public class SuperTextureAtlas extends TextureAtlas
{
/**
* Whether to start support, the default is false
*/
public static var support:Boolean = false;
private var _maxPack:Vector.<Object>;
private var _textureAtlas:Vector.<TextureAtlas>;
private var _separationCount:int = 0;
private var _separationIndex:int = 0;
private var _bitmapData:BitmapData;
private var _xml:XMLList;
private var _length:int = 0;
private var _count:int = 0;
public function SuperTextureAtlas(bitmapData:BitmapData,xml:XML):void
{
_bitmapData = bitmapData;
_xml = xml.children();
_length = _xml.length();
_textureAtlas = new Vector.<TextureAtlas>();
_maxPack = new Vector.<Object>();
_separationCount = 1;
while(_maxPack.length < _separationCount){
_maxPack.push(separation());
}
super(Texture.fromBitmapData(_maxPack[0].bitmapData),_maxPack[0].xml);
for(var c:int = 0;c<_maxPack.length;c++)
{
if(c != 0)
{
var textureAtlas:TextureAtlas = new TextureAtlas(Texture.fromBitmapData(_maxPack[c].bitmapData),_maxPack[c].xml);
_textureAtlas.push(textureAtlas);
}
}
_bitmapData = null;
}
/**
* Isolations, separate the texture set one by one, back together
* @return
*
*/
private function separation():Object
{
var bitmapData:BitmapData = new BitmapData(2048,2048,true,0x0);
var pack:MaxRectsBinPack = new MaxRectsBinPack(2048,2048,false);
for(var i:int = _separationIndex;i<_length;i++)
{
var rect:Rectangle = pack.insert(int(_xml[i].@width),int(_xml[i].@height),2);
_count ++;
if(rect.width == 0 || rect.height == 0)
{
_separationCount ++;
break;
}
}
var newXML:XML = <xml></xml>;
for(var u:int = 0;u<pack.usedRectangles.length;u++)
{
bitmapData.copyPixels(_bitmapData,new Rectangle(int(_xml[_separationIndex+u].@x),int(_xml[_separationIndex+u].@y),int(_xml[_separationIndex+u].@width),int(_xml[_separationIndex+u].@height)),new Point(pack.usedRectangles[u].x,pack.usedRectangles[u].y));
var nodeXML:XML = _xml[_separationIndex+u].copy();
nodeXML.@x = pack.usedRectangles[u].x;
nodeXML.@y = pack.usedRectangles[u].y;
newXML.appendChild(nodeXML);
}
_separationIndex = i;
return {
bitmapData:bitmapData,
xml:newXML
};
}
override public function getTexture(name:String):Texture
{
var texture:Texture = super.getTexture(name);
if(texture)
return texture;
for(var i:int = 0;i<_textureAtlas.length;i++)
{
texture = _textureAtlas[i].getTexture(name);
if(texture)
return texture;
}
return null;
}
override public function getFrame(name:String):Rectangle
{
var rect:Rectangle = super.getFrame(name);
if(rect)
return rect;
for(var i:int = 0;i<_textureAtlas.length;i++)
{
rect = _textureAtlas[i].getFrame(name);
if(rect)
return rect;
}
return null;
}
override public function getRegion(name:String):Rectangle
{
var rect:Rectangle = super.getRegion(name);
if(rect)
return rect;
for(var i:int = 0;i<_textureAtlas.length;i++)
{
rect = _textureAtlas[i].getRegion(name);
if(rect)
return rect;
}
return null;
}
override public function getRotation(name:String):Boolean
{
var bool:Boolean = super.getRotation(name);
if(bool)
return true;
for(var i:int = 0;i<_textureAtlas.length;i++)
{
bool = _textureAtlas[i].getRegion(name);
if(bool)
return true;
}
return false;
}
override public function getNames(prefix:String="", out:Vector.<String>=null):Vector.<String>
{
var vec:Vector.<String> = super.getNames(prefix,out);
if(vec)
return vec;
for(var i:int = 0;i<_textureAtlas.length;i++)
{
vec = _textureAtlas[i].getNames(prefix,out);
if(vec)
return vec;
}
return null;
}
override public function getTextures(prefix:String="", out:Vector.<Texture>=null):Vector.<Texture>
{
var vec:Vector.<Texture> = super.getTextures(prefix,out);
if(vec)
return vec;
for(var i:int = 0;i<_textureAtlas.length;i++)
{
vec = _textureAtlas[i].getTextures(prefix,out);
if(vec)
return vec;
}
return null;
}
override public function dispose():void
{
for(var c:int = 0;c<_textureAtlas.length;c++)
{
_textureAtlas[c].dispose();
}
for(var i:int = 0;i<_maxPack.length;i++)
{
(_maxPack[i].bitmapData as BitmapData).dispose();
System.disposeXML((_maxPack[i].xml as XML));
}
_maxPack.splice(0,_maxPack.length);
_maxPack = null;
}
}
}
以上是实现原理,所有涉及源码晚些我放在CSND下载区。