Error: No Known Class method for selector 'addChild' - ios

So, I created a new class named 'Level1Class' and I made a method named 'level1Layout'. In that method I created a SKSprite named 'level1ButtonRed' and when I set the position and try to add it by using
[self addChild: level1ButtonRed]
and it gives me the error
"No Known Class method for selector 'addChild'."
#import "Level1Class.h"
#import "GameScene.h"
#implementation Level1Class
+(void) level1Layout{
SKSpriteNode *level1ButtonRed;
level1ButtonRed = [SKSpriteNode spriteNodeWithImageNamed:#"LevelButton_Red"];
level1ButtonRed.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
[self addChild: level1ButtonRed];
}
#end
#import "GameScene.h"
static NSString *levelButtonRed = #"levelButtonRed";
#implementation GameScene
SKSpriteNode *trans;
-(void)didMoveToView:(SKView *)view {
/* Setup your scene here */
trans = [SKSpriteNode spriteNodeWithImageNamed:#"Transparent"];
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
/* Called when a touch begins */
for (UITouch *touch in touches) {
CGPoint location = [touch locationInNode:self];
trans.position = location;
[self enumerateChildNodesWithName:#"levelButtonRed" usingBlock: ^(SKNode *node1, BOOL *stop1){
if( [trans intersectsNode:node1]){
[Level1Class level1Layout];
}
}];
} }
-(void)update:(CFTimeInterval)currentTime {
/* Called before each frame is rendered */ }
#end
Level1Class.h
#import <SpriteKit/SpriteKit.h>
#import <Foundation/Foundation.h>
#interface Level1Class : NSObject
-(void) level1Layout;
#end
Any help??

You send that message to self inside +level1Layout. This is a class method. Therefore self points to the class object. You cannot add children to class objects. You can add children to instance objects of that class.
To solve that issue create an instance first and then add the child to that instance.

Related

Multiple data objects by extension using a protocol

I had the great idea to use a a protocol on the UITouch class to extend it with some methods declared in the protocol. The reason of such a construct is to provide the protocol inside a framework to other users that they can send UITouch-similar data objects (Because they can't create a native UITouch object).
The protocol (myProtocol.h) is quite easy:
// myProtocol.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#protocol myProtocol <NSObject>
- (CGFloat) MYPREFIX_radius;
#end
Now i have a simple extension on UITouch using that protocol
// UITouch+MYPREFIX_Extension.h
#import <UIKit/UIKit.h>
#import "myProtocol.h"
#interface UITouch (MYPREFIX_Extension) <myProtocol>
#end
and
// UITouch+MYPREFIX_Extension.m
#import "UITouch+MYPREFIX_Extension.h"
#implementation UITouch (MYPREFIX_Extension)
- (CGFloat) MYPREFIX_radius {
return self.majorRadius;
}
#end
By this everything is good to me. Now I built a touchRecognizer.
// touchRecognizer.h
#import <UIKit/UIKit.h>
#interface touchRecognizer : UITouch
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
#end
In the touchRecognizer.m the problem begins. There I cast the UITouch object to a NSObject by using the protocol.And then I simply want to get access to the newly defined method MYPREFIX_radius and it should give me back the UITouch.major_radius.
// touchRecognizer.m
#import "touchRecognizer.h"
#import "UITouch+MYPREFIX_Extension.h"
#interface touchRecognizer()
#end
#implementation touchRecognizer
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
for(NSObject<myProtocol> *touch in touches) {
NSLog(#"radius %f", touch.MYPREFIX_radius);
}
}
#end
But when I run the code it just gives me the Error
-[UITouch MYPREFIX_radius]: unrecognized selector sent to instance 0x1701887b0
I don't understand it. What do I miss?
Thank you for your help.
I am guessing you forget to add the implementation file (UITouch+MYPREFIX_Extension.m) to your build target

Xcode & Cocos2d: How Can I Set An int Property of a Scene I'm Creating?

in my mainMenu.h/m I have a method that loads up the first scene of my game.
- (void)loadAgainstTheClockMode:(id)sender
{
CCScene *scene = [HelloWorldLayer scene];
[[CCDirector sharedDirector] replaceScene:[CCTransitionZoomFlipX transitionWithDuration:0.2 scene:scene]];
}
As you can see I instantiate the HelloWorldLayer scene, then switch to it.
I'd like to be able to hand over an integer value to the HelloWorldLayer that will later tell it which level file to load up to save me having to repeat all the code for each level if the game.
In my HelloWorldLayer, I have set a property that i thought I'd be able to access when defining the scene...
#interface HelloWorldLayer : CCLayer
+(CCScene *)scene;
#property int levelToLoadUp;
#end
I was hoping to be able to do this when creating the scene...
- (void)loadAgainstTheClockMode:(id)sender
{
CCScene *scene = [HelloWorldLayer scene];
levelToLoadUp = 1;
[[CCDirector sharedDirector] replaceScene:[CCTransitionZoomFlipX transitionWithDuration:0.2 scene:scene]];
}
Could someone please help me achieve this? Thanks...!
you could add a scene constructor like so :
in .h
#interface HelloWorldLayer : CCLayer {
int _levelToLoad;
}
+(CCScene *)sceneAtLevel:(int) levelToLoad;
#end
in .m
+(CCScene*) sceneAtLevel:(int) levelToLoad {
// 'scene' is an autorelease object.
CCScene *scene = [CCScene node];
// 'layer' is an autorelease object.
HelloWorldLayer *layer = [[[HelloWorldLayer alloc] init ] autorelease ];
layer->_levelToLoad = levelToLoad;
// add layer as a child to scene
[scene addChild:layer];
return scene;
}
// override onEnter
-(void) onEnter {
[super onEnter]; // dont forget this when overriding any onSomething of cocos2d
[self loadScene];
}
-(void) loadScene {
// you can use the iVar _levelToLoad and do your 'load' thing
// as function of the level
}
// ps : written for MRC, if you use ARC change the memory stuff.
// pps : not tested, but should be close.

Accessing variables from another class when importing a .ccbi file

I know this topic is covered in a hundred posts here, but I'm having a lot of trouble with this particular instance and cannot figure it out.
Basically, I'm using Spritebuilder to import sprites/nodes into my game. I import a sprite of some specific class in the body of the GameScene class, but I want to be able to define a variable inside of my sprite class, and then edit it from the GameScene class. For example, if my sprite collects a coin inside the GameScene, I want to change the speed of my sprite inside of the update method in the sprite class.
Below is my code, but unfortunately it isn't working. The variable increaseY and increaseX do not appear to be available in my GameScene class. I know this is because I didn't instantiate the Penguin class properly, but I don't know how to properly create an instance of this class while simultaneously importing the .ccbi file of it. The problem line is commented on and has a bunch of ** next to it to easily find it. It's in GameScene.m. I really appreciate the help, been stuck on this for several hours.
Penguin.h
#import "CCSprite.h"
#interface Penguin : CCSprite
{
float xPosition;
float yPosition;
}
#property (nonatomic,assign) float increaseY;
#property (nonatomic,assign) float increaseX;
#end
Penguin.m
#import "Penguin.h"
#implementation Penguin
#synthesize increaseX;
#synthesize increaseY;
- (id)init {
self = [super init];
if (self) {
CCLOG(#"Penguin created");
}
return self;
}
-(void) update:(CCTime)delta
{
self.position = ccp(self.position.x + increaseX,self.position.y + increaseY);
}
#end
GameScene.h
#import "CCNode.h"
#interface GameScene : CCNode
#end
GameScene.m
#import "GameScene.h"
#import "Penguin.h"
#implementation GameScene
{
CCPhysicsNode *_physicsNode;
CCNode *_catapultArm;
CCNode *_levelNode;
CCNode *_contentNode;
}
// is called when CCB file has completed loading
- (void)didLoadFromCCB {
self.userInteractionEnabled = TRUE;
CCScene *level = [CCBReader loadAsScene:#"Levels/Level1"];
[_levelNode addChild:level];
}
// called on every touch in this scene
- (void)touchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
[self launchPenguin];
}
- (void)launchPenguin {
// loads the Penguin.ccb we have set up in Spritebuilder
CCNode* penguin = [CCBReader load:#"Penguin"];
penguin.position = ccpAdd(_catapultArm.position, ccp(16, 50));
[_physicsNode addChild:penguin];
//THE FOLLOWING LINE DOES NOT WORK********************************
penguin.increaseY = 1;
// Gives Error------Property "increaseX" not found on object of type "CCNode *"
self.position = ccp(0, 0);
CCActionFollow *follow = [CCActionFollow actionWithTarget:penguin worldBoundary:self.boundingBox];
[_contentNode runAction:follow];
}
You have to change this line:
CCNode* penguin = [CCBReader load:#"Penguin"];
To this line:
Penguin* penguin = (Penguin*)[CCBReader load:#"Penguin"];
In the old line you were using the compiler was giving you an error because the CCNode class does not have a property called increaseX. increaseX is part of the Penguin class. If you want to access properties of the Penguin class you need to use a cast and let the compiler know, that what you are loading using the CCBReader is actually a Penguin instance.

Use of undeclared identifier 'CCJumpBy'

This is my code
#import "Gameplay.h"
#import <CCActionInterval.h>
#implementation Gameplay {
CCPhysicsNode *_physicsNode;
}
- (void)didLoadFromCCB {
// tell this scene to accept touches
self.userInteractionEnabled = TRUE;
}
- (void)touchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
[self jumpRunner];
}
-(void)jumpRunner {
CCNode *spaceship = [CCBReader load:#"Runner"];
id jump = [CCJumpBy actionWithDuration:1 position:ccp(100, 0)
height:50 jumps:1];
[spaceship runAction:jump];
}
#end
It's telling me
Use of undeclared identifier 'CCJumpBy'
How do I fix this to make it work? I don't know what to do.
Thanx in advance
Import cocos2d and you should resolve the error
#import "cocos2d.h"
You probably need to #import the CCJumpBy class's header file.
Also I notice that you're #importing a .m file, which generally you don't do. You probably want to change your import of CCActionInterval to be the .h file, not the .m file.
CCJumpBy is defined in CCActionInterval.h.
Change your import to
#import <CCActionInterval.h>
And you should resolve this error.

How to add SKSpriteNode from a method into another class?

I'm trying to add a SKSpriteNode one class to another class MainMenu which is a subclass of SKScene. The class I created DumpTruckFramework that defines these methods is a subclass of SKSpriteNode (Which may be the problem?). Below is all the code I am using:
#DumpTruckFramework.h
#import <SpriteKit/SpriteKit.h>
#interface DumpTruckFramework : SKSpriteNode
-(void)createDumpTruckMainBody;
#end
#DumpTruckFramework.m
#import "DumpTruckFramework.h"
#implementation DumpTruckFramework
-(SKNode*)setupDumpTruckMainBody{
SKSpriteNode *mainBody = [SKSpriteNode spriteNodeWithImageNamed:#"Dump_Truck_Main_Body.png"];
mainBody.name = #"";
mainBody.scale = 0.5;
mainBody.position = CGPointMake(300, 400);
return mainBody;
}
-(void)createDumpTruckMainBody{
SKNode *mainBody = [self setupDumpTruckMainBody];
[self addChild:mainBody];
}
#end
Above is the method I use in the MainMenu class to add the mainBody sprite. Maybe the issue could be the [self addChild:mainBody]; code line as self is referring to the DumpTruckFramework class?
#MainMenu.h
#import <SpriteKit/SpriteKit.h>
#interface MainMenu : SKScene
#end
#MainMenu.m
#import "MainMenu.h"
#import "DumpTruckFramework.h"
#implementation MainMenu
-(id)initWithSize:(CGSize)size{
if (self = [super initWithSize:size]){
//[self createMainMenuTitle];
DumpTruckFramework *dumpTruck = [[DumpTruckFramework alloc] init];
[dumpTruck createDumpTruckMainBody];
}
return self;
}
Now what I think is happening is that the method does work but doesn't do what is expected. As the MainMenu scene is what is meant to be displaying the nodes, it's declared to be the "view-able scene".
Hopefully someone can help me resolve this issue, cheers.
You're not adding a sprite node to your scene. You can change createDumpTruckMainBody to:
-(SKNode*)createDumpTruckMainBody{
SKNode *mainBody = [self setupDumpTruckMainBody];
return mainBody;
}
and in your main menu change your code to:
-(id)initWithSize:(CGSize)size{
if (self = [super initWithSize:size]){
//[self createMainMenuTitle];
DumpTruckFramework *dumpTruck = [[DumpTruckFramework alloc] init];
SKNode *node = [dumpTruck createDumpTruckMainBody];
[self addChild: node];
}
return self;
}
Hope this helps.
You can add the dumpTruck to MainScene: [self addChild: dumpTruck];.
What's happening is you are creating an instance of DumpTruckFramework which almost immediately goes out-of-scope, and is therefore destroyed:
-(id)initWithSize:(CGSize)size{
if (self = [super initWithSize:size]){
DumpTruckFramework *dumpTruck = [[DumpTruckFramework alloc] init];
[dumpTruck createDumpTruckMainBody];
// dumpTruck destroyed here
}
return self;
}
So your issue is one of scope. Looks like you need to use an instance variable to maintain the DumpTruckFramework.

Resources