Cocos2D:如何在不同类之间发送事件

时间:2012-10-22 17:42:54

标签: ios events cocos2d-iphone cclayer game-loop

我读过的大部分教程只解释了HelloWorld类中的Cocos2D示例,但是当我开始构建一个简单的游戏时,我需要知道如何将事件发送到不同的类,并让他们响应无论何时发生。

我有GameSceneLayer,一个CCLayer类,它加载在我不同的精灵CCLayers中:

@implementation GameSceneLayer
+ (CCScene *)scene {
    CCScene *scene = [CCScene node]; // Create a container scene instance
    GameSceneLayer *gameLayer = [GameSceneLayer node]; // Create an instance of the current layer class
    [scene addChild:gameLayer]; // Add new layer to container scene
    return scene; // Return ready-made scene and layer in one
}
-(id)init
{
self = [super init];
if (self != nil)
{
    Background *background = [Background node];
    [self addChild:background z:0];
    Player *player = [player node];
    [self addChild:player z:1];
    MainMenu *mainMenu = [MainMenu node];
    [self addChild:mainMenu z:2];

}
return self;
}
@end

然而,当触摸我的MainMenu CCLayer START精灵时,我希望它从玩家CCLayer中的PLAYER精灵中产生。

我猜我需要一个类似于:

的GlobalVariables.h
 #define gameStart @"0"

因此,当按下START精灵时,它会将gameStart更改为1,并且PLAYER精灵中的某个地方有

 if (gameStart == 1)
{
    [self addChild:PLAYER];
}

但是我不确定如何设置代码,以便PLAYER精灵始终在寻找这些信息。

2 个答案:

答案 0 :(得分:1)

你有对象(类的实例)。您希望一个对象与另一个对象进行通信。在Objective-C中,这称为发送消息。在其他语言中,它只是调用方法。

您不需要全局变量。相反,接收对象MainMenu需要向Player对象发送消息(调用方法)。你如何让两个物体相互认识?你可以把它们放在一个臭,声,过度拥挤的迪斯科舞厅里,并希望最好。

或者你可以简单地让他们互相交谈,但唉,他们不应该。由于两者都是GameSceneLayer的兄弟,因此他们不应该自己保持对彼此的引用(除非你使用弱引用,否则创建保留周期的危险)。

但两者都有同一个父母。那么,当两个兄弟姐妹不会互相交谈时,一个好父母会怎么做?它传达了这个信息!

在MainMenu中,向父GameSceneLayer发送消息:

[(GameSceneLayer*)self.parent gameWillStart];

GameSceneLayer实现了该选择器,并将消息转发给任何其他应该被告知开始游戏的对象:

-(void) gameWillStart
{
    [player gameWillStart];
    [ingameUI gameWillStart];
    // etc.
}

播放器还实现了所述选择器:

-(void) gameWillStart
{
    [self addChild:PLAYER];
}

另外一件事:在GameSceneLayer中,制作播放器和所有其他对象ivars(实例变量),以便GameSceneLayer可以随时使用这些引用。另一种方法是标记(不太常用)对象,然后使用getChildByTag:

PS:加入PLAYER,因为孩子看起来很可疑。如果你已经创建了任何PLAYER节点,你应该立即添加它,如果有必要,在游戏尚未开始时将其设置为不可见和/或暂停。

答案 1 :(得分:0)

您可以使用单身GameState Manager,它可以保存有关游戏状态的信息。

这是一个小片段:

+(GameManager*) sharedGameManager {
if (!_sharedGameManager) {
    _sharedGameManager = [[self alloc] init];
}
return _sharedGameManager;
}

+(id) alloc {
    NSAssert(_sharedGameManager == nil, @"Cannot create second instance of singleton Game Manager");
    return [super alloc];
}

- (id)init
{
    self = [super init];
    if (self) {

    }
    return self;
}

在该游戏管理器中,您可以拥有游戏状态的枚举,并为其设置属性。

//Header

typedef enum {
     kGameStarted,
     kGameEnded
 }GameState

@interface GameManager : CCNode {

}
@property (nonatomic) GameSate gameState;

然后返回实现文件,合成该GameState属性,并创建自己的setter

//Implementation
@synthesize gameState = _gameState;

//Create your own setter, so you can notify all listeners
    -(void) setGameState:(GameState) newGameState {
    if (newGameState != _gameState) {
        _gameState = newGameState;

        //Notify listeners via NSNotification
        [[NSNotificationCenter defaultCenter] postNotificationName:@"gameState" object:nil];
    }
}

在您想要获取消息的类中,您只需订阅“gameState”通知,如下所示:

[[NSNotificationCenter defaultCenter] addObserver:self
        selector:@selector(onGameStateChange:) 
        name:@"gameState"
        object:nil];



  -(void) onGameStateChange{
          if ([GameManager sharedManager].gameState == kGameStarted){
          //start game
          }
   }