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

Posted

技术标签:

【中文标题】Cocos2D:如何在不同类之间发送事件【英文标题】:Cocos2D: How to send events between different classes 【发布时间】:2012-10-22 17:42:54 【问题描述】:

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

我有 GameSceneLayer,一个 CCLayer 类,它加载到我的不同 CCLayer 的 Sprites 中:

@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 精灵被触摸时,我希望它从 Player CCLayer 的 PLAYER 精灵中生成。

我猜我需要一个 GlobalVariables.h 类似的东西:

 #define gameStart @"0"

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

 if (gameStart == 1)

    [self addChild:PLAYER];

但是我不确定如何设置代码,以便播放器精灵始终在寻找该信息。

【问题讨论】:

看看 NSNotifications。他们可能会在您的情况下为您提供帮助。 除了你的单身教条工具包......继续寻找:) 【参考方案1】:

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

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

或者您可以简单地让他们互相交谈,但可惜他们不应该这样做。由于两者都是 GameSceneLayer 的兄弟姐妹,因此它们本身不应持有彼此的引用(除非您使用弱引用,否则会产生保留循环的危险)。

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

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

[(GameSceneLayer*)self.parent gameWillStart];

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

-(void) gameWillStart

    [player gameWillStart];
    [ingameUI gameWillStart];
    // etc.

而且 Player 也实现了所说的选择器:

-(void) gameWillStart

    [self addChild:PLAYER];

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

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

【讨论】:

成功了!尽管 ios 6/iPhone5 已经发布,您的书是否仍然具有相关性,还是即将更新?我会买的。【参考方案2】:

您可以使用单例 GameState 管理器,它保存有关游戏状态的信息。

这是一个小sn-p:

+(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
          
   

【讨论】:

以上是关于Cocos2D:如何在不同类之间发送事件的主要内容,如果未能解决你的问题,请参考以下文章

如何使用dart / flutter在不同类上使用变量

如何在不消耗事件的情况下监听事件

个人技术博客

如何在不知道标识符的情况下向聚合发送命令?

如何在Prism框架中的模块之间正确发送事件消息?

在不同类的构造函数中创建对象的动态数组