私は、次の書籍http://www.apress.com/9781430233039に続いて、iphone用のcocos2dを学ぼうとしています。ソースコード(http://www.apress.com/downloadable/download/sample/sample_id/640/)のCH_08フォルダにあるShootEmUp3サンプルを変更しました。iphone用のcocos2dの割り当てシステムの問題点
私が達成したいのは、メニューシーンとゲームシーンを持ち、ゲームシーンが終了すると(たとえばすべてのライフが失われた)メニューシーンに戻ることができることです。メニューシーンからは、 "LevelIcon"というクラスのアイコンであるアイコンをクリックすることで、特定のGameSceneにアクセスできます。言い換えると、 "Navigator"(CCLayerのサブクラス)と呼ばれるメニューシーンは、メニューシーンに現れる "LevelIcon"クラス(NSObjectのサブクラス)と、CCDirectorのreplaceSceneメソッドを呼び出すことによってタッチイベントに応答すること、 次のように:。
//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メソッドでオブジェクトを解放しようとしましたが、私はreleaseメソッドが呼び出されないことが判明LevelIconの解除方法にCCLOGメッセージを追加します。
//From Navigator.m
-(void)dealloc
{
CCLOG(@"Navigator dealloc");
CCLOG(@"%@: %@", NSStringFromSelector(_cmd), self);
level1 = nil;
[level1 dealloc];
[super dealloc];
}
私はその後、更新方法でログを追加し、それはまだシーンがGameSceneなくナビゲーターシーンであっても呼ばれていた観察。私が理解できないことは、LevelIconがNavigatorで作成されたオブジェクトであり、Navigatorのdeallocメソッドでは、上に示したクラスのistanceを解放しようとしました(ですが、はしません)。
本の確認として、私はGameSceneに次のコードをトリガするためにGameSceneからのナビゲーターに戻すと、前方に行くことを試みた:
Navigator * navigator = [Navigator scene];
[[CCDirector sharedDirector] replaceScene:navigator];
また、新しいナビゲータークラスの作成が適切に動作しますが、 GameSceneに戻ると、新しいLevelIconクラスインスタンスは消えず、残っています(累積するように)。このイベントの後ナビゲーター解除方法はLevelIconと複数の場合と呼ばれていない、つまり
GameScene * game = [GameScene scene];
[[CCDirector sharedDirector] replaceScene:game];
を:私たちは、次のようreplaceScene方法は、タッチイベントに応答LevelIconクラス内から呼び出されていることに気づくしなければなりませんLevelIconクラスはメモリ内でアクティブなままです。
私は間違っていますが、いくつかのヒントや助けに感謝します。
また、(addChildメソッドを使用して)Navigatorの子としてLevelIconのistanceを追加することで、別のアプローチを試みましたが、NSObjectクラスから派生し、cocos2d Nodeクラスから派生しているため動作しません。何とかこれを調整するのが理にかなっているのか、2つの異なるクラス階層(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
感謝を!:)
こんにちは、投稿していただきありがとうございます。私はNavi deallocメソッドを変更して、無割り当てを取り除き、 '[level1 release];を呼び出しました;' LevelIcon releaseメソッドを2回呼び出すときにコードがクラッシュするようになりました。 '(2012-01-03 14:48:54.506 ShootEmUp [6120 :207] Navigator dealloc 2012-01-03 14:48:54.507 ShootEmUp [6120:207] dealloc: 2012-01-03 14:48:54.507 ShootEmUp [6120:207 ]レベルアイコンdealloc 2012-01-03 14:48:54.508 ShootEmUp [6120:207]レベルアイコンdealloc) ' –
mm24
また、{[CCTouchDispatcher sharedDispatcher] removeDelegate:self];'をccTouchBeganメソッドから削除しようとしました。 LevelIconは、それがダブルアロケーションを引き起こしたかもしれないと思っていますが、そうするときには(上に掲示されているコードに示されているようにdeallocでのみコールを残します。 – mm24