SKView bounds.size 在触摸事件时反转(Sprite Kit)

Posted

技术标签:

【中文标题】SKView bounds.size 在触摸事件时反转(Sprite Kit)【英文标题】:SKView bounds.size get inverted on touch event (Sprite Kit) 【发布时间】:2014-09-11 01:15:12 【问题描述】:

请帮助我理解以下行为(ios Sprite Kit)。

我在下面给出的代码的输出是:

1.skView.bounds.size = 768.00, 1024.00

2.skView.bounds.size = 1024.00, 768.00

如上所示,宽度和高度在两种方法之间切换,这导致我的第二个场景无法以正确的比例呈现。

我的游戏只会在横向模式下运行,这意味着事实上,第二个宽 x 高比是正确的(尽管它是第一个以正确的纵横比渲染场景,这本身就是一个谜给我)。

谁能告诉我如何解决这个问题?我做错了什么?

- (void)viewDidLoad

    [super viewDidLoad];

    self.currentGameState = GS_INTRO_SCENE;

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

    // Create and configure the scene.

    printf("1.skView.bounds.size = %.2f, %.2f\n", skView.bounds.size.width, skView.bounds.size.height);

    SKScene *scene = [SKTGameIntroScene sceneWithSize:skView.bounds.size];
    scene.scaleMode = SKSceneScaleModeAspectFill;

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


-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event

    if (self.currentGameState == GS_INTRO_SCENE) 
        self.currentGameState = GS_GAME_PLAY;

        SKView * skView = (SKView *)self.view;

        printf("2.skView.bounds.size = %.2f, %.2f\n", skView.bounds.size.width, skView.bounds.size.height);

        SKScene *nextScene = [SKTMyScene sceneWithSize:skView.bounds.size];
        nextScene.scaleMode = SKSceneScaleModeAspectFill;

        SKTransition *fadeIn = [SKTransition fadeWithDuration:5.0f];

        [skView presentScene:nextScene transition:fadeIn];
    

提前非常感谢。

** 编辑:**

@giorashc 解决了我的问题,建议我将场景启动移动到 -(void)viewWillLayoutSubviews 方法。

但是我的第二个场景仍然被拉伸......这是更改后 SKTViewController.m 的完整代码(谁能说为什么第二个视图仍然被拉伸?):

//
//  SKTViewController.m
//  SpriteKitTest
//
//  Created by Claudia Dazcal on 13/07/14.
//  Copyright (c) 2014 DazcalFamily_inc. All rights reserved.
//

#import "SKTViewController.h"
#import "SKTMyScene.h"
#include "SKTGameIntroScene.h"

typedef enum

    GS_INTRO_SCENE,
    GS_GAME_PLAY
GameStates;

@interface SKTViewController ()

@property GameStates currentGameState;
@property BOOL firstSceneLoaded;

@end

@implementation SKTViewController

- (void)viewDidLoad

    [super viewDidLoad];

    self.currentGameState = GS_INTRO_SCENE;

    self.firstSceneLoaded = NO;



-(void)viewWillLayoutSubviews

    if (!self.firstSceneLoaded) 
        self.firstSceneLoaded = YES;

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

        // Create and configure the scene.

        printf("1.skView.bounds.size = %.2f, %.2f\n", skView.bounds.size.width, skView.bounds.size.height);

        SKScene *scene = [SKTGameIntroScene sceneWithSize:skView.bounds.size];
        scene.scaleMode = SKSceneScaleModeAspectFill;

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

    



-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event

    if (self.currentGameState == GS_INTRO_SCENE) 
        self.currentGameState = GS_GAME_PLAY;

        SKView * skView = (SKView *)self.view;

        printf("2.skView.bounds.size = %.2f, %.2f\n", skView.bounds.size.width, skView.bounds.size.height);

        //CGSize DebugSize = CGSizeMake(skView.bounds.size.height, skView.bounds.size.width);

        //SKScene *nextScene = [SKTMyScene sceneWithSize:DebugSize];
        SKScene *nextScene = [SKTMyScene sceneWithSize:skView.bounds.size];
        nextScene.scaleMode = SKSceneScaleModeAspectFill;

        //SKTransition *fadeIn = [SKTransition fadeWithDuration:5.0f];

        //[skView presentScene:nextScene transition:fadeIn];
        [skView presentScene:nextScene];
    


- (BOOL)shouldAutorotate

    return YES;


- (NSUInteger)supportedInterfaceOrientations

    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) 
        return UIInterfaceOrientationMaskAllButUpsideDown;
     else 
        return UIInterfaceOrientationMaskAll;
    


- (void)didReceiveMemoryWarning

    [super didReceiveMemoryWarning];
    // Release any cached data, images, etc that aren't in use.


@end

* 编辑 2 **

好的,现在都解决了。

@giorashc 在他建议将场景启动移至 viewWillLayoutSubviews 时立即解决了我的问题。事实证明,由于我之前使用了错误的边界,所以我使用错误的值设置了我的原始场景,现在它已被修复,它看起来被拉伸了。

但它现在已修复。非常感谢@giorashc!!

【问题讨论】:

【参考方案1】:

viewWillLayoutSubviews 方法中初始化您的场景。在这种方法中,视图边界被正确更新。

请确保您只初始化场景一次,因为每当视图控制器呈现另一个视图控制器或应用程序正在改变其方向时都会调用此方法。

【讨论】:

谢谢,它确实解决了我看到的切换纵横比。但是我的第二个场景仍然在切换纵横比的情况下被拉伸(即使我在输出中确实看到纵横比实际上并没有切换)......知道为什么吗?? 您在哪里创建第二个场景?你能显示代码吗? (如果可能,用代码编辑您的问题) 在呈现第二个场景之前打印什么边界?他们和你期望的一样吗? 谢谢@giorashc。它已解决(谢谢你)......我在问题本身中解释它【参考方案2】:

在第一种方法中,视图尚未旋转到横向模式。在第二个中,它已旋转到横向模式,因此现在报告的边界比它的高度更宽。

【讨论】:

以上是关于SKView bounds.size 在触摸事件时反转(Sprite Kit)的主要内容,如果未能解决你的问题,请参考以下文章

Swift 中的 viewWillLayoutSubviews

如何使用 Swift 在 Playground 中获取用户交互事件

动画UICollectionViewCell时bounds.size和frame.size之间的相关性是啥

UIScrollView bounds.size

仅在 xCode 中的触摸区域应用高斯模糊滤镜

快速检测到 SKSpriteNode 触摸