15

SpriteKit は初めてです。UIImageView または SpriteNode を介して画像を表示する必要があります (ゲームの背景画像です)。ただし、ユーザーが背景にズームインしてパンできるようにする必要があります。SpriteKit を使用せずにこれを簡単に達成しましたが、ノードがズームとパンを受け入れるようにする方法がわかりません。ストーリーボードで UIScrollView を使用すると、シーンに追加されたすべてのスプライトが子にならず、ズームまたはパンしません。

それは可能ですか、正しい方向に私を向けることができますか?


編集:

私はあなたの答えに少し混乱していますが、これが私がしたことです:

私のルートView Controller .mで:

- (void)viewDidLoad
{
    [super viewDidLoad];
    SKView * showDesigner = (SKView *)self.view;
    SKScene * scene = [iMarchMyScene sceneWithSize:showDesigner.bounds.size];
    scene.scaleMode = SKSceneScaleModeAspectFill;
    [showDesigner presentScene:scene];
}

私のシーンで .m: (あなたのステップはコメントされています)

-(id)initWithSize:(CGSize)size {
    if (self = [super initWithSize:size]) {

        //create SKView (step 1)
        SKView *skview_field = [[SKView alloc]initWithFrame:(CGRectMake(0, 0, size.width, size.height))];

        //create UIScrollView with same dimensions as your SpriteKit view (step 2)
        UIScrollView* uiscrollview_field = [[UIScrollView alloc]initWithFrame:skview_field.frame];

        //initialize the field (field is the game's background node)
        SKSpriteNode *field = [SKSpriteNode spriteNodeWithImageNamed:@"Field"];
        field.position = CGPointMake(CGRectGetMidX(self.frame), (CGRectGetMidY(self.frame)));
        field.size = CGSizeMake(self.size.width, self.size.height / 3);

        //create a UIView (called scrollViewContent) with dimensions of background node (step 3)
        UIView* scrollViewContent = [[UIView alloc]initWithFrame:field.frame];

        //set UIScrollView contentSize with same dimensions as your scrollViewContent and add a scrollContentview as your UISCrollView subview (step 4)
        [uiscrollview_field setContentSize:(CGSizeMake(scrollViewContent.frame.size.width, scrollViewContent.frame.size.height))];
        scrollViewContent.frame = field.frame;
        [uiscrollview_field addSubview:scrollViewContent];



        //[self addChild:field]; -- my original code
        //.....does a bunch of other inits

        return self;
}

ステップ 5: ここで、ルート ビューに SKView を追加し、UIScrollView を SKView の上に追加します。

私があなたを正しく理解していれば、myRootViewController.m に移動し、viewDidLoad メソッドで SKView と UIScrollView (myScene.m で初期化される) を、ここで viewDidLoad メソッドで初期化された SKView にサブビューとして追加する必要がありますか? その部分のやり方がわかりません。

4

5 に答える 5

15

これがスクロールの問題に対する私の解決策です。UIScrollView から動作を「盗む」ことを中心に展開します。これは、UIKit と OpenGL の混合に関する 2012 年の WWDC ビデオから学びました。

  1. UIScrollViewDelegate メソッドを ViewController に追加し、スクロール ビュー デリゲートを ViewController に設定します。
  2. PanGestureRecognizer を UIScrollView から SKView に追加/移動する
  3. scrollViewDidScroll コールバック メソッドを使用して、ユーザーがスクロールするときに必要なノードを制御します。

サンプル プロジェクト: https://github.com/bobmoff/ScrollKit

上記のコメントで述べたように、アプリを実行している時間の約 30% で小さな遅延が発生しています。FPS はまだ 60 ですが、デリゲート メソッドが呼び出される頻度に若干の競合または何かがあるようです。誰かがこの問題を解決することができれば、私はそれについて聞きたいです. 指を押さえている時だけのようで、減速時に遅れることはありません。

于 2013-10-05T12:44:54.493 に答える
4

ジャスティン、

ちょっとしたトリックを使用できます。私はそれを使用していますが、私にとってはうまく機能します。セットアップは次のとおりです。

  • SKViewを作成する
  • SpriteKit ビューと同じサイズの UIScrollView を作成します
  • バックグラウンド ノードと同じサイズの UIView (scrollContentView という名前を付けます) を作成します。
  • UIScrollView contentSize を scrollContentView と同じサイズに設定し、 scrollContentView を UIScrollView サブビューとして追加します

次に、ルート ビュー (UIView) に SKView を追加し、UIScrollView を SKView の上に追加します。次のようになります(ビューコントローラー):

self.scrollView              = [[UIScrollView alloc] initWithFrame:[UIScreen mainScreen].bounds.size];
self.scrollContentView       = [[UIView alloc] init];
self.scrollView.delegate     = self;

self.spriteKitView           = [[SKView alloc] initWithFrame:[UIScreen mainScreen].bounds.size];
self.scrollContentView.frame = self.scene.bacgroundNode.frame;
self.scrollView.contentSize  = self.scrollContentView.frame.size;

[self.scrollView addSubview:self.scrollContentView];

[self.view addSubview:self.spriteKitView];
[self.view addSubview:self.scrollView];

[self.spriteKitView presentScene:self.scene];


トリックの最後の部分は、UIScrollViewDelegate を実装することです。

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {

  //here you set your background node position based on scrollView contentoffset
}

- (void)scrollViewDidZoom:(UIScrollView *)scrollView {

  //here you set background node scale based on scrollView zoomScale
}

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {

  //just return scrollContentView
}

このようにして、UISCrollView 内で SKView をシミュレートできます。お役に立てれば。

編集 2014-04-20

SpriteKit でシーンをパンおよびスクロールするためのコンポーネントをオープン ソース化しました。https ://github.com/pzbyszynski/PIOSpriteKit をご覧ください

于 2013-09-30T14:04:35.410 に答える
1

シーン全体をズームせずに特定のノードをズームする独自の方法を作成しましたが、これがその基本ですが、完全ではありません (実際、ここで独自のヘルプ リクエストを作成しました: SKNode の不一致のズーム)

この if ステートメントは、シーンの touchesMoved メソッドに入ります。

   if (touches.count == 2) {
        // this means there are two fingers on the screen
        NSArray *fingers = [touches allObjects];
        CGPoint fingOneCurr = [fingers[0] locationInNode:self];
        CGPoint fingOnePrev = [fingers[0] previousLocationInNode:self];
        CGPoint fingTwoCurr = [fingers[1] locationInNode:self];
        CGPoint fingTwoPrev = [fingers[1] previousLocationInNode:self];

        BOOL yPinch = fingOneCurr.y > fingOnePrev.y && fingTwoCurr.y < fingTwoPrev.y;
        BOOL yUnpinch = fingOneCurr.y < fingOnePrev.y && fingTwoCurr.y > fingTwoPrev.y;

        BOOL xPinch = fingOneCurr.x > fingOnePrev.x && fingTwoCurr.x < fingTwoPrev.x;
        BOOL xUnpinch = fingOneCurr.x < fingOnePrev.x && fingTwoCurr.x > fingTwoPrev.x;

        if (xUnpinch | yUnpinch) {
            if (YES) NSLog(@"This means an unpinch is happening");
            mapScale = mapScale +.02;
            [map setScale:mapScale];
        }

        if (xPinch | yPinch) {
            if (YES) NSLog(@"This means a pinch is happening");
            mapScale = mapScale - .02;
            [map setScale:mapScale];
        }
    }

私が抱えている唯一の問題は、一貫性のない動作とスムーズでないスクロールです。私はその意味で「だけ」という言葉を非常に寛大に使っています。

于 2013-10-19T02:27:27.423 に答える