Cocos2d Displaying a Layer Issue - cocos2d-iphone

I'm trying to display a pause game layer from the applicationDidEnterBackground: method and for some reason it does call the method but nothing happens.
Delegate
- (void)applicationDidEnterBackground:(UIApplication*)application {
ship = [[Ship alloc] init];
[ship pause];
Pause Method
- (void)pause
{
BOOL isPaused = [[CCDirector sharedDirector] isPaused];
if(!isPaused)
{
//Pause the game
ccColor4B c = {100,100,0,100};
PauseLayer *pauseLayer = [[[PauseLayer alloc] initWithColor:c] autorelease];
[self.leftMenuItem setIsEnabled:NO];
[self.rightMenuItem setIsEnabled:NO];
[self.fireMenuItem setIsEnabled:NO];
[self addChild:pauseLayer z:10 tag:100];
[[CCDirector sharedDirector] pause];
}
}
PauseLayer
+ (id)scene
{
CCScene *scene = [CCScene node];
PauseLayer *layer = [PauseLayer node];
[scene addChild:layer];
return scene;
}
- (id)initWithColor:(ccColor4B)color
{
if((self = [super initWithColor:color]))
{
self.isTouchEnabled = YES;
[CCMenuItemFont setFontName:#"Marker Felt"];
[CCMenuItemFont setFontSize:40];
CCMenuItemFont *resumeGameItem = [CCMenuItemFont itemFromString:#"Resume" target:self selector:#selector(resumeGame)];
CCMenuItemFont *menuGameItem = [CCMenuItemFont itemFromString:#"Menu" target:self selector:#selector(goToGameMenu)];
CCMenu *menu = [CCMenu menuWithItems:resumeGameItem,menuGameItem,nil];
[menu alignItemsVerticallyWithPadding:40.00];
[self addChild:menu];
}
return self;
}
Thanks!

If you init the ship in the delegate, it isn't added to any cocos layer that I can see. you would have to get a reference to the current scene and add the ship to it (assuming ship is a sub-class of Cocos node).

Related

Refresh game scene in cocos2d

Hey folks I've being working around as follows. I get 2 layers, one's for control and the other's for game stuff. The problem is that the game's stucked ( the game's scene is refreshed and showed but it's out of control) when I trigerred a function for restart from my control layer. Have no idea where the problem is.
//restart function from input layer
......
-(id) init
{
if ((self = [super init]))
{......}
return self;
}
......
-(void)restart
{
GameScene* game = [GameScene sharedGameScene];
[game restartScene];
}
//gameLayer
......
static GameScene* instanceOfGameScene;
#implementation GameScene
+(GameScene*) sharedGameScene
{
if(instanceOfGameScene == nil)
instanceOfGameScene = [[self alloc]init];
return instanceOfGameScene;
}
+(id) scene
{
CCScene* scene = [CCScene node];
GameScene* layer = [GameScene node];
[scene addChild:layer z:0];
InputLayer* inputLayer = [InputLayer node];
[scene addChild:inputLayer z:1];
return scene;
}
-(void) restartScene
{
CCScene * newScene = [GameScene scene];
[[CCDirector sharedDirector] replaceScene:\
[CCTransitionFade transitionWithDuration:0.7f scene:newScene]];
}
......
[scene:newScene] does not seem to be valid ObjC syntax, does this even compile?
Anyway, you'll want to use newScene there and nothing else:
-(void) restartScene
{
CCScene * newScene = [GameScene scene];
[[CCDirector sharedDirector] replaceScene:newScene];
}

Cocos2d - Alternative for CCNode userData

I am using CCNode userData property to define whether a touched sprite has had a node built upon it (using Ray Wenderlich's - Tower Defence Tutorial).
The problem I am having is that for every new sprite position I touch and build upon, the previous ones are not retained in the sense that I am unable to sell the building built on it using my sell method.
What is the best way to save data to an individual CCSprite that is selected by touch, and defined by a property through a for loop?
I have read that subclassing CCSprite is an option, or creating a struct for userData etc. I have tried to implement these strategies but have been unsuccessful getting them to work.
touch method with sprite property:
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
for(UITouch *touch in touches){
CGPoint location = [touch locationInView:[touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
for(CCSprite *tb in self.BuildPositions){
//BuildPositions contains CCSprites from a class defining build positions and contained in a mutable array.
if(CGRectContainsPoint([tb textureRect],[tb convertToNodeSpace:location ])){
_selectedBuildPosition = tb;
[self buildMenuTapped];
}
}
}
}
build menu method:
-(void)buildMenuTapped{
[self removeChild:_buildSelectMenu cleanup:YES];
[self removeChild:_sellBuildingMenu cleanup:YES];
if (_selectedBuildPosition.userData == nil) {
CCMenuItem *buildOption = [CCMenuItemImage itemWithNormalImage:#"building.png" selectedImage:#"building.png" target:self selector: #selector(buildOption)];
buildOption.position = ccpAdd(_selectedBuildPosition.position,ccp(0,40));
_buildSelectMenu = [CCMenu menuWithItems:BuildOption, nil];
_buildSelectMenu.position = CGPointZero;
[self addChild:_buildSelectMenu z:100];
}else{
[self sellBuildingMenu];
}
}
build upon method:
-(void)buildOption{
if([self canBuyBuilding] && !_selectedBuildPosition.userData){
_playerEssence -= kBUILD_COST;
_lvl1BuildNodeInstance = [lvl1BuildNode nodeWithTheGame:self location:_selectedBuildPosition.position];
//method as seen in RW tutorial. Generates a lvl1BuildNode class node within the HelloWorldLayer.
_selectedBuildPosition.userData = (__bridge void*)(_lvl1BuildNodeInstance);
}
}
sell menu method:
-(void)sellBuildingMenu{
[self removeChild:_buildSelectMenu cleanup:YES];
[self removeChild:_sellBuildingMenu cleanup:YES];
CCMenuItem *buildingSell = [CCMenuItemImage itemWithNormalImage:#"sell.png" selectedImage:#"sell.png" target:self selector:#selector(sellBuilding)];
buildingSell.position = ccpAdd(_selectedBuildPosition.position,ccp(40,0));
_sellBuildingMenu = [CCMenu menuWithItems:buildingSell, nil];
_sellBuildingMenu.position = CGPointZero;
[self addChild:_sellBuildingMenu z:100];
}
sell method:
-(void)sellBuilding{
if (_selectedBuildPosition.userData == (__bridge void*)(_lvl1BuildNodeInstance)){
[self removeChild:_lvl1GemNodeInstance cleanup:YES];
[_buildings removeObject:_lvl1BuildNodeInstance];
_playerEssence += kBUILD_COST;
_selectedBuildPosition.userData = nil;
}else{
}
}
Thank you for your time.

Issue with selecting level form Level Selection screen (Cocos2d + box2d)

having menu item in level selection screen and depending on selected item level is started ... here is code..where selectedLevel is index of menuItem.
if(selectedLevel==0)
{
activeScene = [level2_1Scene node];
[[CCDirector sharedDirector] pushScene:activeScene];
}
else if(selectedLevel==1)
{
activeScene = [level2_2Scene node];
[[CCDirector sharedDirector] pushScene:activeScene];
}
else if(selectedLevel==2)
{
activeScene = [level2_3Scene node];
[[CCDirector sharedDirector] pushScene:activeScene];
... so on for all level
how can i do it with simple format of level scene name something like this which is not working
activeScene = [[NSString stringWithFormat:#"level2_%d",selectedLevel+1] node];
[[CCDirector sharedDirector] pushScene:activeScene];
this snippet from one of my factories can probably do your trick after adaptation:
Skill *skkk = (Skill *) NSClassFromString(className);
if (skkk) {
return (Skill *) [[skkk class] skillWithSpec:ss];
} else {
MPLOGERROR(#"*****************************************************************");
MPLOGERROR(#" no class with name %#", className);
MPLOGERROR(#"*****************************************************************");
return nil;
}
this worked for me,,,
NSString *level=[NSString stringWithFormat:#"level2_%dScene",selectedLevel+1];
Class sceneClass = NSClassFromString(level);
activeScene = (bunnyScene*)[sceneClass node] ;
[[CCDirector sharedDirector] replaceScene:activeScene];
I think this may be what you are looking for:
switch(selectedLevel)
{
case 0:
activeScene = [level2_1Scene node];
break;
case 1:
activeScene = [level2_2Scene node];
break;
// Etc....
}
if(activeScene) {
[[CCDirector sharedDirector] replaceScene:activeScene];
}

Code Refactoring issue

I have game ready and now I am trying to refactor code. I have derived Spider class from CCNode and used targeted delegate method CCTargetedTouchDelegate.
#interface Spider : CCNode<CCTargetedTouchDelegate> {
CCSprite* spiderSprite;
NSString * spiderKilled;
int killed;
AppDelegate *del;
}
+(id) spiderWithParentNode:(CCNode*)parentNode;
-(id) initWithParentNode:(CCNode*)parentNode;
#end
On Touch spider should be killed and here goes the code:
-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint tch = [touch locationInView: [touch view]];
CGPoint touchLocation = [[CCDirector sharedDirector] convertToGL:tch];
// Check if this touch is on the Spider's sprite.
BOOL isTouchHandled = CGRectContainsPoint([spiderSprite boundingBox], touchLocation);
if (isTouchHandled)
{
j = j + 1;
killed ++;
[del setKilledScore:j];
[self removeChild:spiderSprite cleanup:YES];
}
return isTouchHandled;
}
I am adding 10 spiders in GameScene layer using: -
for(int i=0; i <10 ;i++){
[Spider spiderWithParentNode:self];
}
But, unfortunately I am not able to remove spiders and giving me EXC_BAD_ACCESS error on this line: [self removeChild:spiderSprite cleanup:YES];
Please help me overcome this error.
Thanks
Update --
Spider Init code
// Static autorelease initializer, mimics cocos2d's memory allocation scheme.
+(id) spiderWithParentNode:(CCNode*)parentNode
{
return [[[self alloc] initWithParentNode:parentNode] autorelease];
}
-(id) initWithParentNode:(CCNode*)parentNode
{
if ((self = [super init]))
{
[parentNode addChild:self];
del = [[UIApplication sharedApplication] delegate];
CGSize screenSize = [[CCDirector sharedDirector] winSize];
spiderSprite = [CCSprite spriteWithFile:#"spider.png"];
spiderSprite.position = CGPointMake(CCRANDOM_0_1() * screenSize.width, CCRANDOM_0_1() * screenSize.height);
[self addChild:spiderSprite];
// Manually add this class as receiver of targeted touch events.
[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:-1 swallowsTouches:YES];
}
return self;
}
If you manually add the class to the CCTouchDispatcher list, you should remove it from there after you're done using it.

how to do a function for a sprite or menu in cocos2d?

I created two CCLayers, one is gamelayer, another is howlayer. The code of gamelayer.m is
-(id)init{
if (self = [super init]) {
CCSprite *gamebg = [CCSprite spriteWithFile:#"bg.png"];
gamebg.anchorPoint = CGPointZero;
[self addChild:gamebg z:0 tag:1];
HowLayer *howLayer = [HowLayer node];
[self addChild:howLayer];
[self schedule:#selector(showthegamecontent:) interval:0.4];
}
return self;
}
the code of howlayer is
-(id)init{
if (self=[super init]) {
CCSprite *howbg = [CCSprite spriteWithFile:#"translucentbg.png"];
howbg.anchorPoint = CGPointZero;
[self addChild:howbg z:5 tag:1];
CCMenuItem *howmenu = [CCMenuItemImage itemFromNormalImage:#"how.png"
selectedImage:#"how.png"
target:self
selector:#selector(startgame:)];
CCMenu *ccMenuhowmenu = [CCMenu menuWithItems:howmenu, nil];
ccMenuhowmenu.position=ccp(517,384);
[self addChild:ccMenuhowmenu z:5 tag:2];
}
return self;
}
-(void)startgame:(id)sender{
[self removeAllChildrenWithCleanup:YES];
}
I want to do function like this:
When I click the menu on howlayer, the Howlayer will be removed (I have done), and then the game starts, calls the selector 'showthegamecontent', so how should I do?
Simple hack in your howlayer:
-(void)startgame:(id)sender{
gameLayer* parent = (gameLayer*) self.parent;
[parent showthegamecontent];
}
but it may leave you with a warning.. But it works..
The implementation without warning is that you have to store a reference to the parent with you init. Which i feel its unnecessary as you only need to reference it once.