Я пытаюсь узнать cocos2d для iphone, следуя следующей книге http://www.apress.com/9781430233039. Я изменил пример ShootEmUp3, доступный в папке CH_08 исходного кода (http://www.apress.com/downloadable/download/sample/sample_id/640/).
Что я хочу сделатьДля этого нужно иметь сцену меню и игровую сцену, и иметь возможность вернуться к сцене меню после завершения игровой сцены (например, все жизни потеряны). Из сцены меню я могу получить доступ к определенной GameScene, нажав назначки, которые являются экземплярами класса с именем «LevelIcon». Другими словами, сцена меню, которую я назвал «Navigator» (подкласс CCLayer), содержит экземпляры класса «LevelIcon» (подкласс NSObject), появляющегося в сцене меню иотвечая на событие касания, вызывая метод replaceScene в CCDirector, следующим образом:.
//From LevelIcon.m
-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
CCLOG(@"Touch");
[[CCTouchDispatcher sharedDispatcher] removeDelegate:self];
GameScene * game = [GameScene scene];
[[CCDirector sharedDirector] replaceScene:game];
return TRUE;
}
Я пытался освободить объекты в методе навигатора dealloc, но, добавив сообщение CCLOG в методе освобождения LevelIcon Iобнаружил, что метод выпуска никогда не вызывается.
//From Navigator.m
-(void)dealloc
{
CCLOG(@"Navigator dealloc");
CCLOG(@"%@: %@", NSStringFromSelector(_cmd), self);
level1 = nil;
[level1 dealloc];
[super dealloc];
}
Затем я добавил журнал в UМетод pdate и заметил, что он все еще вызывается, даже если сцена была GameScene, а не сцена Navigator.Я не могу понять, что LevelIcon был объектом, созданным в Navigator, и в методе dealloc в Navigator я пытался освободить istance класса, как показано выше (, но не делает этого ).
В подтверждение этого я попытался вернуться назад и переместиться из GameScene в Navigator, чтобы вызвать следующий фрагмент кода в GameScene:
Navigator * navigator = [Navigator scene];
[[CCDirector sharedDirector] replaceScene:navigator];
И создание нового класса Navigator работаетправильно, но при возвращении в GameScene новый экземпляр класса LevelIcon не исчезает, а остается (так что он накапливается).Мы должны отметить, что метод replaceScene вызывается из класса LevelIcon, отвечая на событие касания следующим образом:
GameScene * game = [GameScene scene];
[[CCDirector sharedDirector] replaceScene:game];
Другими словами, после этого события вызывается метод выпуска Navigator, а не LevelIcon иесли несколько раз класс LevelIcon остается активным в памяти.
Я не уверен, что делаю неправильно, но был бы признателен за подсказку или помощь.
Я также попробовал другой подход, добавив istiance LevelIcon как дочерний элемент Navigator (используя метод addChild), но он не работает, потому что является производным от класса NSObject, а не от класса Node cocos2d.Мне было интересно, имеет ли смысл это каким-то образом подправлять или это не так, как для двух разных иерархий классов (cocos2d и NS / Objective-C).
Я вставляю полный код, чтобы помочь понять:
--NAVIGATOR.H-----
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#import "LevelIcon.h"
@interface Navigator : CCLayer {
LevelIcon *level1;
}
+ (id) scene;
@end
-----NAVIGATOR.M------
#import "Navigator.h"
#import "LevelIcon.h"
@implementation Navigator
+(id) scene {
CCScene *scene = [CCScene node];
CCLayer *layer = [Navigator node];//??
[scene addChild:layer];
return scene;
}
-(id)init
{
CCLOG(@"init");
if((self=[super init])){
CCLOG(@"%@: %@", NSStringFromSelector(_cmd), self);
self.isAccelerometerEnabled=YES;
self.isTouchEnabled = YES;
[self scheduleUpdate];
level1 = [LevelIcon levelIconWithParentNode:self];
}
return self;
}
-(void)dealloc
{
CCLOG(@"Navigator dealloc");
CCLOG(@"%@: %@", NSStringFromSelector(_cmd), self);
level1 = nil;
[level1 dealloc];
[super dealloc];
}
[..]
@end
------LEVELICON.H------------
#import <Foundation/Foundation.h>
#import "cocos2d.h"
@interface LevelIcon : NSObject<CCTargetedTouchDelegate> {
CCSprite* levelIconSprite;
}
+(id) levelIconWithParentNode:(CCNode*)parentNode;
-(id) initWithParentNode:(CCNode*)parentNode;
@end
-----LEVEL ICON.M----------------
#import "LevelIcon.h"
#import "GameScene.h"
@implementation LevelIcon
// Static autorelease initializer, mimics cocos2d's memory allocation scheme.
+(id) levelIconWithParentNode:(CCNode*)parentNode
{
CCLOG(@"levelIconWithParentNode");
return [[[self alloc] initWithParentNode:parentNode] autorelease];
}
-(id) initWithParentNode:(CCNode*)parentNode
{
CCLOG(@"initWithParentNode");
if ((self = [super init]))
{
CCLOG(@"initWithParentNode: inside if");
CGSize screenSize = [[CCDirector sharedDirector] winSize];
levelIconSprite = [CCSprite spriteWithFile:@"Icon.png"];
levelIconSprite.position = CGPointMake(CCRANDOM_0_1() * screenSize.width, CCRANDOM_0_1() * screenSize.height);
[parentNode addChild:levelIconSprite];
// Manually schedule update via the undocumented CCScheduler class used internally by CCNode.
[[CCScheduler sharedScheduler] scheduleUpdateForTarget:self priority:0 paused:NO];
// Manually add this class as receiver of targeted touch events.
[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:-1 swallowsTouches:YES];
}
return self;
}
-(void) dealloc
{
CCLOG(@"Level icon dealloc");
// Must manually unschedule, it is not done automatically for us.
[[CCScheduler sharedScheduler] unscheduleUpdateForTarget:self];
// Must manually remove this class as touch input receiver!
[[CCTouchDispatcher sharedDispatcher] removeDelegate:self];
[super dealloc];
}
-(void) update:(ccTime)delta
{
CCLOG(@"Icon Update!");
}
-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
CCLOG(@"Touch");
[[CCTouchDispatcher sharedDispatcher] removeDelegate:self];
GameScene * game = [GameScene scene];
[[CCDirector sharedDirector] replaceScene:game];
return TRUE;
}
@end
Спасибо за чтение!:)