Scene not changing in SpriteKit - ios

I've created a game and now I want to add a start screen in which I want to run a video and after that there will be a screen with start button, I've searched over internet but couldn't find out the way to do it, have tried many things, the latest code is:
#import "FirstScreen.h"
#import "GameScene.h"
#import <MediaPlayer/MediaPlayer.h>
#implementation FirstScreen
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
NSURL *url =[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"Intro" ofType:#"mp4"]];
_player = [[MPMoviePlayerController alloc] initWithContentURL:url];
_player.view.frame = CGRectMake(0,0, 1024, 768);
[self.view addSubview:_player.view];
_player.shouldAutoplay = YES;
[_player prepareToPlay];
NSString *nextSceneButton;
nextSceneButton = #"Start";
SKLabelNode *myLabel = [SKLabelNode labelNodeWithFontNamed:#"Chalkduster"];
myLabel.text = nextSceneButton;
myLabel.fontSize = 30;
myLabel.fontColor = [SKColor blackColor];
myLabel.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
myLabel.name = #"Start";
[self addChild:myLabel];
}
return self;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
/* Called when a touch begins */
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:location];
if ([node.name isEqualToString:#"Start"]) {
SKTransition *reveal = [SKTransition fadeWithDuration:3];
GameScene *scene = [GameScene sceneWithSize:self.view.bounds.size];
scene.scaleMode = SKSceneScaleModeAspectFill;
[self.view presentScene:scene transition:reveal];
}
}
#end
App just starts and give the SIGABRT error. Can you tell me how to do it?

You should check few things to make sure is everything okay there:
Check if everything is okay with file name, look for spaces or typos etc...
See what pathForResource returns (println it)
See what fileURLWithPath returns
Go to : Target -> Build Phases -> Copy Bundle Resources and add Intro.mp4 file there. If that file is already added , delete it, clean your project Project->Clean, and add it again. Build project and run it.

Related

SpriteKit problems with SKScene

I have performance problems using iOS Sprite kit.
I did the main scene of the game and every thing run nice and smoothly, then I inserted a splash windows in the beginning and when I change the scene to the main scene the game seems laggy with frame drop, but fps, cpu and memory parameters are Ok.
I also have a game over screen and the behaviour is the same, when the game return to the main scene looks very laggy.
I have tried with [self removeFromParents] and removing children, and nothing happens.
Code:
#implementation Splash
- (id) initWithSize:(CGSize)size
{
if (self = [super initWithSize:size]) {
SKSpriteNode *sprite= [SKSpriteNode spriteNodeWithImageNamed:#"main"];
sprite.position = CGPointMake(160,284);
[self addChild:sprite];
}
return self;
}
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// Transition back to the Game
SKScene *myScene = [[MyScene alloc] initWithSize:self.size];
SKTransition *reveal = [SKTransition fadeWithDuration:0.5];
[self.view presentScene:myScene transition:reveal];
[self removeAllChildren];
[self removeAllActions];
[self removeFromParent];
}
#end

UITouch methods in an object not working properly

