背景图片大小 Sprite Kit 游戏

34

我刚开始一个Sprite Kit项目来学习如何使用它。我看了很多教程,但是没有一个教程能够回答我的问题/问题。

我想创建一个专门为我的iPhone 5S制作的应用程序。所以屏幕尺寸为1136x640。我为我的应用程序创建了一个1136x640的背景图像。但是当我将图像添加到应用程序中时,它太大了!iOS模拟器只显示图像的中间部分。

有人能告诉我我必须使用什么屏幕尺寸以及原因吗?

非常感谢!

这里是我从教程中复制的代码。 该代码位于myScene.m文件中的initWithSize方法中

        SKSpriteNode *background = [SKSpriteNode spriteNodeWithImageNamed:@"myBackground"];
    background.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMidY(self.frame));

    [self addChild:background];

编辑:

我在Google上搜索并找到了以下内容:

视图加载方法必须改为“viewWillLayoutSubviews”。

这是该方法:

    - (void)viewWillLayoutSubviews
    {
    [super viewWillLayoutSubviews];

    // Configure the view.
    SKView * skView = (SKView *)self.view;
    skView.showsFPS = YES;
    skView.showsNodeCount = YES;

    // Create and configure the scene.
    SKScene * scene = [MyScene sceneWithSize:CGSizeMake(skView.bounds.size.width*2,skView.bounds.size.height*2)];
    scene.scaleMode = SKSceneScaleModeAspectFill;

    // Present the scene.
    [skView presentScene:scene];
}

一开始的场景 = MySceneWithSize 的语句是:

SKScene * scene = [MyScene sceneWithSize:skView.bounds.size];

但是它只有iPhone 5屏幕尺寸的一半(568x320)。所以我不得不将尺寸加倍。有人知道为什么吗?


1
只是一个想法:如果你想为你的手机制作一个应用程序,那么你确实应该首要在你的手机上进行测试。从我的经验来看,模拟器往往是一种痛苦的来源。 - Kheldar
Mike - 如果你还在 Stack Overflow 上,能否标记下面的正确/最有用的答案。我有点偏见,但我认为我的是最好的;-) - GilesDMiddleton
1
@Gilesey - 对不起..我完全忘记了这个帖子。没问题,你的答案可行。 - Mike_NotGuilty
9个回答

30

针对您当前问题的简短答案:

background.size = self.frame.size;

长篇回答以及其他方法的讨论...

场景中使用的是逻辑单位,而不是物理像素(如其他帖子所述)。

1个逻辑单位通常等于旧设备上的1个像素,而等于新设备/ iPad上的2个像素。在未来5年内,这可能会增加到4个像素。

使用逻辑单位工作可以保护您免受大小在未来更改的影响,并且应该有助于程序员 - 尽管这经常会使新手感到困惑。

将图像填充到当前场景的最简单方法是无论其原始大小如何,都将其大小设置为“逻辑单位”。

这比使用SKActions好(因为用户可能最终会看到它们,而且在节点尺寸基础上进行的任何计算直到操作完成才能被依赖),并且比缩放更好,因为缩放需要您了解原始图像尺寸。

您可以通过大小属性或通过操作来执行此操作,如果您真的想制作动画。

在场景中只需...

-(void)didMoveToView:(SKView *)view
{
    [super didMoveToView:view];

    SKSpriteNode* background = [SKSpriteNode spriteNodeWithImageNamed:@"myBackground"];
    background.size = self.frame.size;
    background.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
    [self addChild:background];
} 

或者,如果您的图像在高分辨率上使用良好,则可以将其重命名为myBackground@2x.png,并将其添加到项目中,您可能根本不需要调整大小,但对于低分辨率设备,您还需要将其缩小50%并将其保存为myBackground.png。

我总是将导入图像的大小设置为我想要的逻辑单位大小(或屏幕尺寸的百分比),以保持我的理智。


1
这是在Sprite Kit中设置背景图像最重要的部分。background.size = self.frame.size; 干得好,伙计。 - Adrian P

9

我发现,如果一个图片的大小与您要创建的节点不同,那么缩放将会有点奇怪(例如,在非视网膜设备上使用视网膜图片或使用不正确的图片命名)。如果您从图像创建纹理并使用以下代码设置纹理和节点大小,则可以对图像进行缩放以填充:

SKTexture *backgroundTexture = [SKTexture textureWithImageNamed:@"MyImage.png"];
SKSpriteNode *background = [SKSpriteNode spriteNodeWithTexture:backgroundTexture size:self.view.frame.size];
background.position = (CGPoint) {CGRectGetMidX(self.view.frame), CGRectGetMidY(self.view.frame)};
[scene addChild:background];

