Доступ к объектам в других слоях (cocos2d) - PullRequest
5 голосов
/ 01 марта 2012

Я играл с джойстиком, перемещая спрайт в одном слое. Теперь, согласно лучшей практике, джойстик и спрайт должны находиться в разных слоях одной и той же сцены. Мне удалось отделить их, но я теперь совершенно застрял, не имея ни малейшего понятия, как передавать команды джойстика из одного слоя в другой? Каков рекомендуемый способ сделать это?

Сцена

  • Уровень игры
    • Sprite
  • Уровень управления игрой
    • Джойстик

Когда джойстиком манипулируют, мне нужно передать эту информацию GamePlayLayer для управления спрайтом.

1 Ответ

5 голосов
/ 02 марта 2012

Что ж, я получил отличную книгу по Cocos2d, написанную Родом Строго и Рэем Вендерлихом под названием «Изучение Cocos2d».В своей книге они реализуют игру, в которой реализован джойстик и все, используя вашу первоначальную настройку.GamePlayLayer содержит как джойстик, так и спрайт героя.(См. Стр. 40).

Я не верю, что они использовали бы плохие практики в своей книге, учитывая, что они очень талантливы!

...

С этимПри этом у меня есть возможные решения, если вы хотите реализовать их на отдельных уровнях:

GameScene
|
|__>GameLayer
|
|__>ControlLayer

Это ваша основная установка.Но, интуитивно, какова цель уровня управления?Управляйте содержанием игрового слоя!Итак, я бы посоветовал вам иметь (слабую) ссылку на GameLayer в ControlLayer.Таким образом, используя простое:

@property (nonatomic, assign) CCSprite* hero;

, теперь у вас есть доступ к герою из ControlLayer!

Дополнительно (при необходимости):

//GameScene init:
- (id)init {
    ....
    gameLayer = [GameLayer node];
    controlLayer = [ControlLayer node];
    [controlLayer setGameLayerRef:gameLayer];
    ...
}

// Control layer:
@property (nonatomic, assign) GameLayer* gameLayerRef;

Даже еслиЯ просто предложил этот способ, я не использую его в своих играх:)

Что я обычно делаю, это:

Сделайте класс GameScene «Полу-синглтоном».(Я изучил этот метод из «Изучения iPhone и iPad Game Dev» Иттерхайма (он же игровой ужас, издатель Kobold2d и т. Д.).

Затем внутри слоя управления я бы вызвал объект GameScene:

[[GameScene sharedScene] doSomethingToTheGameLayer];

Да, у gameScene есть упрощенные методы, которые просто зависят от того, что нужно обновить элемент управления в игровом слое.

Редактировать:

Реализация модели полу-синглтона, как описано Иттерхеймом в его книге.

Но что такое полу-синглтон?

Он имеет свойство одноэлементного шаблона: вы можете получить доступ к экземпляру объекта из любого места, используя статический вызов.

[GameScene sharedScene];

Однако одноэлементные объекты обычно сохраняются после первого создания до концажизни приложения.В шаблоне Semi-singleton это не так.

После создания экземпляра вы не можете создать другой экземпляр до того, как уничтожите старый, НО, как только вы закончите с экземпляром, вы уничтожитеэто (dealloc) .Создание другого при необходимости.

Резюме: Полу-синглтон: Создайте из него много объектов, но только один в любой момент времени.Воссоздавать только после уничтожения старого.

Реализация:

Конечно, как и в случае с любым одноэлементным классом, вы сначала объявляете статическую переменную того же типа, что икласс:

//In GameScene.m
static GameScene* instance = nil;

@implementation

//Here we have the static method to access the instance:
+(GameScene*)sharedScene {
    //you must have created one before trying to access it "Globally".
    ///Typically, created where you transition the GameScene using CCDirector's replaceScene.
    NSAssert(instance != nil, @"GameScene not instantiated!!");
    return instance;
}

-(id)init {
    if((self = [super init])) {
        //Make sure you don't have another instance of the class created
        //NOTE: Possible race condition that I wouldn't worry about, since it should never happen.
        NSAssert(instance == nil, @"Another instance is already created!!");
        instance = self;

        ...
    }
    return self;
}

//Don't forget!! Dealloc!!
- (void)dealloc {
    //the only instance we had is dealloc'd! We are back to zero. Can create a new one later! :D
    instance = nil;
    [super dealloc];
}

Edit2:

Итак, график времени:

CCScene* scene = [GameScene node];
[[CCDirector sharedDirector] replaceScene:scene];
...
[[GameScene sharedScene] doSomething];
...
[[CCDirector sharedDirector] replaceScene:otherScene];
//After the new scene replaces GameScene, dealloc will be called, implicitly. Making instance = nil;
instance = nil;
[super dealloc];
...
//Loop again
CCScene* scene = [GameScene node];
[[CCDirector sharedDirector] replaceScene:scene];
...
...