在Spritekit游戏中约束GUI元素的比例

时间:2015-03-22 19:29:41

标签: ios sprite-kit size sprite universal

GUI elements example image

我提前道歉,因为帖子很大,但是每个试图制作某种通用应用程序的人都知道这是非常有问题的东西,所以请对我很轻松......

目标

我想要实现的目标(如上图所示)是在iPhone 5和6上同时使用@ 2x资源,并保持应用程序的外观相同。并且如果可能的话,在没有基于检测到的设备手动计算节点的比例和位置属性的情况下完成所有这些...简而言之,如何实现该应用程序自动约束元素(和场景)之间的比例?另外我想在iPhone 6+上使用@ 3x资产看一下应用程序,但由于简单,我只集中在iPhone 5和6上。

我在网上发现的是有些人说这个(缩减采样)是由iOS自动完成的,例如他们建议:

  

"制作iPhone 6大小的@ 2x资产,然后iOS就可以了   iPhone 5"。

自动降尺寸

但是当谈到Spritekit场景时,这显然不是真的,或者我错过了什么。

问题

即使iPhone 6和iPhone 5具有相同的宽高比和相同的PPI,使用相同的资产看起来与场景尺寸相比看起来相同(第1和第2张图片上的外观菜单精灵与场景尺寸相比)因为PPI与像素密度有关,iPhone 6有更多的空间(更大的对角线,更大的英寸),这意味着它的像素比iPhone 5更多。这就是我的问题所在,我不知道会是什么一种处理它的有效方法。

到目前为止我做了什么

第二个图像不是GUI的问题,但对于游戏玩法,在我的情况下,因为我想在不同的设备上看起来和感觉相同。 只需查看第一张和第三张图片。

感谢Skyler Lauren's建议我已经设法在7.1或8.1系统以及iPhone 6上的所有iPhone 5设备上看到相同的应用程序。所以现在,问题是如何使用@ 3x纹理以及iPhone 4s,使用此代码可以与iPhone 6+配合使用。这是iPhone 5和6的解决方案:

查看controller.m

GameScene *scene = [GameScene sceneWithSize:CGSizeMake(375,677)];//fixed instead of view.bounds.size
 scene.scaleMode = SKSceneScaleModeAspectFill;

因此,iPhone 6尺寸的场景始终具有固定尺寸,并且视图尺寸根据设备而变化。我正在使用资产目录来启动图像而不是xib文件。图像尺寸为推荐尺寸 - 640x960px 4s,640x1136px 5,750x1334px 6和1242x2208 6 +型号。资产的大小适合iPhone 6,因此对于该型号,根本没有缩放。

与4s模型相关,当我使用上述方法时,每边都有两个黑条......

到目前为止,我只在模拟器和iPhone 6设备上测试了这一点(我在设备或模拟器上看到的第一张图片看起来像。)

问题

目前正如我所说的一切都适用于iPhone 4s(由于不同的宽高比而有两个黑条),5,6使用@ 2x资产,但如何使用@ 3x资产使iPhone 6+一切正常? 如果我使用375x667尺寸的场景,那么一切都正确定位并具有良好的比例,但质量受损(因为升级@ 2x)

2 个答案:

答案 0 :(得分:5)

统一的GUI和游戏

据我所知,处理统一GUI和游戏的最佳方法是设置场景大小(无论设备如何),让SpriteKit从那里开始缩放。

GameScene *scene = [GameScene sceneWithSize:CGSizeMake(375,677)];//fixed instead of view.bounds.size
scene.scaleMode = SKSceneScaleModeAspectFill;

这是iPhone 6的分数。因为SpriteKit在点上工作但设备以像素显示,对于@ 2x设备,场景大小为750px x 1354px像素,对于iPhone 6+,场景大小为1125px x 2031px(以像素为单位的设备是实际1080 x 1920)。

这如何与资产配合使用?

对于.atlas文件夹中的1x和2x资产,它的效果相当不错。再次因为所有内容都转换为点,你可以在纹理图集中使用button.png和button@2x.png,并且所有iPhone的定位都相同并且看起来相同。

@ 3x怎么样?

这对Apple来说是一个更好的问题。显然,SpriteKit不支持纹理图集中的@ 3x图像。 SO上已经有一些问题试图解决这个问题。

一个例子......

Spritekit - not loading @3x images from SKTextureAtlas

似乎它还没有在Xcode 6.2中得到修复。如果你正在读这篇文章并想要@ 3x,那么可能值得用Apple提交雷达。需要注意的一点是,我没有看到文档中的任何地方声称纹理地图集被认为支持@ 3x(或者甚至是@ 2x)当它们被支持时你不会做任何事情更改代码。只需将@ 3x资产放入.atlas文件夹即可。

我可以/应该对@ 3x资产做些什么?