我不确定这样做是否能解决你的问题,但或许值得一试。


抱歉打扰您了...但我很好奇...使用SKTexture而不是像这样使用图像是否有原因/好处/优势:SKSpriteNode *bgImage = [SKSpriteNode spriteNodeWithImageNamed:@"background"]; - Confused
1
去年我在玩SpritKit时发现[SKSpriteNode spriteNodeWithImageNamed:@"background"];无法将图像缩放到指定的SKSprideNode大小(例如,如果我的图像为20x20,则将节点大小设置为100x100时不会缩放图像)。 但是,使用单独的SKTexture并将其传递给构造函数,并且具有不同的大小可以缩放图像。自从7.1发布以来,我还没有玩过SpritKit,所以我不知道这是否仍然正确。 - James Jones

8

此行返回的是点大小,而不是像素大小。这样做是因为不同设备具有不同的分辨率,但在点数上大小相同。在非视网膜设备上,1点等于1像素,在视网膜设备上,1点等于2像素。这就是为什么您可以从中获取此大小的原因。

SKScene * scene = [MyScene sceneWithSize:skView.bounds.size];

如果您将场景的大小翻倍,它将超出屏幕范围,变得不可见。


7
您尝试过在图像名称末尾添加“@2x”吗?该方法可以提高图像质量。

我认为这可能只适用于Xcode 5,但是Xcode可以自动显示您正在使用的图像分辨率。如果您同时使用2x和标准分辨率,则通常会自动选择2x。 - user2277872
请尝试在真实设备上运行此代码,而非模拟器。 - Nicolas Miari

3

我基本上和上面的回答一样,但我会直接设置宽度和高度,这样我就不用担心是否设置正确了,当然,我还需要检查他们是否在使用iPhone4以获得完整的解决方案。

- (void)viewWillLayoutSubviews
{
    [super viewWillLayoutSubviews];

    // Configure the view.
    SKView * skView = (SKView *)self.view;
    if (!skView.scene) {
        skView.showsFPS = YES;
        skView.showsNodeCount = YES;

        CGSize tmpSize;
        tmpSize.width = 640;
        tmpSize.height = 1136;
        // Create and configure the scene
        SKScene * scene = [CreationScene sceneWithSize:tmpSize];

        scene.scaleMode = SKSceneScaleModeAspectFill;

        // Present the scene.
        [skView presentScene:scene];
    }
}

2
这对我有效。这样做可以吗?
//Set background image.
    SKSpriteNode *background = [SKSpriteNode spriteNodeWithImageNamed:@"myBackground.png"];
    background.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
    background.xScale = 0.5;
    background.yScale = 0.5;

    [self addChild:background];

如果您从不更改底层图像尺寸,则可以这样做。如果更改了图像尺寸,则必须更改代码。通过设置 .size,您将保护自己免受此类更改的影响。 - GilesDMiddleton

2

我使用了精灵图作为背景。

    double escalax =        self.size.width/ sprite.size.width  ;
    double escalay =        self.size.height/ sprite.size.height  ;


    SKAction *mostrar = [SKAction scaleXTo:escalax y:escalay duration:0];

希望能帮到你!

2
解决方案:
将此代码放入viewWillLayoutSubviews中,而不是加载精灵的UIViewController的viewDidLoad中。
  - (void)viewWillLayoutSubviews
{
    [super viewWillLayoutSubviews];

    // Configure the view.
    SKView * skView = (SKView *)self.view;
    if (!skView.scene) {
      skView.showsFPS = YES;
      skView.showsNodeCount = YES;

      // Create and configure the scene.
      SKScene * scene = [MyScene sceneWithSize:skView.bounds.size];
      scene.scaleMode = SKSceneScaleModeAspectFill;

      // Present the scene.
      [skView presentScene:scene];
    }
}

说明:这将创建一个与视图边界大小相同的场景。然而,在调用viewDidLoad之前,此时视图尚未添加到视图层次结构中,因此它尚未响应布局更改。因此,视图边界可能尚不正确,这可能不是启动场景的最佳时间。
此答案来自:http://www.raywenderlich.com/42699/spritekit-tutorial-for-beginners,由Ray提供。 :)
我在我的SKScene中使用了与您相同的代码,但如果没有Ray在呈现场景的UIViewController中提供的解决方案,它将无法正常工作。

1

最终我解决了我的问题。我已经将场景设置为1024*768,因此我的场景高度为768而不是480。看到这篇文章的每个人都可以尝试一下。 - Alfred

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接