SpriteKit: Presenting the initial scene wth a transition - skview

I've created multiple transitions from between my game scenes, so I'm unsure why this code is not working.
In my GameViewController, I am simply setting up my TitleScene to appear as the next scene, but I would like it to fade in. I've done this in my touchesBegan succesfully.
Here is the code:
#implementation GameViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Configure the view.
SKView * skView = (SKView *)self.view;
skView.showsFPS = NO;
skView.showsNodeCount = NO;
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = YES;
// Create and configure the scene.
SKScene * scene = [TitleScene sceneWithSize:skView.frame.size];
scene.scaleMode = SKSceneScaleModeResizeFill;
// Present the scene.
SKTransition *transition = [SKTransition fadeWithColor:[SKColor blackColor] duration:3.6];
[skView presentScene:scene transition:transition];
}

You can't use SpriteKit to present the initial scene with a transition because the SKView is (by definition) not showing any scene before the initial scene, so from its perspective there's nothing for it to transition from.
Presumably, from your point of view, you want to fade into your scene from whatever the user is seeing before SpriteKit gets started — the launch screen of your app, maybe? A common strategy for that is to have the initial storyboard scene contain a UIImageView containing the same image as your launch screen, layered on top of your SKView. When you're ready to start the game, use UIView animateWithDuration:animations:completion: to fade out the image view and remove it from the view hierarchy, and your SKView will be revealed beneath.

Related

Animating Change in NSPopover’s contentViewController

