Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/35.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 对Cocos2D的误解:图层、静态变量和模型视图控制器。这些能共存吗?_Iphone_Cocos2d Iphone_Background Music - Fatal编程技术网

Iphone 对Cocos2D的误解:图层、静态变量和模型视图控制器。这些能共存吗?

Iphone 对Cocos2D的误解:图层、静态变量和模型视图控制器。这些能共存吗?,iphone,cocos2d-iphone,background-music,Iphone,Cocos2d Iphone,Background Music,很抱歉,如果这个问题太枯燥了,但我一直试图从书中的代码示例中尽可能多地理解它,但无法理解它是如何工作的 在我的“HelloWorldLayer.m”中,我创建了一个名为“MusicLayer”的类的实例,该类扩展了CCLayer。其灵感在于,在名为“ShootEmUp”(的第8章)的示例中,有一个InputLayer。因此,我想我会创建一个音乐播放器来处理我在游戏中遇到的各种音乐文件,并解决一些问题(将在文章末尾解释)。我大部分的音乐相关代码都是从 但首先我想介绍一些可能导致这个问题的背景想法,

很抱歉,如果这个问题太枯燥了,但我一直试图从书中的代码示例中尽可能多地理解它,但无法理解它是如何工作的

在我的“HelloWorldLayer.m”中,我创建了一个名为“MusicLayer”的类的实例,该类扩展了CCLayer。其灵感在于,在名为“ShootEmUp”(的第8章)的示例中,有一个InputLayer。因此,我想我会创建一个音乐播放器来处理我在游戏中遇到的各种音乐文件,并解决一些问题(将在文章末尾解释)。我大部分的音乐相关代码都是从

但首先我想介绍一些可能导致这个问题的背景想法,希望能对此有一些明确的参考

我习惯了一个“模型-视图-控制器”()的方法,因为我来自C++和java背景,以前从未编码过游戏,而且我觉得游戏模式与“经典”软件工程大学的方法有点不同(别误会我的意思,我确信在很多大学里,他们不再教这些东西了)。)

重点是,在我看来,“经典”软件工程方法在这些示例中丢失了(例如,在ShooteMap代码中,InputLayer的实例引用了GameSecene类-见下文-同时在InputLayer中,引用了GameSecene的静态共享实例-见下文-)

我被告知静态实例是需要避免的。尽管如此,我理解拥有游戏场景staic实例的好处,但我仍然对双向引用感到困惑(从游戏场景到InputLayer和viceversa)…:

这是游戏编程中的常见做法吗?

有没有办法避免这种做法?

我现在将粘贴我的代码,我承认它可能是垃圾,可能会有一些明显的错误,因为我试图做一件非常简单的事情,我不管理

我们到了。这就是MusicLayer类(它包含注释掉的代码,正如我之前尝试将其作为共享类实例时所做的那样):

现在,我创建了一个新的Ccoos2d Helloworld模板,并将以下内容添加到.m类中以测试代码:

#import "cocos2d.h"
#import "MusicLayer.h"

enum tags {
    MUSICLAYERTAG = 99,
    };

// HelloWorldLayer
@interface HelloWorldLayer : CCLayer
{

}

+(CCScene *) scene;

@end


//
//  HelloWorldLayer.m
//  MusicFadingTest
//

// Import the interfaces
#import "HelloWorldLayer.h"

// HelloWorldLayer implementation
@implementation HelloWorldLayer

+(CCScene *) scene
{
    CCLOG(@"In helloworld scene");
    // 'scene' is an autorelease object.
    CCScene *scene = [CCScene node];

    // 'layer' is an autorelease object.
    HelloWorldLayer *layer = [HelloWorldLayer node];
    // add layer as a child to scene
    [scene addChild: layer];

    MusicLayer *musicLayer = [MusicLayer node];
    [musicLayer loadPopLevel];

    [scene addChild:musicLayer z:-1 tag:MUSICLAYERTAG];

    // return the scene
    return scene;
}

// on "init" you need to initialize your instance
-(id) init
{
    // always call "super" init
    // Apple recommends to re-assign "self" with the "super" return value
    if( (self=[super init])) {


        // ask director the the window size
        CGSize size = [[CCDirector sharedDirector] winSize];

        //Add menu items
        [CCMenuItemFont setFontSize:20];

        CCMenuItemFont *music0Item = [CCMenuItemFont itemFromString:@"Song A" target:self selector:@selector(play:)];
        music0Item.tag = 0;
        CCMenuItemFont *music1Item = [CCMenuItemFont itemFromString:@"Song B" target:self selector:@selector(play:)];
        music1Item.tag = 1;
        CCMenuItemFont *music2Item = [CCMenuItemFont itemFromString:@"Song C" target:self selector:@selector(play:)];
        music2Item.tag = 2;
        CCMenuItemFont *music3Item = [CCMenuItemFont itemFromString:@"Song D" target:self selector:@selector(play:)];
        music3Item.tag = 3;
        CCMenuItemFont *music4Item = [CCMenuItemFont itemFromString:@"Sound A" target:self selector:@selector(play:)];
        music2Item.tag = 4;
        CCMenuItemFont *music5Item = [CCMenuItemFont itemFromString:@"Sound B" target:self selector:@selector(play:)];
        music3Item.tag = 5;

        //Create our menus
        CCMenu *menu0 = [CCMenu menuWithItems:music0Item, music1Item,  music2Item,  music3Item,  music4Item,  music5Item, nil];
        [menu0 alignItemsInColumns: [NSNumber numberWithUnsignedInt:6], nil];
        menu0.position = ccp(240,240);
        [self addChild:menu0];
    }
    return self;
}

