用Adobe AIR支持多样设备多倍屏幕尺寸
要求
预备知识
中级理解程度用Adobe Air为移动设备开发应用和具有ActionScript 3编程经验将有助于你掌握这篇文章大部分内容。
用户级别
中级
要求的产品
Flash专业版(下载试用版)
Flash Builder(下载试用版)
Adobe AIR
无论你正开发一个运行在浏览器的flash player中的游戏在用Adobe AIR的手持设备操作系统上,还是为安卓界面写一个Adobe AIR应用,你都需要支持至少一些不同的屏幕显示。我过去可采纳的策略是游戏重构(用更多的背景,读取重建后的)被设计用800 x 600像素大小的flash player在浏览器里,于是,它使用了一些技巧去适应使它运行在较多的移动设备上。
In this article, I share some of those tricks (based on Adobe AIR 3.2) and sample code for:
在这篇文章,我分享一些技巧(基于Adobe AIR 3.2) 和一些示例代码
? 侦测屏幕尺寸
?朝向
?计算物理坐标
?缩放和居中界面
?对缩放位图转换向量
?侦测和限制苹果系统设备
?限制安卓设备
侦测屏幕尺寸
有四种方法检查坐标
stage.width和stage.height属性以像素验证舞台内容的高度和宽度。如果你的SWF文件是500 x 500像素包括一个100 x 100像素的图形,这个属性将返回100 x 100.
你能用stage.stageWidth 和 stage.stageHeight以像素为单位访问当前的Flash Player 或者 Adobe AIR的SWF文件的宽度和高度,他们将返回500 x 500。他们在前几帧可能设置得不正确。StageScaleMode.NO_SCALE设置下,当这些改变将触发重设尺寸事件。
stage.fullScreenWidth和stage.fullScreenHeight属性当全尺寸时返回屏幕的宽度和高度,包括工具条的空白。这些属性只会在宽度和高度在方向上被改变时改变。
最后,Capabilities.screenResolutionX和Capabilities.screenResolutionY属性返回屏幕最大的水平和垂直方式。换句话说,他们告诉你设备整个屏幕的尺寸。如果你的游戏运行在一个窗口(例如,一个仿照你计算机的窗口),这些属性将返回整个显示器的尺寸。
理想化看,你的应用应当检查stage.stageWidth 和 stage.stageHeight,这侦听一个重设尺寸事件(这包含了在方向上的变化)。依赖于设备,这些数值起初可能完全错误,接着过几秒后你将看到几个重设尺寸事件当应用成为全屏时,工具条消失了,而且方向自动纠正。这是如何检查结果不工作的。
private static function handleResize(…ig) :void { var deviceSize:Rectangle = new Rectangle(0, 0, stage.stageWidth, stage.stageHeight);}
//调整图形用户界面适应新的设备
stage.addEventListener(Event.RESIZE, handleResize);
//调用 handleResize初始化handleResize();
对于游戏重构,我想在游戏开始同时取得坐标。因此我需要一次性初始化用户界面。这种情况Stage.fullScreenWidth 和 Stage.fullScreenHeight属性近似可以实现,尽管他们不包括出现你应用的(例如那些发现的开火)系统工具条尺寸,方向也可能是错的,但是因为我的游戏朝向地平线,我可以假定宽度一直是固定的宽度,像下面:
var deviceSize:Rectangle = new Rectangle(0, 0, Math.max(stage.fullScreenWidth, stage.fullScreenHeight), Math.min(stage.fullScreenWidth, stage.fullScreenHeight));
朝向
在你的application.xml文件,你能设置默认的方向比对着陆地或者人像。对于手持设备操作系统也确定你需要的渲染屏幕图像-默认的陆地或默认的人像图像。如果你想支持两个模式,设置autoOrients 属性为真,在那种情况,重设尺寸事件将在任何时候激活改向当用户倾斜设备。你的应用简要地以错误方向开始即使autoOrients设置为否。
我用下面的配置强制地平方向。
<initialWindow>
<visible>true</visible>
<fullScreen>true</fullScreen>
<autoOrients>false</autoOrients>
<aspectRatio>landscape</aspectRatio>
<renderMode>gpu</renderMode>
…
</initialWindow>
对于游戏重构它普遍地坚持一个方面比多于前后转换,虽然大多数应用普遍支持双向比率
计算物理坐标
尽管一个小电话和一个大平板可能有同样数量的像素,他们有不同的物理尺寸。例如当你触摸iPhone 4\’s视网膜分辨率960 x 640 ,你的手指覆盖四倍多的像素比你触摸iPad 1\’s 1024 x 768 屏幕分辨率。这是重要地对考虑字体或者图标的可读性,尤其对于按钮的尺寸。对于按钮的尺寸。
根据点每英寸(更正确称作PPI或像素每英寸),你能通过估计你的屏幕多大避免一个胖手指错误。苹果建议一个按钮或者交互对象应当是对于一个163dpi屏幕是44 x 44像素(例如,苹果3GS)
安卓使用密度依赖像素,即用于定义基于160dpi屏幕的一个正常像素单元。一个设备的dp被计算作为像素*160/DPI,对于确定的dpi, dp, 和你能用下面代码确定的英寸尺寸
var dpi:Number = Capabilities.screenDPI;
var dpWide:Number = stage.fullScreenWidth * 160 / dpi;
var inchesWide:Number = stage.fullScreenWidth / dpi;
不幸地,设备经常报告错误的dpi(尤其对于IOS显示屏幕),Capabilities.screenDPI确切地是一个最好的猜测基于另外的信息,但是它也可能是错的,比较而言,你能取得初始的dpi通过操作系统像下面:
var serverString:String = unescape(Capabilities.serverString); var reportedDpi:Number = Number(serverString.split(“&DP=”, 2)[1]);
重建操作系统有2个静态接口层:一个用于iPad和另一个用于iPhone和iPod touch带着大文本和按钮.你能用现在的设备dpi和物理尺寸确定你用那个层。
伸缩和界面居中
Adobe AIR有几个已建立的伸缩模式,但是我发现 SHOW_ALL和 EXACT_FIT 行为古怪在设备上使用时。为了获得一个完全控制的设备伸缩(尤其有用当重设位图),我发现最好使用NO_SCALE处理缩放。
重建安卓使用1024 x 600图形用户界面取得缩放,水平居中在屏幕顶部。这被做在游戏第一次载入时,像下面一样:
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
var guiSize:Rectangle = new Rectangle(0, 0, 1024, 600);
var deviceSize:Rectangle = new Rectangle(0, 0, Math.max(stage.fullScreenWidth, stage.fullScreenHeight), Math.min(stage.fullScreenWidth, stage.fullScreenHeight)); var appScale:Number = 1; var appSize:Rectangle = guiSize.clone();
var appLeftOffset:Number = 0;
// 如果设备比用户界面宽,高度决定缩放
if ((deviceSize.width/deviceSize.height) > (guiSize.width/guiSize.height))
{
appScale = deviceSize.height / guiSize.height;
appSize.width = deviceSize.width / appScale;
appLeftOffset = Math.round((appSize.width – guiSize.width) / 2);
}
//如果设备高于图形用户界面,宽决定缩放
else
{
appScale = deviceSize.width / guiSize.width;
appSize.height = deviceSize.height / appScale;
appLeftOffset = 0;
}
// 缩放整个界面
base.scale = appScale;
// 图以左上角为基点并且填充整个屏幕
base.map.x = 0;
// 菜单水平居中
base.menus.x = appLeftOffset;
// 放置一些菜单被设计在屏幕边上
base.scrollRect = appSize;
对象的相对尺寸和位置不论如何缩放保持在基础上。例如,在我的回滚订单列里的项一直以50像素隔开。但是你将需要调整缩放在任何时间,当你用MouseEvent.stageX , MouseEvent.stageY , 或者 DisplayObject.localToGlobal .
转换向量到缩放位图
用向量对象构建、图标、按钮和背景重建的浏览器版本。他们使低文件尺寸放大看上起很大,但是在设备上缩放可能太复杂而不能有效渲染。他们也用不支持GPU渲染模式在Adobe AIR过滤器,并且有一个阻塞的边,当stage.quality设置为低品质能增加性能。我的解决方案是在缩放时用位图替换他们。我只这样做一次当游戏第一次载入时。
如果你不用向量,你也可以用下面代码缩放你需要尺寸的大位图,这样它们看上去平滑而且占用较少的内存。然而包含文本和图标的位图缩放程度太大可能有较差的渲染质量。你可以更好的结果如果有二个或更多的预先渲染的位图并且选择了一个基于屏幕dpi的位图。
// 初始化原始对象尺寸(将不包括光晕效果)
var objectBounds:Rectangle = object.getBounds(object);
objectBounds.x *= object.scaleX;
objectBounds.y *= object.scaleY;
objectBounds.width *= object.scaleX;
objectBounds.height *= object.scaleY;
// 目标位图尺寸
var scaledBounds:Rectangle = objectBounds.clone();
scaledBounds.x *= appScale;
scaledBounds.y *= appScale;
scaledBounds.width *= appScale;
scaledBounds.height *= appScale;
// 缩放并且转换左上角并填充整个对象
var matrix:Matrix = new Matrix();
matrix.scale(object.scaleX, object.scaleY);
matrix.scale(appScale, appScale);
matrix.translate(-scaledBounds.x, -scaledBounds.y);
// 主要增加舞台平直当创建位图时
stage.quality = StageQuality.HIGH;
var bitmapData:BitmapData = new BitmapData(scaledBounds.width, scaledBounds.height, true);
bitmapData.draw(object, matrix); stage.quality = StageQuality.LOW;
// 排列位图用原始的对象并且替换它
var bitmap:Bitmap = new Bitmap(bitmapData);
bitmap.x = objectBounds.x + object.x;
bitmap.y = objectBounds.y + object.y;
object.parent.addChildAt(bitmap, object.parent.getChildIndex(object));
object.parent.removeChild(object);
//转换位图缩放使它填充原始的图形用户界面
// 下面将被反转当整个应用基础被缩放
bitmap.scaleX = bitmap.scaleY = (1 / appScale);
你需要二个或更多的同样的位图对象,你应该存储或重用一个单独的位图数据对象,应为它占用非常少的内存去创建另一个位图对象。记住调用Bitmap.bitmapData.dispose() 方法当你处理它,立即从内存中删除它多于等待垃圾收集器处理。
侦测和限制苹果操作系统设备
iPhone, iPad和 iPod touch 报告它们的名字在Capabilities.os属性,因此依据这属性侦测确切游戏运行在哪一个设备上。例如,重建有更少的动画和更小的图片在较小的 iPad 1 和iPhone 3GS.下面的代码侦测了 iOS 设备而且调整游戏依据属性。
public static function getDevice():String
{
var info:Array = Capabilities.os.split(” “);
if (info[0] + ” ” + info[1] != “iPhone OS”) { return UNKNOWN; }
// 排序从指定的 (iPhone1,1) 到普遍的 (iPhone)
for each (var device:String in IOS_DEVICES)
{ if (info[3].indexOf(device) != -1)
{ return device; } } return UNKNOWN; }
public static const IPHONE_1G:String = “iPhone1,1”;
//第一代是1,1
public static const IPHONE_3G:String = “iPhone1”;
//第二代是1,2
public static const IPHONE_3GS:String = “iPhone2”;
//第三代是2,1
public static const IPHONE_4:String = “iPhone3”;
// 普通的:3,1版本:3,3
public static const IPHONE_4S:String = “iPhone4”;
// 4S是4,1
public static const IPHONE_5PLUS:String = “iPhone”;
public static const TOUCH_1G:String = “iPod1,1”;
public static const TOUCH_2G:String = “iPod2,1”;
public static const TOUCH_3G:String = “iPod3,1”;
public static const TOUCH_4G:String = “iPod4,1”;
public static const TOUCH_5PLUS:String = “iPod”;
public static const IPAD_1:String = “iPad1”;
// iPad1是1,1
public static const IPAD_2:String = “iPad2”;
// wifi:2,1 gsm:2,2 cdma:2,3
public static const IPAD_3:String = “iPad3”;
// (猜猜)
public static const IPAD_4PLUS:String = “iPad”;
public static const UNKNOWN:String = “unknown”;
private static const IOS_DEVICES:Array = [IPHONE_1G, IPHONE_3G, IPHONE_3GS, IPHONE_4, IPHONE_4S, IPHONE_5PLUS, IPAD_1, IPAD_2, IPAD_3, IPAD_4PLUS, TOUCH_1G, TOUCH_2G, TOUCH_3G, TOUCH_4G, TOUCH_5PLUS];
尽管,我已经在上面列出所有的苹果移动设备,你将从来不需要支持第一或者第二代 iPhone 和 iPod Touch,因为他们缺乏需要的架构(armv7) 和图像库 (opengles-2)用来运行AIR 3.2 应用。他们有很少的方式更多地限制你在一个兼容的iOS 设备上的应用。你能设置你的应用只用于iPads, 或者只用于 iPhone/iPod Touch通过UIDeviceFamily 用application.xml,例如:
<iPhone>
<InfoAdditions>
<![CDATA[ <key>UIDeviceFamily</key> <array>
<!– iPhone 支持 –> <string>1</string>
<!– 取消注解对于iPad 支持<string>2</string> –> </array> … ]]>
</InfoAdditions>
</iPhone>
你能取得更多指定通过设置UIRequiredDeviceCapabilities在同样的application.xml.例如,要求一个持续的照相意味着设备必须有一摄像机。要求一个陀螺仪便利限制你的应用用于新的 iPhone 4+, iPod Touch 4+和 iPad 2+. 维基百科有一个明确的 iOS设备和他们特征的列表。
为了能使双倍密度显示在iPhone 4S+(iPad 3视网膜支持也不能得到在AIR 3.2),设置requestedDisplayResolution为高。这个变化报告屏幕解决在iPhones从480 x 320 (163 dpi) 到960 x 640 (326 dpi)。确保你的应用缩放准确对于 iPhone 3GS和iPod Touch 3gen,他们都不支持视网膜分辨率屏幕。
限制安卓设备
有近1000个不同的安卓设备。他们并不通过能力系统报告自己的名字,并且没有方法决定中央处理器的能力或者设备的 内存。然而,你可以通过谷歌演示定位不同的安卓设备(例如只是表)或者是安卓苹果商店通过需要一定的屏幕大小和设备密度。
屏幕大小的性能指的是短边可以被扩展多少英寸:
小(大约2到3英寸)
正常(大约3到5英寸)
大(大约5到7英寸)
超大(大约7英寸及以上)
下面这些除去从application.xml意外意味着重组并不支持小或者说低像素的屏幕:
<android>
<manifestAdditions>
<![CDATA[ <manifest android:installLocation=”preferExternal”>
<supports-screens android:smallScreens=”false” android:normalScreens=”true” android:largeScreens=”true” android:xlargeScreens=”true”/>
<compatible-screens> <!– 在这里列出你支持的屏幕–>
<screen android:screenSize=”normal” android:screenDensity=”hdpi” />
<screen android:screenSize=”normal” android:screenDensity=”xhdpi” />
<screen android:screenSize=”large” android:screenDensity=”ldpi” />
<screen android:screenSize=”large” android:screenDensity=”mdpi” />
<screen android:screenSize=”large” android:screenDensity=”hdpi” />
<screen android:screenSize=”large” android:screenDensity=”xhdpi” />
<screen android:screenSize=”xlarge” android:screenDensity=”ldpi” />
<screen android:screenSize=”xlarge” android:screenDensity=”mdpi” />
<screen android:screenSize=”xlarge” android:screenDensity=”hdpi” />
<screen android:screenSize=”xlarge” android:screenDensity=”xhdpi” />
</compatible-screens> … </manifest> ]]>
</manifestAdditions>
</android>
2012年初,最流行的安卓系统是三星银河手机系列(800*480),摩托罗拉机器人(960*540),高科技公司需求系列(800*480),三星银河选项卡(1280*800), 和亚马逊kindle fire(1024*600).然而,每个国家都有不同的流行模式,并且没有任何一个安卓设备可以绝对的领导其他的,所以我们并不推荐去定位特殊的设备。
我在本地测试了一个我想支持的低端手机Nexus One(2010年一月发布的那款800*480),还有普通性能的kindle Fire。但是由于缓慢的设备使人丧气,最后开发应用一款更久的硬件这样你就可以明白什么事最低表现。像Test Droid这样的设备可以帮助以远程测试更宽范围的一系列的设备。
这儿该从哪里开始呢?
我取消了重置安卓好几个月因为我担心无法操控这么多设备,但是最后把规模放上来是一件很容易的事情,只需几天的时间。我也在黑莓的电脑上设置端口,最后也证明非常值得这相对较少的努力。
奥多比AIR使得在成千上万个不同的移动设备上运行相同的代码非常容易。奥多比已经做了大部分工作,所以如果你想定位一个设备,你也需要支持他们所有的性能在不同的形状,不同的大小条件下。
这项工作是在一个有创造性的普通性能非商业化的3.0非端口证书的条件下取得许可的。
adobe技术支持论坛:http://www.adobetop.com