I have an NSPopover, which switches between two View Controllers.
I set one at launch,
self.popover.contentViewController = viewController1;
and I change to the other one based on a user action:
self.popover.contentViewController = viewController2;
AppKit does some animations to the NSPopover itself to accomodate the second VC, which work well, but the transition between the two View Controller’s views is jarring. I would like them to slide in and out horizontally or at the very least cross fade.
I am using layer-backed views, which I'm setting like this in the AppDelegate’s applicationDidFinishLaunching method:
self.popover.contentViewController.view.wantsLayer = YES;
self.popover.contentViewController.view.layerContentsRedrawPolicy = NSViewLayerContentsRedrawOnSetNeedsDisplay;
Here’s what I’ve tried:
fading out the first View Controller's view in -viewWillDisappear and fading in the second View Controller's view in -viewWillAppear. This fades out the first VC’s view immediately and does not fade the second VC’s view back in
fading out the first VC’s view’s layer before switching the popover’s contentViewController:
CALayer *theLayer = self.popover.contentViewController.view.layer;
CABasicAnimation* fadeAnim = [CABasicAnimation animationWithKeyPath:#"opacity"];
fadeAnim.fromValue = [NSNumber numberWithFloat:1.0];
fadeAnim.toValue = [NSNumber numberWithFloat:0.0];
fadeAnim.duration = 1.0;
[theLayer addAnimation:fadeAnim forKey:#"opacity"];
theLayer.opacity = 0.0;
self.popover.contentViewController = self.viewController;
This second strategy doesn't wait for the animation to finish before switching the View Controllers over.
How do I animate changing the NSPopover’s contentViewController?
So since you have multiple child view controllers in a parent view controller you should follow the view controller containment protocol. Rather than animating the views you want to animate the transition between the view controllers themselves.
toController.view.frame = fromController.view.bounds;
[containerViewController addChildViewController:toController];
[fromController willMoveToParentViewController:nil];
[containerViewController transitionFromViewController:fromViewController
toViewController:toViewController
duration:0.2
options:UIViewAnimationOptionTransitionCrossDissolve
animations:nil
completion:^(BOOL finished) {
[fromViewController removeFromParentViewController];
[toViewController didMoveToParentViewController:containerViewController];
toViewController.view.frame = containerViewController.view.bounds;
}];
Where containerViewController is your contentViewController.
Pretty much just tell the old view controller it's being removed from the parent, animate the transition, and remove the old controller and let the new controller know it's been moved to the parent.
More info from apple here: https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/CreatingCustomContainerViewControllers/CreatingCustomContainerViewControllers.html
And good tutorial on custom transitions here: http://www.objc.io/issues/12-animations/custom-container-view-controller-transitions/

How can I set Background image on MyScene in ios7

When I am setting a background image on a SKScene. I have written the code below:
#import "JTEDMyScene.h"
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#interface MyScene()
#property BOOL isContentCreated;
#end
#implementation MyScene
-(void) didMoveToView:(SKView *)view
{
if(!self.isContentCreated)
{
self.isContentCreated = YES;
[self createSceneContent];
}
}
-(void)createSceneContent
{
[self addChild:[self createBackground]];
}
-(SKSpriteNode *)createBackground
{
SKSpriteNode *backgroundSprite;
SKTexture *textureImage;
if (IS_IPAD) {
textureImage = [SKTexture textureWithImageNamed:#"home_ipad1.jpg"];
backgroundSprite = [SKSpriteNode spriteNodeWithTexture:textureImage];
}
backgroundSprite.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
return backgroundSprite;
}
Device orientation modes are only Landscape left and landscape right. My image size is width = 1024 and height= 768 and 264 dpi. But the image is not showing fully a portion of image is showing.
Maq has the right idea. I think what he's saying is, the problem lies in your view controller .m file, instead of in your Scene. Instead of creating your SKView and SKScene and presenting the SKScene from within the viewDidLoad method of your VC, put that code in the viewWillLayoutSubviews method instead. Something along the lines of this:
-(void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
SKView * skView = (SKView *)self.view;
SKScene * scene = [YourScene sceneWithSize:skView.bounds.size];
scene.scaleMode = SKSceneScaleModeAspectFill;
[skView presentScene:scene];
}
Apparently, viewWillLayoutSubviews gets called later than viewDidLoad. When viewDidLoad is called, the view hasn't even been added to the view hierarchy yet.
Ray Wenderlich's Sprite Kit Tutorial for Beginners quotes this answer from SO as to why this happens.
Try to present and create MyScene in viewWillLayoutSubviews - if you haven't done it already.
It may work if you just rename viewDidLoad to viewWillLayoutSubviews and rename the super call too.
I started a blank project and copy-pasted your code into it and it works fine. I know you said you set your device orientation, but did you do that in your project settings? That's the only problem I can think of. Select your project, general tab, and under Deployment Info, there's a "Devices" drop-down box. Select iPad and make sure "Landscape Left" and "Landscape Right" are the only two checked. My guess is that the project thinks it's supposed to be starting in portrait mode, so it's stretching your 768-tall image vertically to 1024 at start; then when your app determines that it's in landscape orientation, it just rotates that stretched image accordingly, which would result in the image being cut off.
yes, to control and resize background image (in my case) correspond to device orientation, you have to use -(void)viewWillLayoutSubviews
but don't forget, it will start from first scene by default, so you need to use some "sceneNumber" selector in this function to point to actual scene

Cocos2d scene loaded with wrong orientation

I'm trying to make a cocos2d scene on top of some UIKit views. I understand that the cocos2d 2.0 CCDirector is a subclass of UIViewController so that I can just add that as a subview.
I've written this function to handle switching to a scene in my appDelegate (currently thats
the delegate of my MainWindow.xib following http://www.raywenderlich.com/4817/how-to-integrate-cocos2d-and-uikit):
- (void)switchToScene
{
self.viewController = [CCDirector sharedDirector];
[[CCDirector sharedDirector] view].center = self.window.center;
[self.window addSubview:[self.viewController view]];
[[CCDirector sharedDirector] runWithScene:[CCTransitionSlideInL transitionWithDuration:1 scene:[BattleLayer scene]]];
}
So I'm missing quite a bit from this code. But with this, I get some resemblance of a scene to load http://i.stack.imgur.com/pubWE.png
My question is:
1: If I'm going in the right direction
2: If it is, is the next step to manually adjust the orientation of the scene?
2.1: How do I do this :)
I'm not sure how you want it to look but it seems that the CCDirector's view is rotated 90 degrees CW. This may be because of a few reasons:
you add the view wrong (i.e. rotated 90 degrees CW)
you rotated the device and the CCDirector didn't rotate (in which case you should look at orientation parameters and who and what rotates. It may be that the app rotates but CCDirector doesn't receive the rotation flag).
you can rotate the CCDirector view with CGAffineTransformRotate (i'm not sure..but because CCDirector is a subclass of UIViewController..it should work).
I solved the issue by creating a UINavigationController
- (void)switchToScene:(CCScene *)sceneObj
{
navController_ = [[UINavigationController alloc] initWithRootViewController:director_];
[window_ setRootViewController:navController_];
[[CCDirector sharedDirector] pushScene:sceneObj];
}

Prevent shutter animation from appearing full screen when using cameraOverlayView [duplicate]

I have a transparent view with a rectangle drawn onto it using CoreGraphics.
When the camera launches the custom overlay view is above the shutter animation.
What you see is the standard camera shutter with the custom rectangle above it.
How do I get it to go in the right place, underneath the shutter animation? I've looked at other sample code but it's for OS 3.1 and doesn't seem to do anything differently.
Here's my code:
-(IBAction)cameraButton{
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerCameraDeviceRear]){
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
//Add the OverlayView with the custom Rectangle
CGRect overlayFrame = CGRectMake(0.0f, 0.0f, 320.0f, 480.0f);
OverlayView *overlayView = [[OverlayView alloc]initWithFrame:overlayFrame];
picker.cameraOverlayView = overlayView;
[overlayView release];
[self presentModalViewController:picker animated:YES];
[picker release];
}
}
On the iPad this problem doesn't exist, and the overlay view is behind the shutter animation by default. But on the iPhone, the overlay appears at front.
I've found a solution that worked for me.
You have to set your overlay view as a subview in this method:
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
if (!viewController)
return;
UIView* controllerViewHolder = viewController.view;
UIView* controllerCameraView = [[controllerViewHolder subviews] objectAtIndex:0];
UIView* controllerPreview = [[controllerCameraView subviews] objectAtIndex:0];
[controllerCameraView insertSubview:self.overlayView aboveSubview:controllerPreview];
}
Hope it helps
Original source:
http://www.alexcurylo.com/blog/2009/06/18/uiimagepickercontroller-in-3-0/
You may not do anything else other than what you're already doing; if iOS decides to put your overlay view over the shutter, you'll just have to live with it (unless you want to risk getting rejected from the app store).
As an imperfect workaround, you could start your overlay with alpha=0 and then set alpha to 1 a second or two later. But there is no set time period that the shutter appears for before 'opening' (I think it depends on how long it takes to initialize the camera hardware), so sometimes your interface might not appear until late and sometimes might appear too early.
As of 4.3.3, the shutter animation is broken because elements are displayed on top, and then snap underneath when the animation starts. I've filed this as a Radar: http://openradar.appspot.com/radar?id=1204401
I answered a similar question here. What worked for me (in iOS 6) was setting the cameraOverlayView in navigationController:willShowViewController:animated.
- (void) navigationController:(UINavigationController*) navigationController willShowViewController:(UIViewController*) viewController animated:(BOOL) animated {
self.imagePickerController.cameraOverlayView = ...; // your camera overlay view
}