我的建议是不要担心它并运行@ 2x资产。 SpriteKit在缩放图像方面做得不错,有很多应用程序不支持@ 3x。作为iPhone 6+的拥有者,这是我现在学会了的东西。我希望Apple很快支持.atlas文件夹中的@ 3x图像。

<强>警告

你要求所有设备都缩小,但iPhone 6除外(并扩展iPhone 6+)在大多数情况下你不应该注意到你的艺术(或我的测试表现)的巨大差异,但正如你所知,如果缩小图像,它们可能会略有不同。还有4s的黑条问题,目前我还没有为您提供解决方案。

结束点

如果您设置场景大小并将场景设置为SKSceneScaleModeAspectFill,那么您将在所有设备的应用中获得完全相同的外观和感觉,但是您要求旧设备缩小。据我所知,它节省了大量的时间和计划,并进行了小幅缩减。

希望这对您的应用程序有所帮​​助并带来好运。

答案 1 :(得分:5)

您的主要问题似乎是处理与图像资源和屏幕对象坐标相关的各种屏幕尺寸。

我的解决方案是编写代码,就像编写iPhone 6 plus一样。为iPhone 6屏幕尺寸制作所有图像@ 3x尺寸和屏幕布局坐标。

只需一点代码,我就可以获得iPhone 6 plus,6,5和4屏幕尺寸的统一布局。我为每个人都添加了屏幕截图。角色图像为300x300。 2个按钮图像为100x100。

static const float kIphone6PlusScaleFactorX = 1.0;
static const float kIphone6PlusScaleFactorY = 1.0;
static const float kIphone6ScaleFactorX = 0.9;
static const float kIphone6ScaleFactorY = 0.9;
static const float kIphone5ScaleFactorX = 0.772;
static const float kIphone5ScaleFactorY = 0.772;
static const float kIphone4ScaleFactorX = 0.772;
static const float kIphone4ScaleFactorY = 0.652;

#import "GameScene.h"

@implementation GameScene {
    float scaleFactorX;
    float scaleFactorY;

    SKSpriteNode *node0;
    SKSpriteNode *node1;
    SKSpriteNode *node2;
    SKLabelNode *label0;
}

-(void)didMoveToView:(SKView *)view {
self.backgroundColor = [SKColor blackColor];

    if(view.frame.size.height == 736) {
        NSLog(@"iPhone 6 plus");
        scaleFactorX = kIphone6PlusScaleFactorX;
        scaleFactorY = kIphone6PlusScaleFactorY;
    }
    if(view.frame.size.height == 667) {
        NSLog(@"iPhone 6");
        scaleFactorX = kIphone6ScaleFactorX;
        scaleFactorY = kIphone6ScaleFactorY;
    }
    if(view.frame.size.height == 568) {
        NSLog(@"iPhone 5");
        scaleFactorX = kIphone5ScaleFactorX;
        scaleFactorY = kIphone5ScaleFactorY;
    }
    if(view.frame.size.height == 480) {
        NSLog(@"iPhone 4");
        scaleFactorX = kIphone4ScaleFactorX;
        scaleFactorY = kIphone4ScaleFactorY;
    }

    node0 = [SKSpriteNode spriteNodeWithImageNamed:@"Pic"];
    node0.position = CGPointMake(self.size.width/2, self.size.height/2);
    [node0 setScale:scaleFactorX];
    [self addChild:node0];

    node1 = [SKSpriteNode spriteNodeWithImageNamed:@"button0"];
    node1.position = CGPointMake(100*scaleFactorX, 100*scaleFactorY);
    [node1 setScale:scaleFactorX];
    [self addChild:node1];

    node2 = [SKSpriteNode spriteNodeWithImageNamed:@"button1"];
    node2.position = CGPointMake(314*scaleFactorX, 100*scaleFactorY);
    [node2 setScale:scaleFactorX];
    [self addChild:node2];

    label0 = [SKLabelNode labelNodeWithFontNamed:@"HelveticaNeue-Bold"];
    label0.text = @"Big Game Menu";
    label0.fontSize = 48*scaleFactorX;
    label0.fontColor = [SKColor whiteColor];
    label0.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeCenter;
    label0.verticalAlignmentMode = SKLabelVerticalAlignmentModeCenter;
    label0.position = CGPointMake(207*scaleFactorX,690*scaleFactorY);
    [self addChild:label0];
}

iPhone 4

enter image description here

iPhone 5

enter image description here

iPhone 6

enter image description here

iPhone 6 +

enter image description here

请注意文本标签是如何正确缩小的,不仅仅是字体大小,还有位置。

供我参考,我确实使用了GameViewController中的标准代码,因为我发现使用更简单的版本更容易。这是我用来呈现我的SKView的代码:

- (void)viewDidLoad {
    [super viewDidLoad];

    SKView * skView = (SKView *)self.view;
    SKScene *scene = [GameScene sceneWithSize:skView.bounds.size];
    scene.scaleMode = SKSceneScaleModeAspectFill;
    [skView presentScene:scene];
}