Cocos2d EXC_BAD_ACCESS - ios

I am new to cocos2d and suddenly got this EXC_BAD_ACCESS,
I made a new winning menu and i got the error
I think the error is because i called a released object, but i dont release anything?
My Debug Console had no error, which is strange
here is my Level_1.m
//
// Level_1.m
// iPadGame
//
// Created by My Name on 1/25/12.
// Copyright 2012 __MyCompanyName__. All rights reserved.
//
#import "Level_1.h"
#import "HelloWorldLayer.h"
CCSprite *player;
CCSprite *enemy;
CCSprite *enemy2;
CCSprite *enemy3;
CCSprite *star;
CCSprite *star2;
CCSprite *star3;
CCSprite *bg;
CCSprite *toolBar;
CCLabelTTF *youWin;
bool movePlayer;
#implementation Level_1
#synthesize score;
+(CCScene *) scene {
// 'scene' is an autorelease object.
CCScene *scene = [CCScene node];
// 'layer' is an autorelease object.
Level_1 *layer = [Level_1 node];
// add layer as a child to scene
[scene addChild: layer];
// return the scene
return scene;
}
-(void) setUpWinMenu {
[CCMenuItemFont setFontName:#"Marker Felt"];
[CCMenuItemFont setFontSize:75];
CCMenuItem *MainMenu = [CCMenuItemFont itemFromString:#"Main Menu" target:self selector:#selector(gotoMainMenu)];
CCMenu *WinMenu = [CCMenu menuWithItems:MainMenu, nil];
[self addChild:WinMenu];
MainMenu.position = ccp(400,500);
}
// on "init" you need to initialize your instance
-(id) init
{
// always call "super" init
// Apple recommends to re-assign "self" with the "super" return value
if( (self=[super init]))
{
self.isTouchEnabled = YES;
scoreNumber = 10;
bg = [CCSprite spriteWithFile:#"metal_background.jpeg"];
bg.position = ccp(512,384);
[self addChild:bg];
toolBar = [CCSprite spriteWithFile:#"ToolBar.png"];
toolBar.position = ccp(512,-30);
[self addChild:toolBar];
score = [CCLabelAtlas labelWithString:#"0123456789" charMapFile:#"ScoreFinal.png" itemWidth:50 itemHeight:75 startCharMap:'.'];
[self addChild:score];
score.position = ccp (-100,15);
CCLabelTTF *scoreLabel = [CCLabelTTF labelWithString:#"Score:" fontName:#"Marker Felt" fontSize:45];
scoreLabel.position = ccp(score.position.x + 275,score.position.y + 40);
scoreLabel.color = ccc3(0, 0, 0);
[self addChild:scoreLabel];
star = [CCSprite spriteWithFile:#"Star.png"];
star.position = ccp(400,600);
[self addChild:star];
star2 = [CCSprite spriteWithFile:#"Star.png"];
star2.position = ccp(600,600);
star3 = [CCSprite spriteWithFile:#"Star.png"];
star3.position = ccp(200,600);
player = [CCSprite spriteWithFile:#"ball.png"];
player.position = ccp(500,300);
[self addChild:player];
enemy = [CCSprite spriteWithFile:#"SpaceShip.png"];
enemy.position = ccp(150,600);
[self addChild:enemy];
enemy2 = [CCSprite spriteWithFile:#"SpaceShip.png"];
enemy2.position = ccp(250,600);
[self addChild:enemy2];
enemy3 = [CCSprite spriteWithFile:#"SpaceShip.png"];
enemy3.position = ccp(350,600);
[self addChild:enemy3];
[self schedule:#selector(enemyMove) interval:0.01];
[self schedule:#selector(collisionDetection) interval:0.01];
[self schedule:#selector(getStar) interval:0.01];
NSString *string = [NSString stringWithFormat:#"Score: %i", (int)scoreNumber];
[score setString:string];
x = 15;
x2 = 15;
x3 = 15;
y = 15;
Bx = 10;
By = 10;
movePlayer = FALSE;
CCRepeatForever *repeat = [CCRepeatForever actionWithAction: [CCRotateBy actionWithDuration:2 angle:360]];
[star runAction:repeat];
star.visible = 1;
}
return self;
}
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch* myTouch = [touches anyObject];
CGPoint location = [myTouch locationInView: [myTouch view]];
location = [[CCDirector sharedDirector]convertToGL:location];
CGRect playerRect = CGRectMake(player.position.x - (player.contentSize.width/2),
player.position.y - (player.contentSize.height/2),
player.contentSize.width,
player.contentSize.height);
CGRect Tlocation = CGRectMake(location.x, location.y, 10, 10);
NSLog(#"Touch Began");
if (CGRectIntersectsRect (Tlocation, playerRect)) {
player.position = location;
movePlayer = TRUE;
}
}
-(void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *myTouch = [touches anyObject];
CGPoint point = [myTouch locationInView:[myTouch view]];
point = [[CCDirector sharedDirector] convertToGL:point];
if (movePlayer == TRUE) {
player.position = point;
if (player.position.y < 110) {
player.position = ccp(player.position.x, 111);
}
}
}
-(void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(#"Touch ended");
movePlayer = FALSE;
}
-(void) enemyMove {
enemy.position = ccp(enemy.position.x + x, enemy.position.y);
enemy2.position = ccp(enemy2.position.x - x2, enemy2.position.y);
enemy3.position = ccp(enemy3.position.x + x3, enemy3.position.y);
if (enemy.position.x > 1024 || enemy.position.x < 0) {
x = -x;
}
if (enemy2.position.x > 1024 || enemy2.position.x < 0) {
x2 = -x2;
}
if (enemy3.position.x > 1024 || enemy3.position.x < 0) {
x3 = -x3;
}
if (enemy.position.y > 768 || enemy.position.y < 120) {
y = -y;
}
}
-(void) collisionDetection {
if (CGRectIntersectsRect(player.boundingBox, enemy.boundingBox)) {
[self schedule:#selector(collisionAlert)];
}
if (CGRectIntersectsRect(player.boundingBox, enemy2.boundingBox)) {
[self schedule:#selector(collisionAlert)];
}
if (CGRectIntersectsRect(player.boundingBox, enemy3.boundingBox)) {
[self schedule:#selector(collisionAlert)];
}
}
-(void) getStar {
if (CGRectIntersectsRect(player.boundingBox, star.boundingBox)) {
NSLog(#"Got Star!");
scoreNumber += 100;
NSString *string = [NSString stringWithFormat:#"Score: %i", (int)scoreNumber];
[score setString:string];
[self addChild:star2];
if (star.visible == 1) {
}
}
if (CGRectIntersectsRect(player.boundingBox, star2.boundingBox)) {
NSLog(#"Got Star!");
scoreNumber += 100;
NSString *string = [NSString stringWithFormat:#"Score: %i", (int)scoreNumber];
[score setString:string];
[self addChild:star3];
}
if (CGRectIntersectsRect(player.boundingBox, star3.boundingBox)) {
youWin = [CCLabelTTF labelWithString:#"You Win" fontName:#"Marker Felt" fontSize:75];
youWin.position = ccp(500,400);
[self addChild:youWin];
[self setUpWinMenu];
NSLog(#"Got Star!");
scoreNumber += 100;
NSString *string = [NSString stringWithFormat:#"Score: %i", (int)scoreNumber];
[score setString:string];
player.position = ccp(player.position.x - 10, player.position.y - 20);
[self unschedule:#selector(enemyMove)];
[self unschedule:#selector(collisionAlert)];
[self unschedule:#selector(getStar)];
}
return;
}
-(void) collisionAlert {
player.position = ccp(player.position.x - 10, player.position.y - 20);
[self unschedule:#selector(enemyMove)];
UIAlertView* dialog = [[UIAlertView alloc] init];
[dialog setDelegate:self];
[dialog setTitle:#"Fail"];
[dialog setMessage:#"You are a Failure!"];
[dialog addButtonWithTitle:#"Goto Main Menu"];
[dialog addButtonWithTitle:#"Retry!"];
[dialog addButtonWithTitle:#"Dont push this button"];
[dialog show];
[dialog release];
[self unschedule:#selector(collisionAlert)];
}
-(void) alertView:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)buttonIndex {
if(buttonIndex == 0) {
[[CCDirector sharedDirector] replaceScene:[CCTransitionFlipAngular transitionWithDuration:1 scene:[HelloWorldLayer node]]];
}
if (buttonIndex == 1) {
[[CCDirector sharedDirector] replaceScene:[Level_1 node]];
}
if (buttonIndex == 2) {
[self schedule:#selector(noting)];
}
}
-(void) gotoMainMenu {
[[CCDirector sharedDirector] replaceScene:[CCTransitionJumpZoom transitionWithDuration:1 scene:[HelloWorldLayer node]]];
}
#end
im not finished completely but there maybe a few empty methods but im sure thats not whats causing the problem

All this objects:
CCSprite *player;
CCSprite *enemy;
CCSprite *enemy2;
CCSprite *enemy3;
CCSprite *star;
CCSprite *star2;
CCSprite *star3;
CCSprite *bg;
CCSprite *toolBar;
are being allocated with autorelease methods, such as CCSprite spriteWithFile: and then, when you access these objects in other methods, like you do at ccTouchesBegan: withEvent: they are already deallocated, and you get the EXC_BAD_ACCESS
One thing you can do to fix it, is to call the spriteWithFile: method followed by a retain call, like
toolBar = [[CCSprite spriteWithFile:#"ToolBar.png"] retain];
But don't forget to release the retained objects on your Level_1's class dealloc (which I didn't see implemented in your class)
-(void) dealloc {
[toolBar release];
[super dealloc]
}

Even if you don't see anything on the console, if you run the app under the debugger, you should be able to inspect the call stack at the moment of the crash.
This will tell you clearly if you are accessing some already deallocated object, or possibly trying to send a message.

Related

Having issues with touchesBegan method

I have my sound on logo showing up on the screen and the sound off logo appears when i test it. what I want it to do is change from sound on to sound off when I tap on it. The buttons do acknowledge the tap but nothing happens. I don't have much experience in change node images when they're tapped so I don't really know if I used the most efficient code. Can someone look over my code and see what's wrong? Thanks in advance!
#implementation MyScene
{
SKSpriteNode *soundLogo;
SKSpriteNode *soundOff;
}
-(void) addSoundOff:(CGSize)size {
soundOff = [SKSpriteNode spriteNodeWithImageNamed:#"soundOff"];
//resize sprite
soundOff.size = CGSizeMake(soundOff.size.width/2.25, soundOff.size.height/2.25);
//position it
soundOff.position = CGPointMake(65, 25);
//name sound off
soundOff.name = #"soundOff";
soundOff.zPosition = 0;
soundOff.alpha = 0;
//[self addChild:soundOff];
}
-(void) addSoundOn:(CGSize)size {
soundLogo = [SKSpriteNode spriteNodeWithImageNamed:#"soundLogo"];
//resize sprite
soundLogo.size = CGSizeMake(soundLogo.size.width/2.25, soundLogo.size.height/2.25);
//position sprite
CGPoint myPoint = CGPointMake(65, 25);
soundLogo.position = myPoint;
//name sound logo
soundLogo.name = #"soundOn";
//add action
//soundLogo.alpha = 1;
soundLogo.zPosition = 100;
[self addChild:soundLogo];
}
-(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:#"soundOn"]) {
soundOff.zPosition = 100;
soundOff.alpha = 1;
soundLogo.alpha = 0;
soundLogo.zPosition = 0;
// [node removeFromParent];
// [node addChild:soundOff];
NSLog(#"sound on is pressed");
}
if ([node.name isEqualToString:#"soundOff"]) {
soundLogo.zPosition = 100;
soundLogo.alpha = 1;
soundOff.alpha = 0;
soundOff.zPosition = 0;
// [node removeFromParent];
// [node addChild:soundLogo];
NSLog(#"sound off is pressed");
}
}
It seems nothing wrong in your addSoundOff and addSoundOn functions. What you can do as one of the solutions to change alpha and zPosition properties of SKSpriteNode . And also createsoundOff and soundLogo as instance variables under the implementation. So here is the all code:
#import "MyScene.h"
#implementation MyScene
{
SKSpriteNode *soundLogo;
SKSpriteNode *soundOff;
}
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
/* Setup your scene here */
self.backgroundColor = [SKColor colorWithRed:0.15 green:0.15 blue:0.3 alpha:1.0];
[self addSoundOn:self.size];
[self addSoundOff:self.size];
}
return self;
}
-(void) addSoundOff:(CGSize)size {
soundOff = [SKSpriteNode spriteNodeWithImageNamed:#"soundOff"];
//resize sprite
soundOff.size = CGSizeMake(soundOff.size.width/2.25, soundOff.size.height/2.25);
//position it
soundOff.position = CGPointMake(65, 25);
//name sound off
soundOff.name = #"soundOff";
soundOff.alpha = 0;
soundOff.zPosition = 0;
[self addChild:soundOff];
}
-(void) addSoundOn:(CGSize)size {
SKTexture *soundOn = [SKTexture textureWithImageNamed:#"soundLogo"];
soundLogo = [SKSpriteNode spriteNodeWithTexture:soundOn];
//resize sprite
soundLogo.size = CGSizeMake(soundLogo.size.width/2.25, soundLogo.size.height/2.25);
//position sprite
CGPoint myPoint = CGPointMake(65, 25);
soundLogo.position = myPoint;
//name sound logo
soundLogo.name = #"soundOn";
//add action
soundLogo.zPosition = 100;
[self addChild:soundLogo];
}
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:location];
//sound logo pressed to turn sound on/off
if ([node.name isEqualToString:#"soundOn"]) {
soundOff.alpha = 1;
soundOff.zPosition = 100;
soundLogo.alpha = 0;
soundLogo.zPosition = 0;
NSLog(#"sound on is pressed");
}
if ([node.name isEqualToString:#"soundOff"]) {
soundOff.alpha = 0;
soundOff.zPosition = 0;
soundLogo.alpha = 1;
soundLogo.zPosition = 100;
NSLog(#"sound off is pressed");
}
}
#end

Cocos2d 2.0 SimpleAudioEngine stop sound effect in another object

I am trying to stop audio effect using simpleaudioengine in Cocos2d 2.0.
I have the following situation;
Farm Scene with two sky layers day/night. These are placed sprites, created within the layer in the scene.
I also have sprite classes for other characters (using Ray Wenderlichs Space Viking code) that are placed.
Upon touching the sky I have the day change to night, and vice versa, and I can start and stop the night crickets sound effect using ALuint ID in the Farm Layer (PollitosLayer.m) .
touching the sun sprite (class) has it's own ALuint reference I can start. But what I want is to STOP it when touching the Sky Sprite.
Is there a way to reference the ALuint of the Sun Class when touching the simple NON-CLASS Sky Sprite in the same PollitosLayer.m?
My code excerpts below.
#import "Sun.h"
#import "PollitosLayer.h"
#implementation Sun
#synthesize sunAnim;
#synthesize settingAnim;
-(void) dealloc {
}
-(void)playSunSound {
sunSound = PLAYSOUNDEFFECT(SUN_SPIN);
}
-(void)changeState:(CharacterStates)newState {
[self stopAllActions];
id action = nil;
characterState = newState;
switch (newState) {
case kStateGlowing:
CCLOG(#"Sun->Changing State to glowing");
[self setDisplayFrame:
[[CCSpriteFrameCache sharedSpriteFrameCache]
spriteFrameByName:#"sun_1.png"]];
action = [CCSpawn actions:[CCRepeatForever actionWithAction:
[CCAnimate actionWithAnimation:sunAnim]],nil];
//[self playSunSound];
break;
case kStateSetting:
CCLOG(#"Sun->Changing State to Setting");
[self setDisplayFrame:
[[CCSpriteFrameCache sharedSpriteFrameCache]
spriteFrameByName:#"sun_1.png"]];
action = [CCMoveBy actionWithDuration:3.0f
position:CGPointMake(0.0f,-400.0f)];
[[SimpleAudioEngine sharedEngine] stopEffect:sunSound];
break;
default:
CCLOG(#"Sun -> Unknown CharState %d",
characterState);
break;
}
if (action != nil)
[self runAction:action];
}
#pragma mark -
-(id) init {
if( (self=[super init]) ) {
//CGSize screenSize = [[CCDirector sharedDirector] winSize];
[self initAnimations];
[[[CCDirector sharedDirector] touchDispatcher] addTargetedDelegate:self priority:-1 swallowsTouches:YES];
}
return self;
}
-(void) cleanup
{
// Must manually remove this class as touch input receiver!
[[CCDirector sharedDirector].touchDispatcher removeDelegate:self];
[super cleanup];
}
#pragma mark -
#pragma mark initAnimations
-(void)initAnimations {
[self setSunAnim:
[self loadPlistForAnimationWithName:#"sunAnim"
andClassName:NSStringFromClass([self class])]];
}
-(void) update:(ccTime)delta
{
}
-(void) registerWithTouchDispatcher
{
[[[CCDirector sharedDirector] touchDispatcher] addTargetedDelegate:self priority:-1 swallowsTouches:YES];
}
-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint touchLocation = [PollitosLayer locationFromTouch:touch];
// Check if this touch is on the sun's sprite.
BOOL isTouchHandled = CGRectContainsPoint([self boundingBox], touchLocation);
if (isTouchHandled)
{
[self changeState:kStateGlowing];
[self runAction:[CCRotateBy actionWithDuration:1.0f angle:360]];
}
return isTouchHandled;
}
-(void) ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event {
[self playSunSound];
}
#end
farm layer below PollitosLayer.m
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#import "Constants.h"
#import "GameManager.h"
#import "PollitosLayer.h"
#import "Pollito.h"
#import "GameObject.h"
#import "Owl.h"
#import "Sun.h"
#import "Chicks.h"
#import "MainScene.h"
#implementation PollitosLayer
#synthesize backbuttonsprite;
#synthesize henNightSprite;
#synthesize henDaySprite;
#synthesize skyDay;
#synthesize skyNight;
#synthesize moon;
ALuint nightcrickets;
ALuint sunSoundLayer;
ALuint sunSound;
ALuint pollitoSound;
+(CGPoint) locationFromTouch:(UITouch*)touch
{
CGPoint touchLocation = [touch locationInView: [touch view]];
return [[CCDirector sharedDirector] convertToGL:touchLocation];
}
+(CGPoint) locationFromTouches:(NSSet*)touches
{
return [self locationFromTouch:[touches anyObject]];
}
-(void)playNightSound {
nightcrickets = PLAYSOUNDEFFECT(NIGHT_CRICKETS);
}
-(void)playSunSoundLayer {
sunSoundLayer = PLAYSOUNDEFFECT(SUN_SPIN);
}
-(void)playPollitoSound {
pollitoSound = PLAYSOUNDEFFECT(POLLITOS_CHIRP);
}
-(id)init {
self = [super init];
if (self != nil) {
CGSize screenSize = [CCDirector sharedDirector].winSize;
// enable touches
self.isTouchEnabled = YES;
srandom(time(NULL)); // Seeds the random number generator
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
[[CCSpriteFrameCache sharedSpriteFrameCache]
addSpriteFramesWithFile:#"sceneatlas1_default.plist"]; // 1
sceneSpriteBatchNode =
[CCSpriteBatchNode batchNodeWithFile:#"sceneatlas1_default.png"]; // 2
} else {
[[CCSpriteFrameCache sharedSpriteFrameCache]
addSpriteFramesWithFile:#"sceneatlas1_default.plist"]; // 1
sceneSpriteBatchNode =
[CCSpriteBatchNode batchNodeWithFile:#"sceneatlas1_default.png"];// 2
}
[self addChild:sceneSpriteBatchNode z:70 tag:100];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
[[CCSpriteFrameCache sharedSpriteFrameCache]
addSpriteFramesWithFile:#"sunsheet_default.plist"]; // 1
sunSpriteBatchNode =
[CCSpriteBatchNode batchNodeWithFile:#"sunsheet_default.png"]; // 2
} else {
[[CCSpriteFrameCache sharedSpriteFrameCache]
addSpriteFramesWithFile:#"sunsheet_default.plist"]; // 1
sunSpriteBatchNode =
[CCSpriteBatchNode batchNodeWithFile:#"sunsheet_default.png"];// 2
}
[self addChild:sunSpriteBatchNode z:6 tag:101];
[self createObjectOfType:kSun
//withHealth:100
atLocation:ccp(screenSize.width * 0.18f,
screenSize.height * 0.79f)
withZValue:10];
CCSprite *backgroundImage;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
// Indicates game is running on iPad
backgroundImage =
[CCSprite spriteWithFile:#"pollitosbackground.png"];
} else {
backgroundImage =
[CCSprite spriteWithFile:#"pollitosbackground.png"];
}
[backgroundImage setPosition:ccp(screenSize.width/2.0f,
screenSize.height/2.0f)];
[self addChild:backgroundImage z:20 tag:69];
}
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
// Indicates game is running on iPad
skyDay =
[CCSprite spriteWithFile:#"SkyDay.png"];
} else {
skyDay =
[CCSprite spriteWithFile:#"SkyDay.png"];
}
CGSize screenSize = [CCDirector sharedDirector].winSize;
[skyDay setPosition:ccp(screenSize.width * 0.5f,
screenSize.height* 0.75f)];
[self addChild:skyDay z:0 tag:59]; //skyDay.visible=YES;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
// Indicates game is running on iPad
skyNight =
[CCSprite spriteWithFile:#"SkyNight.png"];
} else {
skyNight =
[CCSprite spriteWithFile:#"SkyNight.png"];
}
[skyNight setPosition:ccp(screenSize.width * 0.5f,
screenSize.height * 0.75f)];
[self addChild:skyNight z:2 tag:51]; skyNight.visible = NO;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
// Indicates game is running on iPad
moon =
[CCSprite spriteWithFile:#"Moon.png"];
} else {
moon =
[CCSprite spriteWithFile:#"Moon.png"];
}
[moon setPosition:ccp(screenSize.width * 0.87f,
screenSize.height * 0.51f)];
[self addChild:moon z:5 tag:52];
backbuttonsprite =[CCSprite spriteWithFile:#"back.png"];
[backbuttonsprite setPosition:ccp(screenSize.width * 0.88f,
screenSize.height * 0.95f)];
[self addChild:backbuttonsprite z:75 tag:75];
henDaySprite =[CCSprite spriteWithFile:#"henDay.png"];
[henDaySprite setPosition:ccp(screenSize.width * 0.70f,
screenSize.height * 0.37f)];
[self addChild:henDaySprite z:60 tag:60];
henNightSprite =[CCSprite spriteWithFile:#"henNight.png"];
[henNightSprite setPosition:ccp(screenSize.width * 0.70f,
screenSize.height * 0.37f)];
[self addChild:henNightSprite z:61 tag:61];
henNightSprite.visible = NO;
[self createObjectOfType:kPollito
atLocation:ccp(screenSize.width * 0.378f,
screenSize.height * 0.13f)
withZValue:21];
[self createObjectOfType:kPollito2
atLocation:ccp(screenSize.width * 0.578f,
screenSize.height * 0.18f)
withZValue:22];
[self createObjectOfType:kPollito3
atLocation:ccp(screenSize.width * 0.450f,
screenSize.height * 0.20f)
withZValue:23];
[self createObjectOfType:kPollito4
atLocation:ccp(screenSize.width * 0.3f,
screenSize.height * 0.43f)
withZValue:24];
[self createObjectOfType:kPollito5
atLocation:ccp(screenSize.width * 0.10f,
screenSize.height * 0.27f)
withZValue:25];
[self createObjectOfType:kPollito6
atLocation:ccp(screenSize.width * 0.25f,
screenSize.height * 0.19f)
withZValue:26];
[self createObjectOfType:kPollito7
atLocation:ccp(screenSize.width * 0.77f,
screenSize.height * 0.12f)
withZValue:27];
[self createObjectOfType:kPollito8
atLocation:ccp(screenSize.width * 0.17f,
screenSize.height * 0.42f)
withZValue:28];
[self createObjectOfType:kChicks
atLocation:ccp(screenSize.width * 0.73f,
screenSize.height * 0.25f)
withZValue:75];
[self createObjectOfType:kOwl
atLocation:ccp(screenSize.width * 0.897f,
screenSize.height * 0.727f)
withZValue:29];
return self;
}
#pragma mark -
-(void)createObjectOfType:(GameObjectType)objectType
atLocation:(CGPoint)spawnLocation
withZValue:(int)ZValue {
if (objectType == kPollito) {
CCLOG(#"Creating the Pollito1");
Pollito *pollito = [[[Pollito alloc] init] initWithSpriteFrameName:#"pollito_1.png"];
[pollito setPosition:spawnLocation];
[sceneSpriteBatchNode addChild:pollito z:ZValue tag:1];
[pollito changeState:kStatePecking1];
} else if (objectType == kPollito2) {
CCLOG(#"Creating the Pollito2");
Pollito *pollito2 = [[[Pollito alloc]init ]initWithSpriteFrameName:#"pollito_1.png"];
[pollito2 setPosition:spawnLocation];
[sceneSpriteBatchNode addChild:pollito2 z:ZValue tag:2];
[pollito2 changeState:kStatePecking2];
}else if (objectType == kPollito3) {
CCLOG(#"Creating the Pollito3");
Pollito *pollito3 = [[[Pollito alloc] init ]initWithSpriteFrameName:#"pollito_1.png"];
[pollito3 setPosition:spawnLocation];
[sceneSpriteBatchNode addChild:pollito3 z:ZValue tag:3];
[pollito3 changeState:kStatePecking3];
}else if (objectType == kPollito4) {
CCLOG(#"Creating the Pollito4");
Pollito *pollito4 = [[[Pollito alloc] init ]initWithSpriteFrameName:#"pollito_1.png"];
[pollito4 setPosition:spawnLocation];
[sceneSpriteBatchNode addChild:pollito4 z:ZValue tag:4];
[pollito4 changeState:kStatePecking4];
[pollito4 setScale:0.8f];
}else if (objectType == kPollito5) {
CCLOG(#"Creating the Pollito5");
Pollito *pollito5 = [[[Pollito alloc] init ]initWithSpriteFrameName:#"pollito_1.png"];
[pollito5 setPosition:spawnLocation];
[sceneSpriteBatchNode addChild:pollito5 z:ZValue tag:5];
[pollito5 changeState:kStatePecking5];
}else if (objectType == kPollito6) {
CCLOG(#"Creating the Pollito6");
Pollito *pollito6 = [[[Pollito alloc] init] initWithSpriteFrameName:#"pollito_1.png"];
[pollito6 setPosition:spawnLocation];
[sceneSpriteBatchNode addChild:pollito6 z:ZValue tag:6];
[pollito6 changeState:kStatePecking6];
}else if (objectType == kPollito7) {
CCLOG(#"Creating the Pollito7");
Pollito *pollito7 = [[[Pollito alloc] init ]initWithSpriteFrameName:#"pollito_1.png"];
[pollito7 setPosition:spawnLocation];
[sceneSpriteBatchNode addChild:pollito7 z:ZValue tag:7];
[pollito7 changeState:kStatePecking7];
}else if (objectType == kPollito8) {
CCLOG(#"Creating the Pollito8");
Pollito *pollito8 = [[[Pollito alloc] init] initWithSpriteFrameName:#"pollito_1.png"];
[pollito8 setPosition:spawnLocation];
[sceneSpriteBatchNode addChild:pollito8 z:ZValue tag:8];
[pollito8 changeState:kStatePecking8];
[pollito8 setScale:0.8f];
}else if (objectType == kOwl) {
CCLOG(#"Creating the Owl");
Owl *owl = [[[Owl alloc] init ]initWithSpriteFrameName:#"owl_1.png"];
[owl setPosition:spawnLocation];
[sceneSpriteBatchNode addChild:owl z:ZValue tag:9];
owl.visible = NO;
}else if (objectType == kChicks) {
CCLOG(#"Creating the Chicks");
Chicks *chicks = [[[Chicks alloc] init] initWithSpriteFrameName:#"PollitosSleeping_1.png"];
[chicks setPosition:spawnLocation];
[sceneSpriteBatchNode addChild:chicks z:ZValue tag:11];
chicks.visible = NO;
}else if (objectType == kSun) {
CCLOG(#"Here comes the Sun");
CCSprite *sun = [[[Sun alloc] init ]initWithSpriteFrameName:#"sun_1.png"];
[sun setPosition:spawnLocation];
[sunSpriteBatchNode addChild:sun z:ZValue tag:12];
}
}
-(void) registerWithTouchDispatcher
{
[[[CCDirector sharedDirector] touchDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:NO];
}
-(void) dealloc
{
CCLOG(#"%#:worked %#", NSStringFromSelector(_cmd), self);
}
-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
CGSize screenSize = [CCDirector sharedDirector].winSize;
Chicks *chicks = (Chicks*)[sceneSpriteBatchNode getChildByTag:11];
Sun *sun = (Sun*)[sunSpriteBatchNode getChildByTag:12];
Owl *owl = (Owl*)[sceneSpriteBatchNode getChildByTag:9];
CGPoint touchLocation = [PollitosLayer locationFromTouch:touch];
// Check if this touch is on the pollito sprite.
if (CGRectContainsPoint([backbuttonsprite boundingBox], touchLocation))
{
STOPSOUNDEFFECT(nightcrickets);
STOPSOUNDEFFECT(pollitoSound);
STOPSOUNDEFFECT(sunSound);
STOPSOUNDEFFECT(sunSoundLayer);
[[GameManager sharedGameManager] runSceneWithID:kMainScene];
}
else if ((CGRectContainsPoint([henDaySprite boundingBox], touchLocation))&&(henNightSprite.visible == NO))
{
henDaySprite.visible = NO;
henNightSprite.visible = YES;
chicks.visible = YES;
[chicks changeState:kStateChirping];
}
else if ((CGRectContainsPoint([henNightSprite boundingBox], touchLocation))&&(henDaySprite.visible == NO))
{
henDaySprite.visible = YES;
henNightSprite.visible = NO;
chicks.visible = NO;
}
else if ((CGRectContainsPoint([skyDay boundingBox], touchLocation)) && (skyNight.visible == NO))
{
skyNight.visible = YES;
owl.visible = YES;
CCAction *moveUp = [CCMoveTo actionWithDuration:2.0f
position:CGPointMake(screenSize.width * 0.87f,
screenSize.height * 0.91f)];
[moon runAction:moveUp];
[[SimpleAudioEngine sharedEngine] stopEffect:sunSoundLayer];
CCAction *sunDown = [CCMoveTo actionWithDuration:2.0f
position:CGPointMake(screenSize.width * 0.18f,
screenSize.height * 0.40f)];
[sun runAction:sunDown];
STOPSOUNDEFFECT(sunSound);
[self playNightSound];
//[[SimpleAudioEngine sharedEngine] stopEffect:sunSound];
STOPSOUNDEFFECT(sunSoundLayer);
}else if (((CGRectContainsPoint([skyNight boundingBox], touchLocation)) && (skyNight.visible == YES) )){
skyNight.visible = NO;
CCAction *moveAction = [CCMoveTo actionWithDuration:2.0f
position:CGPointMake(screenSize.width * 0.87f, screenSize.height * 0.57f)];
[moon runAction:moveAction];
owl.visible = NO;
CCAction *sunUp = [CCMoveTo actionWithDuration:2.0f
position:CGPointMake(screenSize.width * 0.18f,
screenSize.height * 0.79f)];
[sun runAction:sunUp];
STOPSOUNDEFFECT(nightcrickets);
}
return YES;
}
-(void) ccTouchMoved:(UITouch *)touches withEvent:(UIEvent *)event{
}
-(void) ccTouchCancelled:(UITouch *)touch withEvent:(UIEvent *)event {
}
-(void) ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event {
}
#end
To keep it simple, one thing you can do is have the farm layer own the two skies (day and night) and have the day sky own the sun. That way when you are determining what is touched, you can see if the current sky's heavily body (e.g. sun) is touched. If so then stop all necessary effects and play the sun effect. If the sky itself is touched then you can stop the heavily body's audio effect (which would do nothing if one was not playing) before changing the day/night cycle and continuing to play the next set of audio effects. For example:
#intereface FarmLayer()
#property (nonatomic, strong) Sky* day;
#property (nonatomic, strong) Sky* night;
#property (nonatomic, weak) Sky* currentSky;
#end
#implementation FarmLayer
- (void)onEnter
{
[super onEnter];
self.day = [...];
self.night = [...];
self.currentSky = self.day;
// Couldn't think of a better name but you get what I mean.
self.day.skyBody = [Sun ...];
...
}
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// Pseudo-ish code...
// if self.currentSky && self.currentSky.skyBody is touched
// - Stop all necessary audio effects if playing.
// - Play sky body audio.
// else if self.currentSky is touched
// - Stop all necessary audio effects (including self.currentSky.skyBody's audio effect).
// - If self.currentSky == self.day then switch to night (and vice versa).
// - Play all necessary audio effects for the new sky.
// - Make self.currentSky equal to the the new sky.
}
#end
I hope this helped. The example is just a quick one that assumes a lot of stuff and is not meant to be copied and pasted but it should give you an idea on how to go about solving your dilemma. Let me know if I misunderstood the question.
Edited:
Also I forgot to mention, each object can have its own array of audio files and you can have convenience methods to start and stop them. So for example assume you had an array property called audioEffects:
#interface Sky()
#property (nonatomic, strong) NSMutableArray* audioFileNames;
#property (nonatomic, strong) NSMutableArray* audioIds;
#end
#implementation Sky
- (void)addSoundEffectWithFileName:(NSString *)fileName
{
if (!fileName)
{
// Handle error.
return;
}
if (!self.audioFileNames)
{
self.audioFileNames = [NSMutableArray array];
}
[self.audioFileNames addObject:fileName];
if (!self.audioIds)
{
self.audioIds = [NSMutableArray array];
}
[self.audioIds addObject:#0];
}
- (void)playAllAudioEffects
{
for (int i = 0; i < [self.audioFileNames count]; i++)
{
NSString* audioFile = self.audioFileNames[i];
ALuint audioId = [[SimpleAudioEngine sharedEngine] playEffect:audioFile];
self.audioIds[i] = [NSNumber numberWithUnsignedInt:audioId];
}
}
- (void)stopAllAudioEffects
{
for (int i = 0; i < [self.audioIds count]; i++)
{
ALuint audioId = [self.audioIds[i] unsignedIntegerValue];
[[SimpleAudioEngine sharedEngine] stopEffect:audioId];
}
}
#end
Many Many thanks to Allen S. The creation of the separate SkyLayer and creating the properties inside of it, then referencing those as properties inside the parent layer and then using your onEnter worked. I can now reference and stop the audio of the sky elements from other sprites in the parent layer Here's my onEnter code.
(void)onEnter
{
[super onEnter];
CGSize screenSize = [CCDirector sharedDirector].winSize;
self.skyNight = [CCSprite spriteWithFile:#"SkyNight.png"];
[_skyNight setPosition:ccp(screenSize.width * 0.5f,
screenSize.height * 0.75f)];
[self addChild:_skyNight];
_skyNight.visible=NO;
self.currentsky = self.skyDay;
self.skyDay =
[CCSprite spriteWithFile:#"SkyDay.png"];
[_skyDay setPosition:ccp(screenSize.width * 0.5f,
screenSize.height* 0.75f)];
[self addChild:_skyDay];
_skyDay.visible=YES;
self.Sunspin = [CCSprite spriteWithFile:#"sun_1.png"];
[_Sunspin setPosition:ccp(screenSize.width * 0.18f,screenSize.height* 0.85f)];
[self addChild:_Sunspin];
}

How to restart a Cocos2D application?

I am making a game, and everything works except the restart button. I would like the game to start again from the restart method, which loads everything onto the screen and sets up gameplay. However I get an error saying "Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[HelloWorldLayer resetAll:]: unrecognized selector sent to instance 0x9142c70'"
Below is the code for the main class (I'm assuming you guys don't need the other classes, as they work fine):
#import "HelloWorldLayer.h"
#import "AppDelegate.h"
#import "Block.h"
#import "Character.h"
#implementation HelloWorldLayer
-(id) init{ //Init method
if(self = [super initWithColor:ccc4(84,56,8,26)]){ //Initialise with a black background
[self restart];
}
return self;
}
-(void) setUpMenus{
moveRight = [CCMenuItemImage itemWithNormalImage:#"GoRightButton.png" selectedImage:#"GoRightButtonSelected.png" target: self selector:#selector(moveRightMethod:)];
moveLeft = [CCMenuItemImage itemWithNormalImage:#"GoLeftButton.png" selectedImage:#"GoLeftButtonSelected.png" target: self selector:#selector(moveLeftMethod:)];
moveUp = [CCMenuItemImage itemWithNormalImage:#"GoUpButton.png" selectedImage:#"GoUpButtonSelected.png" target: self selector:#selector(moveUpMethod:)];
moveDown = [CCMenuItemImage itemWithNormalImage:#"GoDownButton.png" selectedImage:#"GoDownButtonSelected.png" target: self selector:#selector(moveDownMethod:)];
moveRight.position = ccp(player.image.position.x - 10, player.image.position.y);
moveLeft.position = ccp(player.image.position.x - 80, player.image.position.y);
moveUp.position = ccp(player.image.position.x - 40, player.image.position.y + 30);
moveDown.position = ccp(player.image.position.x - 40, player.image.position.y - 30);
myScore.position = ccp(player.image.position.x - 20, player.image.position.y + 100);
mainMenu = [CCMenu menuWithItems:moveRight, moveLeft, moveUp, moveDown, nil];
[self addChild: mainMenu];
}
-(void) enemyMoveTowardsPlayer{
CGPoint playerPosition = player.image.position;
[enemy moveToLocationEnemy:&playerPosition];
}
-(void) moveRightMethod: (id) sender{
if(enemyExists == YES){
[self enemyMoveTowardsPlayer];
}
if(player.image.position.x < 5000){
[player move];
[self changeBack];
}
}
-(void) moveLeftMethod: (id) sender{
if(enemyExists == YES){
[self enemyMoveTowardsPlayer];
}
if(player.image.position.x > 20){
[player moveLeft];
[self change];
}
}
-(void) moveUpMethod: (id) sender{
if(enemyExists == YES){
[self enemyMoveTowardsPlayer];
}
if(player.image.position.y < 7000){
[player moveUp];
[self changeUp];
}
}
-(void) moveDownMethod: (id) sender{
if(player.image.position.y > -100){
[player moveDown];
[self changeDown];
}
if(enemyExists == YES){
[self enemyMoveTowardsPlayer];
}
}
-(void) callSpawnEnemy{
CCSprite *enemyImage = [CCSprite spriteWithFile:#"Lizard_Sprite.png"]; //Enemy picture
enemy = [[Character alloc] initWithImageAndNameAndProjectile:enemyImage
andAnotherParam:#"Enemy"];
//Enemy instantiation
enemy.image.position = ccp(100,400);
[self addChild:enemy.image]; //Add the enemy image object
enemyExists = YES;
}
-(void)ccTouchesBegan:(NSSet*)touches withEvent:(UIEvent*)event{
//CODE FOR HANDLING TOUCH EVENTS. THE BELOW CODE SIMPLY CREATES AND INSTANTIATES A TOUCH OBJECT AND STORES THE LOCATION
CGPoint touchLocation;
for(UITouch *touch in touches ) {
touchLocation = [touch locationInView: [touch view]];
CGPoint prevLocation = [touch previousLocationInView: [touch view]];
touchLocation = [[CCDirector sharedDirector] convertToGL: touchLocation];
prevLocation = [[CCDirector sharedDirector] convertToGL: prevLocation];
CGPoint diff = ccpSub(touchLocation,prevLocation);
[self setPosition: ccpAdd(self.position, diff)];
}
//
NSLog(#"%f", touchLocation.x);
NSLog(#"%f",touchLocation.y);
}
-(void) change{ //Code to change the image to a leftward facing sprite
CCTexture2D* tex = [[CCTextureCache sharedTextureCache] addImage:#"PlayerSpriteLeftHugeV2.png"];
[player.image setTexture: tex];
}
-(void) changeBack{ //Code to change the image to a rightward facing sprite
CCTexture2D* tex = [[CCTextureCache sharedTextureCache] addImage:#"PlayerSpriteHugeV2.png"];
[player.image setTexture: tex];
}
-(void) changeUp{ //Code to change the image to a leftward facing sprite
CCTexture2D* tex = [[CCTextureCache sharedTextureCache] addImage:#"PlayerSpriteUp.png"];
[player.image setTexture: tex];
}
-(void) changeDown{ //Code to change the image to a rightward facing sprite
CCTexture2D* tex = [[CCTextureCache sharedTextureCache] addImage:#"PlayerSpriteDown.png"];
[player.image setTexture: tex];
}
-(void) generate2dMap{ //Method to generate a 130 by 80 block map (10400 blocks)
for(int i = 20; i < 13000; i+=100){ //X coordinate. Increment by length of each block.
for(int g = 20; g < 8000; g+=100){ //Y coordinate. Increment by length of each block.
CGPoint p = CGPointMake(i, g); //Point for the block. Changes every time the loop goes through
int randNumber = rand() % 11; //Random number to determine the block type
if(randNumber < 1){ //Only 1 in 10 blocks should be gold blocks
Block* gold = [[Block alloc] initWithTypePositionAndImage:#"Gold" andImageName:[CCSprite spriteWithFile:#"GoldBlockHuge.png"]];
//Create a gold object and pass the appropriate information to the constructor
[allBlocks addObject: gold]; //Add the gold object to the mutable array
gold.image.position = p; //Set the block image position to be the current location
[self addChild:gold.image]; //Add the block image to the screen
}
else{ //More common. Should occur 9/10 times
Block* dirt = [[Block alloc]
initWithTypePositionAndImage:#"Dirt" andImageName:[CCSprite spriteWithFile:#"DirtBlockHuge.png"]];
//Create a dirt object and pass the appropriate information to the constructor
[allBlocks addObject: dirt]; //Add the dirt object to the mutable array
dirt.image.position = p; //Set the block image position to be the current location
[self addChild:dirt.image]; //Add the block image to the screen
}
}
}
}
-(void) checkScore{ //Update the score. Set the score object to be the score primative from the player object
[myScore setString:[NSString stringWithFormat:#"%d", player->score]];
stringScore = myScore.string;
}
-(BOOL) checkForCollisions{ //Method to check for collision detection
for(Block *b in allBlocks){ //Loop through all blocks to check if any have collided with the player image
CGRect playerRect = CGRectMake(player.image.position.x, player.image.position.y, 90, 84);
//Rectangle object for the player
CGRect blockRect = CGRectMake(b.image.position.x, b.image.position.y, 50, 50);
//Rectangle object for each block
if(CGRectIntersectsRect(playerRect, blockRect)){ //If the block is in the state of intersecting the player
amountOfBlocks++;
collisionSprite = b; //Set the collision object to be the block
if([collisionSprite.type isEqualToString:#"Gold"]){ //If it's collided with a gold object...
[player incrementScoreBy:100]; //Then increment the score by 100
}
else if([collisionSprite.type isEqualToString:#"Bronze"]){
[player incrementScoreBy:20];
}
else if([collisionSprite.type isEqualToString:#"Silver"]){
[player incrementScoreBy:50];
}
else if([collisionSprite.type isEqualToString:#"Dirt"]){
[player incrementScoreBy:2];
}
return YES; //There has been a collision, and you should terminate this round of the method
}
if(enemyExists == YES){
CGRect enemyRect = CGRectMake(enemy.image.position.x, enemy.image.position.y, 80,80);
if(CGRectIntersectsRect(enemyRect, blockRect)){
collisionSprite = b;
enemyHitBlock = YES;
return YES;
}
if(CGRectIntersectsRect(enemyRect, playerRect)){
enemyHitPlayer = YES;
return YES;
}
}
}
return NO; //There has not been a collision, and you should terminate this round of the method
}
-(void) update: (ccTime) dt{ //Update method called on regular interval that checks for collisions, updates the score
if(isDone == NO){
if([self checkForCollisions]){ //Check for collisions
[self removeChild:collisionSprite.image cleanup:YES]; //Remove the sprite if there has been a collision
[allBlocks removeObject:collisionSprite]; //Remove the object if there has been a collision
if(enemyExists == YES){
if(enemyHitPlayer == YES){
[self removeChild:enemy.image cleanup:YES];
enemyHitPlayer = NO;
enemyExists = NO;
}
if(enemyHitBlock == YES){
[self removeChild:collisionSprite.image cleanup:YES]; //Remove the sprite if there has been a collision
enemyHitBlock = NO;
}
}
}
mainMenu.position = ccp(player.image.position.x - 10, player.image.position.y);
myScore.position = ccp(player.image.position.x - 20, player.image.position.y + 100);
if(enemyExists == NO){
[self callSpawnEnemy];
}
[self checkScore]; //Update the score
if([stringScore intValue] >= 200){
[self endGame];
}
}
}
-(void) endGame{
isDone = YES;
endGameString = #"You reached the max score in ";
stringBlockCount = [NSString stringWithFormat:#"%d blocks", amountOfBlocks];
totalString = [endGameString stringByAppendingString:stringBlockCount];
endGameMessage = [CCLabelTTF labelWithString:totalString fontName:#"Times New Roman" fontSize:20];
CGSize winSize = [[CCDirector sharedDirector] winSize];
CGPoint point = ccp(winSize.height/2,winSize.width/2);
endGameMessage.position = point;
[self stopAllActions];
[self runAction:[CCFollow actionWithTarget:endGameMessage]];
[self removeAllChildrenWithCleanup:YES];
[self addChild: endGameMessage];
restart = [CCMenuItemImage itemWithNormalImage:#"RestartButton.png" selectedImage:#"RestartButtonSelected.png" target: self selector:#selector(resetAll:)];
restart.position = ccp(point.x - 500, point.y - 250);
restartMenu = [CCMenu menuWithItems:restart, nil];
[self addChild:restartMenu];
}
-(void) restart{
[self removeAllChildrenWithCleanup:YES];
NSLog(#"Got here");
isDone = NO;
amountOfBlocks = 0;
allBlocks = [[NSMutableArray alloc] init]; //Instantiate array that holds all blocks
collisionSprite = [[Block alloc] init]; //Instantiate object that holds the collision object
enemyCollisionSprite = [[Character alloc] init];
enemyHitBlock = NO;
enemyHitPlayer = NO;
[self generate2dMap]; //Generate the map
self.isTouchEnabled = YES; //Enable touch technology
CCSprite *playerImage = [CCSprite spriteWithFile:#"PlayerSpriteHugeV2.png"]; //Player image object
player = [[Character alloc] initWithImageAndNameAndProjectile:playerImage andAnotherParam:#"Player"];
//Instantiate player object
player.image.position = ccp(0,210); //Set player image position
//Set player projectile image position
stringScore = [NSString stringWithFormat:#"%d", player->score]; //Score object
myScore = [CCLabelTTF labelWithString:stringScore fontName:#"Times New Roman" fontSize:20];
//CCLabel representation of score
myScore.position = ccp(20,300); //Set position of label score
myScore.color = ccc3(255,255,255); //Set color of label score
[self addChild:myScore]; //Add the score object
[self addChild:player.image]; //Add the player image object
[self callSpawnEnemy];
[self setUpMenus];
[self moveForward];
[self schedule:#selector(update:) interval:0.005]; //Schedule updating on 0.005 second intervals
}
+(void) resetAll{
[[CCDirector sharedDirector] replaceScene:[HelloWorldLayer scene]];
}
-(void) moveForward{ //Method to move the camera forward
[self runAction:[CCFollow actionWithTarget:player.image]];
}
+(CCScene*) scene{
CCScene *scene = [CCScene node];
HelloWorldLayer *layer = [HelloWorldLayer node];
[scene addChild: layer];
return scene;
}
-(void) dealloc{
[super dealloc];
}
-(void) achievementViewControllerDidFinish:(GKAchievementViewController *)viewController{
AppController *app = (AppController*) [[UIApplication sharedApplication] delegate];
[[app navController] dismissModalViewControllerAnimated:YES];
}
-(void) leaderboardViewControllerDidFinish:(GKLeaderboardViewController *)viewController{
AppController *app = (AppController*) [[UIApplication sharedApplication] delegate];
[[app navController] dismissModalViewControllerAnimated:YES];
}
#end
Any thoughts?
Jake
It seems that you called a class method(+) where you need to call the instance method(-). You just need to reset all the resources but not the whole object. And, as a class method, your +(void)resetAll method is meaningless for it has no return value.
I suggest, you may put all your resource-init codes into a single method, when you need to restart, just call [self removeAllChildrenWithCleanup:] and call that specified resource-init method.

collision detection only happen top of the screen

i am going to make a very simple game like a sprite falling from top and i have to catch it with another sprite , if i don't the sprite will go outside the screen and remove ,, that part is ok , i also add collision detection , main problem is this collision only happen upper side of the screen not collision bottom side of the screen ,why is this happening please help ,(i am new :S),, here is full code
in my .h`then .m
{
CCSprite *right;
CCSprite *left;
NSMutableArray *_left;
}
-(void)ringcreate:(ccTime)dt
{
CGSize winsize = [[CCDirector sharedDirector] winSize];
int minX = left.contentSize.width / 2;
int maxX = winsize.width - left.contentSize.width/2;
int rangeX = maxX - minX;
int actualX = (arc4random() % rangeX) + minX;
left = [CCSprite spriteWithFile:#"2.png"];
left.position = ccp(actualX,winsize.height);
[self addChild:left];
id move3 = [CCMoveTo actionWithDuration:5 position:ccp(winsize.width/2,0)];
[left runAction:move3];
}
-(id) init
{
// always call "super" init
// Apple recommends to re-assign "self" with the "super's" return value
if( (self=[super init]) ) {
self.touchEnabled = YES;
right = [CCSprite spriteWithFile:#"1.png"];
right.position = ccp(0,0);
[self addChild:right];
[self schedule:#selector(ringcreate:) interval:2];
[self schedule:#selector(update:)];
}
return self;
}
-(void) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch =[touches anyObject];
CGPoint location =[touch locationInView:[touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
id move = [CCMoveTo actionWithDuration:1 position:ccp(location.x,location.y)];
[right runAction:move];
}
-(void) update:(ccTime)dt
{
if (CGRectIntersectsRect(right.boundingBox, left.boundingBox)) {
CCLOG(#"collison hoyse");
id move1 = [CCScaleTo actionWithDuration:0.4 scale:0.3];
left.visible = NO;
[left runAction:move1];
}
}
i solved the problem , i just have to add array and update them wining that method ,
-(void) update:(ccTime)dt
{
NSMutableArray *crabToUpdate = [[NSMutableArray alloc] init];
for (CCSprite *crab in crabarray) {
NSMutableArray *ring_to_delete = [[NSMutableArray alloc] init];
for (ring1 in ringarray) {
if (CGRectIntersectsRect(crab.boundingBox, ring1.boundingBox)) {
[ring_to_delete addObject:ring1];
}
}
for (CCSprite *ring1 in ring_to_delete) {
[ringarray removeObject:ring1];
[self removeChild:ring1 cleanup:YES];
}
if (ring_to_delete.count >0) {
[crabToUpdate addObject:crab];
}
[ring_to_delete release];
}
}

Delegate not working between HudLayer and GameLayer

I have created a HudLayer class which defines a protocol for when button presses happen.
-(id) init
{
if( (self=[super initWithColor:ccc4(255, 255, 0, 128)])) {
self.position=ccp(0,0);
self.contentSize=CGSizeMake(480, 40);
scoreLabel=[CCLabelTTF labelWithString:#"0" fontName:#"Marker Felt" fontSize:24];
scoreLabel.position=ccp(62,20);
scoreLabel.anchorPoint=ccp(0,0.5);
[self addChild:scoreLabel];
CCLabelTTF *textLabel=[CCLabelTTF labelWithString:#"Score:" fontName:#"Marker Felt" fontSize:24];
textLabel.position=ccp(5,20);
textLabel.anchorPoint=ccp(0,0.5);
[self addChild:textLabel];
CCMenuItemImage * item = [CCMenuItemImage itemWithNormalImage:#"fire.png" selectedImage:#"fire.png" target:self selector:#selector(projectileButtonTapped:)];
CCMenu *menu = [CCMenu menuWithItems:item, nil];
menu.position = ccp(150, 20);
[self addChild:menu];
}
return self;
}
- (void)projectileButtonTapped:(id)sender
{
NSLog(#"projectileButtonTapped HudLayer");
[self.delegate respondsToSelector:#selector(projectileButtonTapped:)];
}
Then in my HelloWorldLayer class I implement the protocol and set myself as the delegate.
+(CCScene *) scene
{
// 'scene' is an autorelease object.
CCScene *scene = [CCScene node];
// 'layer' is an autorelease object.
HelloWorldLayer *layer = [HelloWorldLayer node];
// add layer as a child to scene
[scene addChild: layer];
//add another layer to the scene
// HudLayer *anotherLayer = [HudLayer node];
// anotherLayer.delegate = self;
// [scene addChild: anotherLayer];
// layer.hud=anotherLayer;
// return the scene
return scene;
}
-(id) init
{
if( (self=[super init]) ) {
_tileMap = [CCTMXTiledMap tiledMapWithTMXFile:#"GridWars#medium.tmx"];
_background = [_tileMap layerNamed:#"Background"];
_foreground = [_tileMap layerNamed:#"Foreground"];
_meta = [_tileMap layerNamed:#"Meta"];
_meta.visible = NO;
CCTMXObjectGroup *objectGroup = [_tileMap objectGroupNamed:#"Objects"];
NSAssert(objectGroup != nil, #"tile map has no objects object layer");
NSDictionary *spawnPoint = [objectGroup objectNamed:#"SpawnPoint"];
int x = [spawnPoint[#"x"] integerValue];
int y = [spawnPoint[#"y"] integerValue];
_wizardHero = [[WizardHero alloc]init];
_redEnemy = [[RedEnemy alloc]init];
_wizardHero.position = ccp(x,y);
[self addChild:_wizardHero];
[self setViewPointCenter:_wizardHero.position];
[self addChild:_tileMap z:-1];
self.touchEnabled = YES;
self.enemies = [[NSMutableArray alloc] init];
self.projectiles = [[NSMutableArray alloc] init];
[self schedule:#selector(testCollisions:)];
for (spawnPoint in [objectGroup objects]) {
if ([[spawnPoint valueForKey:#"Enemy"] intValue] == 1){
x = [[spawnPoint valueForKey:#"x"] intValue];
y = [[spawnPoint valueForKey:#"y"] intValue];
[self addEnemyAtX:x y:y];
}
}
_hud = [HudLayer node];
_hud.delegate = self;
[self addChild:_hud];
}
return self;
}
- (void)projectileButtonTapped:(id)sender
{
// Find where the touch is
// CGPoint touchLocation = [touch locationInView: [touch view]];
// touchLocation = [[CCDirector sharedDirector] convertToGL: touchLocation];
// touchLocation = [self convertToNodeSpace:touchLocation];
if (self.wizardHero.selectedTargets.count > 0) {
// Create a projectile and put it at the player's location
CCSprite *projectile = [CCSprite spriteWithFile:#"Projectile.png"];
projectile.position = _wizardHero.position;
[self addChild:projectile];
// Determine where we wish to shoot the projectile to
int realX;
// Are we shooting to the left or right?
CGPoint diff = ccpSub(self.redEnemy.position, self.wizardHero.position);
if (diff.x > 0)
{
realX = (_tileMap.mapSize.width * _tileMap.tileSize.width) +
(projectile.contentSize.width/2);
} else {
realX = -(_tileMap.mapSize.width * _tileMap.tileSize.width) -
(projectile.contentSize.width/2);
}
float ratio = (float) diff.y / (float) diff.x;
int realY = ((realX - projectile.position.x) * ratio) + projectile.position.y;
CGPoint realDest = ccp(realX, realY);
// Determine the length of how far we're shooting
int offRealX = realX - projectile.position.x;
int offRealY = realY - projectile.position.y;
float length = sqrtf((offRealX*offRealX) + (offRealY*offRealY));
float velocity = 480/1; // 480pixels/1sec
float realMoveDuration = length/velocity;
// Move projectile to actual endpoint
id actionMoveDone = [CCCallFuncN actionWithTarget:self
selector:#selector(projectileMoveFinished:)];
[projectile runAction:
[CCSequence actionOne:
[CCMoveTo actionWithDuration: realMoveDuration
position: realDest]
two: actionMoveDone]];
[self.projectiles addObject:projectile];
}
}
The problem is that only the projectileButtonTapped: in the HudLayer is called (ie. the delegate's method never gets called).
P.S.
To save space I left out both .h files. But I assure you they are correct, with the #protocol used in HudLayer and that same protocol name put in <> within the HelloWorldLayer.
I think :
- (void)projectileButtonTapped:(id)sender
{
NSLog(#"projectileButtonTapped HudLayer");
if ([self.delegate respondsToSelector:#selector(projectileButtonTapped:)]) {
[self.delegate performSelector:#selector(projectileButtonTapped:) withObject:sender];
}
}

Resources