Camera Shutter shows up in front of custom UIView?

I have a custom UIView that I have created to display my custom buttons and toolBar. When I first called for it to show, the bar is on top of the Shutter (which is good). But after the camera is loaded, the shutter comes in front of it, then opens.
If you look at the native camera.app, it doesn't do this. The toolbar stays there the whole time. Here is my code:
// .h
UIImagePickerController *theCamera;
#property (nonatomic, retain) UIImagePickerController *theCamera;
// .m
theCamera = [[UIImagePickerController alloc] init];
theCamera.delegate = self;
theCamera.sourceType = UIImagePickerControllerSourceTypeCamera;
theCamera.showsCameraControls = NO;
theCamera.toolbar.alpha = 0;
theCamera.navigationBarHidden = YES;
theCamera.toolbarHidden = YES;
theCamera.wantsFullScreenLayout = YES;
theCamera.cameraViewTransform = CGAffineTransformMakeScale(1.25, 1.25);
UIImageView *tabBarBack = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"tab_bar_back.png"]];
tabBarBack.frame = CGRectMake(0, 422, 320, 58);
[customView addSubview:tabBarBack];
theCamera.cameraOverlayView = customView;
[self presentModalViewController:theCamera animated:YES];
Obviously there are more buttons I add to the customView, but you get the concept.
Subscribe to:
AVCaptureSessionDidStartRunningNotification
This is when the iris open animation begins. If you add a cameraOverlayView during this time, it will be properly covered up by the iris. It is posted at the same time as that PL… private notification. This is a documented approach that does not risk app rejection.
AFAIK there is no direct way to do this. If you use cameraOverlay, you will get shutter for the complete screen.
How ever there are some alternate methods (playing around with the view hierarchy) that will help you in making your preview screen as parent view. I am not sure if this approach is correct as per app store guidelines.
have a look at Hide/Show iPhone Camera Iris/Shutter animation for better understanding on how to achieve this.
On iOS 6+, if you've added your controller as the delegate for the UIImagePickerController, this code should ensure that the shutter stays behind your cameraOverlayView:
- (void) navigationController:(UINavigationController*) navigationController willShowViewController:(UIViewController*) viewController animated:(BOOL) animated {
self.imagePickerController.cameraOverlayView = ...; // your camera overlay view
}
I haven't tested on versions of iOS prior to iOS 6 though.