Прошло некоторое время с тех пор, как я начал делать игры для iOS и Android на Adobe AIR. Сегодня хочу поделиться способом создания игр под различные разрешения экранов — этот подход я успешно применяю в своих проектах.
Как известно, есть несколько способов подготовки игровой графики для разных разрешений экранов:
// Размер экрана нашего устройства, к примеру iPad2
var _stageWidth:Number = 768;
var _stageHeight:Number = 1024;
// Размер дизайн-макета
var defaultScreenWidth:Number = 600;
var defaultScreenHeight:Number = 800;
// Вычисляем скейлы и берём нужный, в зависимости от ориентации экрана. В моём случае портретная
_scaleX = _stageWidth / defaultScreenWidth;
_scaleY = _stageHeight / defaultScreenHeight;
_minScale = Math.min(_scaleX, _scaleY);
package com.Extension
{
import avmplus.getQualifiedClassName;
import com.Event.GameActiveEvent;
import com.Module.EventBus;
import com.greensock.TweenNano;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.display.StageQuality;
import flash.geom.Matrix;
import flash.geom.Rectangle;
import starling.display.Image;
import starling.display.Sprite;
import starling.textures.Texture;
import starling.textures.TextureAtlas;
public class TextureManager
{
// хранит в себе координаты на которые нужно сдвинуть спрайт, чтобы сохранить PivotPoint объекта из SWC
private static var textureAdditionalData:Object = {};
// контейнер с готовыми атласами
private static var textureAtlases:Vector.<TextureAtlas> = new <TextureAtlas>[];
// массив атласов которые нужно распарсить
// !!! (здесь нужно прописать имена атласов из SWC и скейл)
private static var toParse:Array = [
[guiAtlas, ScaleManager.minScale],
[gameAtlas, ScaleManager.minScale]
];
// возвращает старлинговый спрайт с нужной нам текстурой из атласа
public static function getSprite(textureName:String, smooth:String = "none"):starling.display.Sprite
{
if (textureAdditionalData.hasOwnProperty(textureName))
{
var addition:Object = textureAdditionalData[textureName];
var image:Image = new Image(findTexture(textureName));
image.x = -addition["x"];
image.y = -addition["y"];
image.textureSmoothing = smooth;
var result:starling.display.Sprite = new starling.display.Sprite();
result.addChild(image);
return result;
}
throw new Error("[!!!] Texture '" + textureName + "' not found.");
}
// возвращает текстуру из атласа
public static function getTexture(textureName:String):Texture
{
return findTexture(textureName);
}
// метот, который нужно вызвать при старте игры. Если атласов много, то это может занять некоторое время.
public static function createAtlases():void
{
if (!textureAtlases.length)
{
nextParseStep();
return;
}
throw new Error("[!!!] Texture atlases already.");
}
// поочерёдно создаём атласы
private static function nextParseStep():void
{
if (toParse.length)
{
var nextStep:Array = toParse.pop();
TweenNano.delayedCall(.15, TextureManager.createAtlas, nextStep);
}
else
{
// если всё, то отправляем событие о старте игры.
EventBus.dispatcher.dispatchEvent(new GameActiveEvent(GameActiveEvent.GAME_START, true));
}
}
// поиск нужной текстуры в атласах
private static function findTexture(textureName:String):Texture
{
var result:Texture;
for each (var atlas:TextureAtlas in textureAtlases)
{
result = atlas.getTexture(textureName);
if (result)
{
return result;
}
}
throw new Error("[!!!] Texture '" + textureName + "' not found.");
}
// класс который парсит спрайты из SWC и создаёт атлас
private static function createAtlas(swcPack:Class, scaleFactor:Number):void
{
var pack:flash.display.Sprite = (new swcPack()) as flash.display.Sprite;
var itemsHolder:Array = [];
var canvas:flash.display.Sprite = new flash.display.Sprite();
var children:uint = pack.numChildren;
for (var i:uint = 0; i < children; i++)
{
var selected:DisplayObject = pack.getChildAt(i);
var realX:Number = selected.x;
var realY:Number = selected.y;
selected.scaleX *= scaleFactor;
selected.scaleY *= scaleFactor;
var bounds:Rectangle = selected.getBounds(selected.parent);
bounds.x = Math.floor(bounds.x - 1);
bounds.y = Math.floor(bounds.y - 1);
bounds.height = Math.round(bounds.height + 2);
bounds.width = Math.round(bounds.width + 2);
var drawRect:Rectangle = new Rectangle(0, 0, bounds.width, bounds.height);
var bData:BitmapData = new BitmapData(bounds.width, bounds.height, true, 0);
var mat:Matrix = selected.transform.matrix;
mat.translate(-bounds.x, -bounds.y);
bData.drawWithQuality(selected, mat, null, null, drawRect, false, StageQuality.BEST);
var pivotX:int = Math.round(realX - bounds.x);
var pivotY:int = Math.round(realY - bounds.y);
textureAdditionalData[selected.name] = {x:pivotX, y:pivotY};
var item:flash.display.Sprite = new flash.display.Sprite();
item.name = selected.name;
item.addChild(new Bitmap(bData, "auto", false));
itemsHolder.push(item);
canvas.addChild(item);
}
layoutChildren();
var canvasData:BitmapData = new BitmapData(canvas.width, canvas.height, true, 0x000000);
canvasData.draw(canvas);
var xml:XML = new XML(<TextureAtlas></TextureAtlas>);
xml.@imagePath = (getQualifiedClassName(swcPack) + ".png");
var itemsLen:int = itemsHolder.length;
for (var k:uint = 0; k < itemsLen; k++)
{
var itm:flash.display.Sprite = itemsHolder[k];
var subText:XML = new XML(<SubTexture />);
subText.@name = itm.name;
subText.@x = itm.x;
subText.@y = itm.y;
subText.@width = itm.width;
subText.@height = itm.height;
xml.appendChild(subText);
}
var texture:Texture = Texture.fromBitmapData(canvasData);
var atlas:TextureAtlas = new TextureAtlas(texture, xml);
textureAtlases.push(atlas);
function layoutChildren():void
{
var xPos:Number = 0;
var yPos:Number = 0;
var maxY:Number = 0;
var maxW:uint = 512 * ScaleManager.atlasSize;
var len:int = itemsHolder.length;
var itm:flash.display.Sprite;
for (var i:uint = 0; i < len; i++)
{
itm = itemsHolder[i];
if ((xPos + itm.width) > maxW)
{
xPos = 0;
yPos += maxY;
maxY = 0;
}
if (itm.height + 1 > maxY)
{
maxY = itm.height + 1;
}
itm.x = xPos;
itm.y = yPos;
xPos += itm.width + 1;
}
}
nextParseStep();
}
public function TextureManager()
{
throw new Error("[!!!] Used private class.");
}
}
}
TextureManager.createAtlases();
var tileView:starling.display.Sprite = TextureManager.getSprite("rotateView");
this.addChild(tileView);
К сожалению, не доступен сервер mySQL