I have got a SKScene name “Scene” in which I instantiate 2 objects of my class “Button” subclass of SKNode.
In order to not multiply the number of lines of code in my SKScene, I wanted to implemente the touch methods directly in my class “Button”.
Here is the code :
Scene.h
#import <SpriteKit/SpriteKit.h>
#interface Scene : SKScene
#end
Scene.m
#import "Scene.h"
#import "Button.h"
#implementation Scene
- (id)initWithSize:(CGSize)size
{
if (self = [super initWithSize:size])
{
Button *button01 = [Button node];
[button01.number setString: #"1"];
button01.position = CGPointMake(CGRectGetMidX(self.frame) - 50, 160);
Button *button02 = [Button node];
[button02.number setString: #"2"];
button02.position = CGPointMake(CGRectGetMidX(self.frame) + 50, 160);
[self addChild:button01];
[self addChild:button02];
}
return self;
}
#end
Button.h
#import <SpriteKit/SpriteKit.h>
#interface Button : SKNode
#property (strong, nonatomic) NSMutableString *number;
#end
Button.m
#import "Button.h"
SKShapeNode *button;
#implementation Button
- (id)init
{
if (self = [super init])
{
self.userInteractionEnabled = YES;
_number = [[NSMutableString alloc] init];
[_number setString: #"0"];
button = [SKShapeNode node];
[button setPath:CGPathCreateWithRoundedRect(CGRectMake(-25, -25, 50, 50), 4, 4, nil)];
button.fillColor = [SKColor clearColor];
button.lineWidth = 1.0;
button.strokeColor = [SKColor whiteColor];
button.position = CGPointMake(0, 0);
SKLabelNode *label = [SKLabelNode labelNodeWithFontNamed:#"Arial"];
label.text = _number;
label.fontSize = 20;
label.verticalAlignmentMode = SKLabelVerticalAlignmentModeCenter;
label.position = CGPointMake(0, 0);
label.fontColor = [SKColor whiteColor];
[button addChild:label];
[self addChild:button];
}
return self;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch * touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
if(CGRectContainsPoint(button.frame, location))
{
button.fillColor = [SKColor whiteColor];
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
button.fillColor = [SKColor clearColor];
}
#end
The problem is when I touch inside the button01, it’s the button02 color’s which change. As if the action is only apply on the last instance of my class.
How can I fixe this.
Thanks in advance.
The issue is the following variable has global scope in your Button class:
SKShapeNode *button;
Since it is shared among the instances of Button, it contains a reference to the SKShapeNode of the last Button that was instantiated. In this case, button 2. You can resolve this issue by defining button as an instance variable:
#implementation Button
{
SKShapeNode *button;
}
...
For some reasons your Button has SKNode as a superclass. SKNode doesn't have a size property, which you can change, so it takes the whole size of it's parent node. Consider it as a layer of the scene. So wherever you touch, the latest SKScene's child (which is button02 in your case) will receive the touch.
Solution: Define Button as a subclass of SKShapeNode directly.

App freezes for some seconds when presenting UIActivityView or when presenting a second SKScene

When I press the play Button or Share Button the app freezes, but only the first time.
After the first time it runs without a freeze.
The Duration of the freeze is 2-4 seconds.
I tried for awhile to find a solution, but everything I try does not work.
GameViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
SKView * skView = (SKView *)self.view;
SKScene * scene = [Menu sceneWithSize:skView.bounds.size];
scene.scaleMode = SKSceneScaleModeAspectFill;
[skView presentScene:scene];
}
- (void) openShare
{
int highScore = [self highScoreAbruf];
NSString *shareText= [NSString stringWithFormat:#"The HIghScore is %i", highScore];
NSArray *itemsToShare = #[shareText];
UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:itemsToShare applicationActivities:nil];
[self presentViewController:activityVC animated:YES completion:nil];   
}
- (int) highScoreAbruf
{
NSUserDefaults *myHighScore = [NSUserDefaults standardUserDefaults];
int highScore = [myHighScore integerForKey:#"Score"];
return highScore;
}
Menu.m
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:location];
if ([node.name isEqualToString:#"PlayButton"])
{
PlayButton.hidden = YES;
PlayButtonPressed.hidden = NO;
[self restartButtonPressed];
//[self performSelector:#selector(restartButtonPressed) withObject:nil afterDelay:(0.5)];
}
if ([node.name isEqualToString:#"ShareButton"])
{
ShareButton.hidden = YES;
ShareButtonPressed.hidden = NO;
NSTimer *buttonTimer = [NSTimer scheduledTimerWithTimeInterval:(0.5)
target:self
selector:#selector(ShareMethod)
userInfo:NULL
repeats:NO];
}
}
- (void) restartButtonPressed
{
[self.scene.view presentScene:[GameMyScene sceneWithSize:self.size]];
}
- (void) ShareMethod
{
GameViewController *vc = self.view.window.rootViewController;
[vc openShare];
}

no visible #interface for 'Player' declares the selector 'walkRight'

// Player.m
#import "Player.h"
#implementation Player
+(id)player{
Player *player = [Player spriteNodeWithColor:[UIColor brownColor] size:CGSizeMake(32, 32)];
player.name = #"player";
player.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:player.size];
return player;
}
- (void)walkRight {
SKAction *incRight = [SKAction moveByX:10 y:0 duration:0];
[self runAction:incRight];
}
#end
// MyScene.h
#import "MyScene.h"
#import "Player.h"
#implementation MyScene
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
/* Setup your scene here */
self.anchorPoint = CGPointMake(0.5, 0.5);
self.backgroundColor = [SKColor colorWithRed:0.15 green:0.15 blue:0.3 alpha:1.0];
SKSpriteNode *ground = [SKSpriteNode spriteNodeWithColor:[UIColor greenColor] size:CGSizeMake(self.frame.size.width, 30)];
ground.position = CGPointMake(0, -self.frame.size.height/2 + ground.frame.size.height/2);
ground.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:ground.size];
ground.physicsBody.dynamic = NO;
[self addChild:ground];
Player *player = [Player player];
[self addChild:player];
}
return self;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
Player *player = (Player *)[self childNodeWithName:#"player"];
[player walkRight];
}
-(void)update:(CFTimeInterval)currentTime {
/* Called before each frame is rendered */
}
#end
I'm quite new to objective-c. Well I tried to build the above code and got the error "no visible #interface for 'Player' declares the selector 'walkRight'"
I really do not know why. I would really appreciate it if someone could help me. Thank you.
Make sure you've declared the walkRight method in your Player.h file. This should go somewhere after your interface declaration in that file:
-(void)walkRight;
That allows other files that import Player.h to know that Player.m implements the walkRight method.
Change your player method to return instancetype instead of id. This will make the warning go away. Also declare the walkRight method in the header (.h) file of your Player class.
+(instancetype)player{
Player *player = [Player spriteNodeWithColor:[UIColor brownColor] size:CGSizeMake(32, 32)];
....
return player;
}
Read more about instancetype here and here.
Hope that helps!

How to implement "finger-tracing" layer in app like the iOS Simulator

Now that our app has shipped, our person in charge of training has a request:
"The app is cool, but we need a mode showing the movement of the fingers, like how gestures show up in the Simulator or iPad's laser pointer mode in Keynote [so we can capture films]."
This is an app that uses a UITabBarController with xibs for each tab (4). This is a pretty complicated app with interacting gesture recognizers and I was having "first, do no harm" nightmares...
I tried adding a simple "global UIView" above the tab controller using the scheme here: http://www.james-vandyne.com/creating-universal-overlays-using-uiviews-on-ios/
My "PresentationView" attempt:
in my app delegate:
UIWindow *mainWindow = [[UIApplication sharedApplication] keyWindow];
[self setPresentationView:[[PresentationView alloc] initWithFrame: [mainWindow frame]]];
[mainWindow insertSubview:presentationView aboveSubview:mainWindow];
The class:
// PresentationView.h
#import <UIKit/UIKit.h>
#interface PresentationView : UIView
{
NSMutableDictionary *touchesInView;
}
#property (nonatomic, retain) NSMutableDictionary *touchesInView;
#end
#import "PresentationView.h"
#import "TouchPoint.h"
#implementation PresentationView
#synthesize touchesInView;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
[ self setAlpha:0.1];
[self setBackgroundColor:[UIColor whiteColor]];
[self setUserInteractionEnabled:YES];
[self setMultipleTouchEnabled:YES];
touchesInView = [[NSMutableDictionary alloc] init];
}
return self;
}
- (void) dealloc
{
[touchesInView release];
touchesInView = nil;
[super dealloc];
}
- (void)drawRect:(CGRect)rect
{
if ([touchesInView count] < 1)
return;
CGContextRef context = UIGraphicsGetCurrentContext();
NSEnumerator *touchEnum = [touchesInView objectEnumerator];
TouchPoint *nextTouch;
float rad = 24;
while (nextTouch = [touchEnum nextObject]) {
[[ UIColor redColor] set];
CGContextAddArc(context, nextTouch.current.x, nextTouch.current.y, rad, 0.0, M_PI*2, 1);
CGContextFillPath(context);
CGContextStrokePath(context);
}
}
- (UIView *) hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
[self setNeedsDisplay];
return [[[[[UIApplication sharedApplication] keyWindow] subviews] objectAtIndex:0] hitTest:point withEvent:event];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
for( UITouch *t in touches )
{
NSValue *key = [NSValue valueWithPointer:t];
CGPoint loc = [t locationInView:self];
TouchPoint *newTouch = [[TouchPoint alloc] init];
[newTouch setBegan:loc];
[newTouch setCurrent:loc];
[newTouch setTapCount:[t tapCount]];
[touchesInView setObject:newTouch forKey:key];
[newTouch release];
}
[self setNeedsDisplay];
[[[[[UIApplication sharedApplication] keyWindow] subviews] objectAtIndex:0] touchesBegan:touches withEvent:event];
}
// More touch methods- all ignored
This kinda works- the view sits atop all the other views, and hitTest:withEvent: fires, and I was successfully drawing a red circle at the hit point in drawRect:.
But it breaks down when I try to track touches- touchesBegan/Moved/Ended don't fire. (Yes, I have turned on UserInteractionEnabled and setMultipleTouchEnabled for this global view). Fortunately, I haven't screwed up gesture recognition on anything below- the other views are getting events, and the app is behaving normally under this global view.
Normally I use IB to build/locate views and don't build them in code from scratch, so it's very possible there's (a?/several?) simple UIView properties I'm not setting up right... but I can't see it. Or am I going to get myself in trouble with this, trying to forward events down the chain?
There's a good framework called FingerTips that does this.
It's also easy to implement and it only shows the circles if there is an external display so you are presenting it.

Resources