I am new to SpriteKit. I need to display an image via UIImageView OR SpriteNode (it is a background image for a game). However, I need the user to be able to zoom in to the background and pan around. I accomplished this easily without using SpriteKit but cannot figure out how to make a node accept zoom and pan. If I use UIScrollView in the storyboard, all the sprites added in my scene don't become children and will not zoom or pan.
Is it possible and can you point me in the right direction?
EDIT:
I'm a little confused by your answer, but here's what I did:
In my root 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];
}
In my scene .m: (your steps are commented)
-(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;
}
And here's where I get lost: Step 5: Now, to your root view add your SKView, and UIScrollView on top of SKView.
If I understood you correctly, I need to go to myRootViewController.m and in the viewDidLoad method, add the SKView and UIScrollView (which are initialized in myScene.m) as subviews to SKView initialized here in the viewDidLoad method? I don't see how to do that part.
If you are using an
SKCameraNode
you can calculate the difference between two touches to define zooming and panning at once.SKCameraNode
for your SKViewResult should be something like this. Note that I used the
event?.allTouches
instead of the received set, if one finger doesn't move between touches, it's not in thetouches
set, which would cause a pan where a user would expect a zoom.Justin,
you can use a little trick, I am using it and it works great for me. Here is the setup:
Now, to your root view (UIView) add your SKView, and UIScrollView on top of SKView. It goes something like this (view controller):
Last part of the trick is to implement UIScrollViewDelegate:
This way you can simulate SKView inside UISCrollView. Hope this helps.
EDIT 2014-04-20
I have open sourced my component for panning and scrolling scenes in SpriteKit, please have a look at: https://github.com/pzbyszynski/PIOSpriteKit
You could start with this Ray W tutorial SpriteKit tutorial how to drag and drop that includes some of the things you ask for including Gesture recognizers.
This is good: Apple gesture Recognizer reference
Another from Ray W: uigesturerecognizer-tutorial-in-ios-5-pinches-pans-and-more
The above is good to start with.
Here is my solution to the scrolling problem. It revolves around "stealing" the behaviour from the UIScrollView. I learned this from a WWDC Video from 2012 about mixing UIKit with OpenGL.
Example project: https://github.com/bobmoff/ScrollKit
Like I mentioned in a comment above, I am experiencing some tiny lag about 30% of the times I am running the app. The FPS is still 60 but there seem to be some slight conflict or something with how often the delegate method is called, as it sometimes feel a little laggy. If anyone manages to solve this issue, I would love to hear about it. It seems to be only when I am holding my finger down, it never lags when the deceleration is happening.
I have created my own method for zooming a specific node without having to zoom the entire scene and this is the basics of it, however it is not perfect (and in fact I have created its own help request here: Zooming an SKNode inconsistent )
This if statement goes in the touchesMoved method of the scene:
The only problem I am having with it is inconsistent behavior and unsmooth scrolling. I use the word 'only' in that sense with great liberalness.