//Play music callback
-(void) play:(id)sender {

    CCNode* node = [self getChildByTag:MUSICLAYERTAG];
    NSAssert([node isKindOfClass:[MusicLayer class]], @"not a MusicLayer");

    MusicLayer *musicLayer = (MusicLayer*)node;

    CCMenuItem *item = (CCMenuItem*)sender;

    switch (item.tag ) {
        case 1:
            [musicLayer playBackgroundMusic:PLAYER_STANDARD];
            break;
        case 2:
            [musicLayer playBackgroundMusic:PLAYER_STANDARD];            
            break;

        case 3:
            [musicLayer playBackgroundMusic:PLAYER_STANDARD];            
            break;
        case 4:
            [musicLayer playBackgroundMusic:PLAYER_STANDARD];
            break;
        case 5:
            [musicLayer playSoundFile:A];
            break;
        case 6:
            [musicLayer playSoundFile:B];            
            break;
        default:
            break;
    }

 }

- (void) dealloc
{
     [super dealloc];
} 
@end
但是,当我尝试按下模拟器中的任何按钮并因此触发HelloWorld.m中的play方法时,我会收到一条错误消息

2012-04-23 10:39:18.493 MusicFadingTest[1474:10a03] In _loadMusic
2012-04-23 10:39:18.510 MusicFadingTest[1474:10a03] cocos2d: Frame interval: 1
2012-04-23 10:39:19.405 MusicFadingTest[1474:10a03] *** Assertion failure in -[HelloWorldLayer play:], /Users/user/Desktop/MusicFadingTest/MusicFadingTest/HelloWorldLayer.m:76
2012-04-23 10:39:19.406 MusicFadingTest[1474:10a03] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'not a MusicLayer'
*** First throw call stack:
(0x17f6022 0x1987cd6 0x179ea48 0x11c62cb 0xc264a 0x175c4ed 0x175c407 0x3a3b5 0x3ad73 0x37772 0x17f7e99 0x92821 0x9336f 0x95221 0x8573c0 0x8575e6 0x83ddc4 0x831634 0x27b1ef5 0x17ca195 0x172eff2 0x172d8da 0x172cd84 0x172cc9b 0x27b07d8 0x27b088a 0x82f626 0xc107f 0x2955)
上面的代码有点模仿ShooteMap示例中发生的情况,但我遗漏了一些东西。因为我无法通过标签找到孩子

我问了这个问题,尽管答案可能微不足道,但我希望能够澄清游戏编程中的非ModelViewController方法以及静态变量的使用

我想象在主菜单类和实现我的级别的各个层中使用我的MusicLayer。我会根据播放器播放的级别预加载各种音乐文件,并保留未按特定级别预加载的文件(显然要注意AudioEngine支持的最大声音文件数)

另一种方法是为每个级别使用不同的MusicLayer实例,并使用不同的音乐文件初始化它们。这种方法的缺点是sharedAudioEngine只有一个,当您想让文件在一个场景和另一个场景之间继续播放时,有可能无法完全控制sharedAudioEngine中使用的曲目编号(我记得声音效果应该是32个caf文件,背景曲目很少)

因此,我理解了为什么静态实例在游戏编程中是有益的,但我还是很想听听您对shootemap代码中的双向引用的看法

另外,我想澄清一下,我鼓励购买,因为这是一个很好的起点


多谢各位

哦,多少密码和字母。。。首先,关于“静态实例”的问题。这不是静态实例。这是静态构造函数。所以,你可以像这样使用smth

CCScene* myScene = [GameScene scene];
而不是

CCScene* myScene = [[GameScene alloc] init];
// doing smth
[myScene release];
因此,您只需创建节点的自动释放实例(在这种情况下,是场景的实例)

关于音乐问题。您已将音乐层添加到场景中,但播放方法中的self将是HelloWorldLayer实例。所以,如果你想得到你的音乐层,你可以尝试像这样的smth

MusicLayer* musicLayer = [[self parent] getChildByTag:MUSICLAYERTAG];

我不会再问这么长的问题了。。我应该把它一分为二。。对不起!啊啊,骄傲什么?不理解Cocos2D,不能有效地沟通:)?无论如何请记住,我很高兴有人(见下文)花时间回复。伟大的网站!我指的是“GameSecene*game=[GameSecene SharedGameSecene];”行,它返回GameSecene的静态实例,在调用静态构造函数后在init方法中分配该实例。如果您从shootemap示例下载代码(如上面的链接),您将看到。PS:我在[link]()中重新表述了这个问题,因为我认为这篇文章似乎渴望人们阅读和理解。我在一个问题中提出了太多的问题,因此我现在尝试将它们分成更简单的问题,因为还没有人能够给出明确的答案。谢谢:)我接受了答案,因为这对我解决问题很有帮助,如果有人有进一步的意见,请加:),谢谢!
CCScene* myScene = [GameScene scene];
CCScene* myScene = [[GameScene alloc] init];
// doing smth
[myScene release];
MusicLayer* musicLayer = [[self parent] getChildByTag:MUSICLAYERTAG];