Methods in another scene not called - objective-c

The 'thePlay' gets presented but does not display the redColor background. It remains black. Can someone advice on what I am supposed to do.
More Clarification: All the scenes and quickMenu class are imported on each other
This method execute transition from this scene(gameScene) using a button in quickMenu class (subclass of SKNode)
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch *touch in touches){
if (self.gameEnded && quickMenu.touchable) {
SKNode *theNode = [quickMenu nodeAtPoint:[touch locationInNode:quickMenu]];
if ([theNode.name isEqualToString:#"theMenu"]){
SKScene *thePlay = [[SKScene alloc] initWithSize:self.size];
SKTransition *doors = [SKTransition doorsOpenHorizontalWithDuration:1.0];
[self.view presentScene:thePlay transition:doors];
}
}
}
}
this is the first method in another scene (thePlay scene),
-(void)didMoveToView:(SKView *)view
{
self.backgroundColor = [SKColor redColor];
NSLog(#"this method called");
}
I tried the init method, did not show the redColor background as well, as shown below...
-(id)initWithSize:(CGSize)size
{
if (self = [super initWithSize:size]) {
self.backgroundColor = [SKColor redColor];
NSLog(#"init method called");
}
Am I missing something?

Related

initWithCoder not working as expected in Xcode 6?

I am using Sprite Kit engine. I used to write code in initWithSize but since the update, initWithSize is not called automatically, instead viewDidLoad is called. I got to know that instead of initWithSize, initWithCoder had to be used, so i changed the code from:
-(id) initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
self.backgroundColor = [SKColor blueColor];
SKSpriteNode *paddle = [SKSpriteNode spriteNodeWithImageNamed:#"paddle"];
paddle.position = CGPointMake(150, 100);
paddle.physicsBody.dynamic = NO;
[self addChild:paddle];
}
return self;
}
to:
-(instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
self.backgroundColor = [SKColor blueColor];
SKSpriteNode *paddle = [SKSpriteNode spriteNodeWithImageNamed:#"paddle"];
paddle.position = CGPointMake(150, 100);
paddle.physicsBody.dynamic = NO;
[self addChild:paddle];
}
return self;
}
Now, the color of the scene turns blue, but i am not able to add sprites to the scene. Neither do I get any error while building.
Are there some changes that I should make in initWithCoder? (If yes, please specify and elaborate)
Can initWithCoder be used with EXACTLY the same code as we did in initWithSize?
PS: Heres the full code I have in GameScene.m and I do not have any other scene.
#import "GameScene.h"
#implementation GameScene
-(void)didMoveToView:(SKView *)view {
/* Setup your scene here */
}
-(instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
SKSpriteNode *paddle = [SKSpriteNode spriteNodeWithImageNamed:#"paddle"];
paddle.position = CGPointMake(150, 100);
paddle.physicsBody.dynamic = NO;
[self addChild:paddle];
}
return self;
}
-(void)update:(CFTimeInterval)currentTime {
/* Called before each frame is rendered */
}
#end
And I just copied and pasted the code from initWithSize to initWithCoder. It doesn't seem to create the paddle object.
Please help!
It may be a method signature mismatch?
Instead of instancetype it is defined as: - (id)initWithCoder:(NSCoder *)decoder
I was just looking up if I could have the type safety of instance type in my keyed coding implementations and found your question.
Others say it works. It would be worth a test.
Why does initWithCoder not return instancetype?

Implementing Game Center with Sprite Kit

I'm unable to implement Game Center into my SpriteKit game.
Most tutorials I've screen require a ViewDidLoad which my game does not have.
I am unable to find correct code to Authenticate my game, or it could be that I have the correct code but am placing it in the wrong area of my application.
Currently I have placed the Authentication in the initWithSize:
#import <GameKit/GameKit.h>
#interface GameScene ()
...
#implementation GameScene
...
-(id)initWithSize:(CGSize)size { /* Setup your scene here */
if (self = [super initWithSize:size]) {
self.anchorPoint = CGPointMake(0.5,0.5);
self.physicsWorld.contactDelegate = self;
...
...
**(I HAVE BEEN PLACING AUTHENTICATE CODE FOUND ON INTERNET HERE, BUT NOTHING FOUND TO BE WORKING)**
}
return self;
}
The below code is where I have a UILabel node called "Leaderboards" where I want my player to be able to click, and enable the user to login to game center and view the leaderboards, along with his own score.
(When clicked currently, it says "Game Center Unavailable, Player not signed in", and then after clicking OK, the user is unable to return to the game, but is left with the game screen frozen?)
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:location];
//if fire button touched, bring the rain
if ([node.name isEqualToString:#"LBButtonNode"]) {
NSLog(#"leader boards opened");
GKLeaderboardViewController *leaderboardController = [[GKLeaderboardViewController alloc] init];
if (leaderboardController != NULL)
{
leaderboardController.timeScope = GKLeaderboardTimeScopeAllTime;
leaderboardController.leaderboardDelegate = self;
GKGameCenterViewController *gameCenterController = [[GKGameCenterViewController alloc] init];
if (gameCenterController != nil)
{
gameCenterController.viewState = GKGameCenterViewControllerStateLeaderboards;
UIViewController *vc = self.view.window.rootViewController;
[vc presentViewController: gameCenterController animated: YES completion:nil];
}
}
}
else if(!self.isStarted) {
[self start];
}
else if (self.isGameOver) {
[self clear];
}
else if (self.isStarted) {
[hero jump];
}
}
How do I correctly implement the Game Center feature using SpriteKit?

Animating custom property

I'm trying to animate a custom property, and as I've seen on several sources it seems this would be the way to go, but I'm missing something. Here's the CALayer subclass:
#implementation HyNavigationLineLayer
#dynamic offset;
- (instancetype)initWithLayer:(id)layer
{
self = [super initWithLayer:layer];
if (self) {
HyNavigationLineLayer * other = (HyNavigationLineLayer*)layer;
self.offset = other.offset;
}
return self;
}
-(CABasicAnimation *)makeAnimationForKey:(NSString *)key
{
// TODO
return nil;
}
- (id<CAAction>)actionForKey:(NSString *)event
{
if ([event isEqualToString:#"offset"]) {
return [self makeAnimationForKey:event];
}
return [super actionForKey:event];
}
+ (BOOL)needsDisplayForKey:(NSString *)key
{
if ([key isEqualToString:#"offset"]) {
return YES;
}
return [super needsDisplayForKey:key];
}
- (void)drawInContext:(CGContextRef)ctx
{
NSLog(#"Never gets called");
}
#end
I believe this is the only relevant method on my view:
#implementation HyNavigationLineView
+ (Class)layerClass
{
return [HyNavigationLineLayer class];
}
#end
And, finally, in my view controller:
- (void)viewDidLoad
{
[super viewDidLoad];
// Instantiate the navigation line view
CGRect navLineFrame = CGRectMake(0.0f, 120.0f, self.view.frame.size.width, 15.0f);
self.navigationLineView = [[HyNavigationLineView alloc] initWithFrame:navLineFrame];
// Make it's background transparent
self.navigationLineView.backgroundColor = [UIColor colorWithWhite:0.0f alpha:0.0f];
self.navigationLineView.opaque = NO;
[[self.navigationLineView layer] addSublayer:[[HyNavigationLineLayer alloc] init]];
[self.view addSubview:self.navigationLineView];
}
The thing is that the drawInContext method is not called at all, although layerClass is. Am I missing something to make the layer draw?
Solved it. Need to call setNeedsDisplay
- (void)viewDidLoad
{
[super viewDidLoad];
// Instantiate the navigation line view
CGRect navLineFrame = CGRectMake(0.0f, 120.0f, self.view.frame.size.width, 15.0f);
self.navigationLineView = [[HyNavigationLineView alloc] initWithFrame:navLineFrame];
// Make it's background transparent
self.navigationLineView.backgroundColor = [UIColor colorWithWhite:0.0f alpha:0.0f];
self.navigationLineView.opaque = NO;
[[self.navigationLineView layer] addSublayer:[[HyNavigationLineLayer alloc] init]];
[self.view addSubview:self.navigationLineView];
[self.navigationLineView.layer setNeedsDisplay];
}

Perform SpriteKit Physics Body Collision/ Contact on touch End

I am having some physics body nodes. Sprite Kit immediately calls didbegincontact method. I want that method should be called when i release the touch so that it may perform actions when click was released instead of calling method immediately causing some action setting problems for me.
- (void)didBeginContact:(SKPhysicsContact *)contact
{ NSLog(#"%hhd", _touching);
if(_touching == NO)
return;
something here
}
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
_touching = YES;
NSLog(#"%hhd", _touching);
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
_touching = NO;
NSLog(#"%hhd", _touching);
something here
}
Set the global Variable, ie
BOOL _touching;
When you touch / release (touches ended and began) you set that var to YES / NO;
In the didbegincontact, use something like
if(_touching == YES) {
// what I want to happen when I am touching
}
else {
// i must not be touching so do this
}
Here is the basic set up - however I think its the game logic thats the issue, maybe think of a different way to solve your problem
#interface XBLMyScene()
#property (strong, nonatomic) SKNode *world;
#property (strong, nonatomic) SKSpriteNode *ball;
#property BOOL touching;
#end
#implementation XBLMyScene
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
self.world = [SKNode node];
[self addChild:self.world];
self.backgroundColor = [SKColor colorWithRed:0.15 green:0.15 blue:0.3 alpha:1.0];
self.physicsBody = [SKPhysicsBody bodyWithEdgeFromPoint:CGPointZero toPoint:CGPointMake(500, 0)];
self.ball = [SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(40, 40)];
self.ball.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(40, 40)];
self.ball.position = CGPointMake(200, 300);
[self.world addChild:self.ball];
self.touching = NO;
}
return self;
}
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
self.touching = YES;
}
-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
self.touching = NO;
}
- (void) didSimulatePhysics
{
if (self.touching) {
NSLog(#"I am touching");
}
else {
NSLog(#"I am not touching");
}
}

UIScrolllView and info button

I have custom UIViewController which looks like this.
#implementation UIViewControllerCustom
- (id)init
{
self = [super init];
if (self) {
NSLog(#"init");
}
return self;
}
-(void)viewDidLoad
{
[super viewDidLoad];
UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeInfoLight];
[infoButton setFrame:CGRectMake(290, 10, 16, 16)];
[infoButton addTarget:self action:#selector(showInfo) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:infoButton];
}
-(void)showInfo
{
About *about = [[About alloc]init];
NSLog(#"touched");
[about setModalTransitionStyle:UIModalPresentationFullScreen];
[self presentModalViewController:about animated:YES];
}
#end
Any view controller in my app inherits this controller. When info button is touched the modal window is present. The problem is that one of my view controllers use UIScrollView. In this controller info button is visible and it reacts on touches. The problem is that when I touch the button showInfo method of UIViewControllerCustom is not called. I have no such a problem in the other controller.
What can be wrong here ?
Because the UIScrollView handles the message being sent. In your case the touch on the button will be handled by the UIScrollView.
I would suggest you to subclass the UIScrollView and implement: - (BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view to determine if the UIScrollView should handle the event or not.
The implementation could be something along the lines of:
- (BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view {
if ([view isKindOfClass:[UIButton class]]) {
return NO;
}
return YES;
}