cocos2d self.touchEnabled = YES not found - objective-c

-(id)init
{
if ((self = [super init]))
{
[self setupTitle];
self.touchEnabeled = YES;
}
return self;
}
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[[CCDirector sharedDirector]
replaceScene:[CCTransitionFade transitionWithDuration:1.0 scene:[GameScene node]]];
CCSprite *start = (CCSprite *)
[self getChildByTag:1]; [start stopAllActions];
start.visible = NO;
}
Cant Get self.touchEnabled = YES; working it gives an error ;
touchEnabled Not found on object type of 'TitleLayer'

In older versions, the code is:
self.touchEnabled = YES;
Try just copying this and putting it in.

This property is called userInteractionEnabled since cocos2d v3.0.
If you're using older version of cocos2d try to fix the typo in your code. The right name for property is touchEnabled.

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?

Methods in another scene not called

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?

cocos2d ccTintTo, implementing an endless changing color label

Instead of writing all those lines at the init method of HelloWorldLayer :
CCTintTo* tint1 = [CCTintTo actionWithDuration:2 red:255 green:0 blue:0];
CCTintTo* tint2 = [CCTintTo actionWithDuration:2 red:0 green:0 blue:255];
....
CCSequence* sequence = [CCSequence actions:tint1, tint2, nil];
[label runAction:sequence];
I tried to make the label change color forever but got stucked:
I don't know where to place the relavant commands+ dealing with the integers x,y,z
I tried to do the randomize process at the update method,but didn't have any access to the label, any ideas?
// HelloWorldLayer.h
// Essentials
//
// Created by Steffen Itterheim on 14.07.10.
// Copyright Steffen Itterheim 2010. All rights reserved.
//
#import "cocos2d.h"
#interface HelloWorld : CCLayer
{
CCTintTo* tint1;
CCSequence* sequence1;
// CCLabelTTF* label; even tried property
}
// returns a Scene that contains the HelloWorld as the only child
+(id) scene;
#end
//
// HelloWorldLayer.m
// Essentials
//
// Created by Steffen Itterheim on 14.07.10.
// Copyright Steffen Itterheim 2010. All rights reserved.
//
#import "HelloWorldScene.h"
#import "MenuScene.h"
integer_t x;
integer_t y;
integer_t z;
#implementation HelloWorld
+(id) scene
{
CCScene* scene = [CCScene node];
CCLayer* layer = [HelloWorld node];
[scene addChild:layer];
return scene;
}
-(id) init
{
if ((self = [super init]))
{
CCLOG(#"init %#", self);
// enable touch input
self.isTouchEnabled = YES;
CGSize size = [[CCDirector sharedDirector] winSize];
// add the "touch to continue" label
CCLabelTTF* label = [CCLabelTTF labelWithString:#"Touch Screen For Awesome" fontName:#"AmericanTypewriter-Bold" fontSize:30];
label.position = CGPointMake(size.width / 2, size.height / 8);
[self addChild:label];
[self schedule:#selector(update:) interval:1/60.0f];
/*
tint1 = [CCTintTo actionWithDuration:2 red:x green:y blue:z];
sequence1 = [CCSequence actions:tint1, nil ];
id goaction=[CCRepeatForever actionWithAction:sequence1];
[label runAction:goaction];
*/
}
return self;
}
-(void) registerWithTouchDispatcher
{
// call the base implementation (default touch handler)
[super registerWithTouchDispatcher];
//[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:INT_MIN+1 swallowsTouches:YES];
}
-(void) update:(ccTime)delta
{
x=(integer_t )(CCRANDOM_0_1()*255); y=(integer_t )(CCRANDOM_0_1()*255); z=(integer_t )(CCRANDOM_0_1()*255);
tint1 = [CCTintTo actionWithDuration:2 red:x green:y blue:z ];
sequence1 = [CCSequence actions:tint1, nil ];
[HelloWorld.label runAction:goaction]; //property label not found on object of type 'HelloWorld'
}
// Touch Input Events
-(CGPoint) locationFromTouches:(NSSet *)touches
{
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [touch locationInView: [touch view]];
return [[CCDirector sharedDirector] convertToGL:touchLocation];
}
-(void) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
}
-(void) ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
CGPoint location = [self locationFromTouches:touches];
CCLOG(#"touch moved to: %.0f, %.0f", location.x, location.y);
}
-(void) ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
// the scene we want to see next
CCScene* scene = [MenuScene scene];
CCTransitionSlideInR* transitionScene = [CCTransitionSlideInR transitionWithDuration:3 scene:scene];
[[CCDirector sharedDirector] replaceScene:transitionScene];
}
-(void) ccTouchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
}
-(void) dealloc
{
CCLOG(#"dealloc: %#", self);
// always call [super dealloc] at the end of every dealloc method
[super dealloc];
}
#end
If you want the tint color to be random for each time, then you cannot use CCTintTo directly inside CCRepeatForever. You need to re-randomize the RGB values for each CCTintTo action. Thus you need to embed the randomization process inside the action by using block. Here is how:
// do this in init method
__block void (^changeTint)(CCNode*) = [[^(CCNode *node) {
GLubyte x = (integer_t)(CCRANDOM_0_1()*255), y = (integer_t)(CCRANDOM_0_1()*255), z = (integer_t)(CCRANDOM_0_1()*255);
[node runAction:[CCSequence actionOne:[CCTintTo actionWithDuration:2 red:x green:y blue:z]
two:[CCCallBlockN actionWithBlock:changeTint]]];
} copy] autorelease];
changeTint(label);
You should look at CCRepeatForever action. As the name implies, it will repeat the action it points to forever. So you should remove your update method where you are changing the colors, and return to the CCSequence code that you had, and embed that in a CCRepeatForever action:
CCTintTo* tint1 = [CCTintTo actionWithDuration:2 red:255 green:0 blue:0];
CCTintTo* tint2 = [CCTintTo actionWithDuration:2 red:0 green:0 blue:255];
....
CCSequence* sequence = [CCSequence actions:tint1, tint2, nil];
CCAction* repeat = [CCRepeatForever actionWithAction:sequence];
[label runAction:repeat];

UIPickerView inside UIScrollView hitTest to disable Scrollview?

I am currently building an application which has a resized UIPickerView on a scrollview the problem I am facing is that when you try to scroll the picker the scrollview is moving instead.
For the past few hours I have tried to fix this by disabling the scrollview when the picker is selected by creating a UIScrollView sub class which performs the following hitTest:
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
UIView* result = [super hitTest:point withEvent:event];
if ([result.superview isKindOfClass:[UIPickerView class]])
{
NSLog(#"Cancel touch");
self.canCancelContentTouches = NO;
self.delaysContentTouches = NO;
self.scrollEnabled = NO;
}
else
{
self.canCancelContentTouches = YES;
self.delaysContentTouches = YES;
self.scrollEnabled = YES;
}
return result;
}
With this above code I find that when I click and hold certain sections of the UIPickerView it cancels the touch and disables the UIScrollview OK and I can move the UIPicker to select a new value, however when I certain areas on the PickerView and do an NSLog on the reported class like below
NSLog(#"%#", [result.superview class]);
It outputs UIPickerTableViewWrapperCell to the console and the isKindOfClass[UIPickerView class] never gets entered.
I have also tried isMemberOfClass which also does not work.
Any help would be appreciated.
Thanks Aaron
I think I have figured this out, by searching the class description to see if it contains #"UIPicker*"
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
UIView* result = [super hitTest:point withEvent:event];
NSString *viewDescription = [result.superview class].description;
NSRange range = [viewDescription rangeOfString : #"UIPicker"];
if (range.location != NSNotFound)
{
NSLog(#"Cancel touch on ScrollView");
self.canCancelContentTouches = NO;
self.delaysContentTouches = NO;
self.scrollEnabled = NO;
}
else
{
self.canCancelContentTouches = YES;
self.delaysContentTouches = YES;
self.scrollEnabled = YES;
}
return result;
}
Now when I drag the UIPicker it works perfectly and the scrollview does not move at all, unless I am clicking on that and dragging it.
Aaron

Cocos2d: CCSprite initWithFile in CCSprite subclass crashes

I have cocos2d project with custom CCSprite subclass:
MyCustomSprite.h:
#import "cocos2d.h"
#interface MyCustomSprite : CCSprite
#end
MyCustomSprite.m:
#import "MyCustomSprite.h"
#implementation MyCustomSprite
- (id)init
{
self = [super initWithFile:#"index.png"];
return self;
}
#end
For some strange reason, this code will crash with "EXC_BAD_ACCESS".
But in spite of this, if i init super as ususal and then write code from CCSprite's initWithFile and initWithTexture, it will work fine:
self = [super init];
if (self) {
// Code from CCSprite.m - initWithFile
CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage: #"index.png"];
CGRect rect = CGRectZero;
rect.size = texture.contentSize;
// Code from CCSprite.m - iniWithTexture
[self setTexture:texture];
[self setTextureRect:rect];
return self;
}
What's the reason that the first example crashes, and second not and what's the difference between them?
Thanks for your answers!
Ok, the reason is bad CCSprite design. If we look to CCSprite.h, we can find:
-(id) initWithTexture:(CCTexture2D*)texture rect:(CGRect)rect
{
NSAssert(texture!=nil, #"Invalid texture for sprite");
// IMPORTANT: [self init] and not [super init];
if( (self = [self init]) )
}
And thats the reason. Instead of [super init] this method calls [self init], and creates recursion ([self init]-[super InitWithFile:]-[self initWithTexture]-[self init]-...).
.
So, the simplest way to solve this problem - just re-name your init method to something else (for example "initialize") and call it instead of init: [[MyCustomSprite
alloc] initialize].
Another approach that may work is just replace your code by this one:
- (id)init
{
self = [super init];
if (self != nil)
{
CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage:#"my_image_name.png"];
CGRect rect = CGRectZero;
if (texture != nil)
{
rect.size = texture.contentSize;
}
[self setDisplayFrame:[CCSpriteFrame frameWithTexture:texture rect:rect]];
}
return self;
}
And a simpler way, if you are using CCSpriteFrameCache, would be just setting the display frame by
[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:#"my_image_name.png"]
Hope to help somebody!