Cocos2D + Storyboards,实现Play Again功能并重新加载游戏场景

Posted

技术标签:

【中文标题】Cocos2D + Storyboards,实现Play Again功能并重新加载游戏场景【英文标题】:Cocos2D + Storyboards, implement Play Again feature and reload the game scene 【发布时间】:2014-05-20 10:22:05 【问题描述】:

我在一个故事板项目中集成了一个 Cocos2d 游戏。下面是故事板。当游戏结束时(onExit 方法),我向CocosViewController 发送通知并从那里执行segue,打开ScoreViewController。这工作正常。此外,当用户按下ScoreViewController 中的“再次播放” 按钮时,我想再次加载游戏。

我尝试了一个 unwind segue,它打开了CocosViewController,但它没有加载游戏,它立即返回到ScoreViewController。如何实现 Play Again 功能?也许有一个segue?

CocosViewController

 -(void)setupCocos2d 
    CCDirector *director = [CCDirector sharedDirector];
    //[[[self navigationController] navigationBar] setHidden:YES];


    if([director isViewLoaded] == NO)
    
    // Create the OpenGL view that Cocos2D will render to.
    CCGLView *glView = [CCGLView viewWithFrame:self.view.bounds
                                   pixelFormat:kEAGLColorFormatRGB565
                                   depthFormat:0
                            preserveBackbuffer:NO
                                    sharegroup:nil
                                 multiSampling:NO
                               numberOfSamples:0];

        // Assign the view to the director.
        director.view = glView;


        // Initialize other director settings.
        [director setAnimationInterval:1.0f/60.0f];
        [director enableRetinaDisplay:YES];
    

    // Set the view controller as the director's delegate, so we can respond to certain events.
    director.delegate = self;

    // Add the director as a child view controller of this view controller.
    [self addChildViewController:director];


    // Add the director's OpenGL view as a subview so we can see it.
    [self.view addSubview:director.view];
    [self.view sendSubviewToBack:director.view];

    // Finish up our view controller containment responsibilities.
    [director didMoveToParentViewController:self];

    // Run whatever scene we'd like to run here.
    NSArray *parameters = [[NSArray alloc] initWithObjects:@"3", @"sound", @"countdown", nil];

    if(director.runningScene)
        [director replaceScene:[IntroLayer sceneWithParameters:parameters]];
    else
        [director pushScene:[IntroLayer sceneWithParameters:parameters]];



-(void) viewDidAppear:(BOOL)animated
    [super viewDidAppear:animated];

    [self setupCocos2d];


- (void)viewDidLoad

    [super viewDidLoad];

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



-(void)receiveNotificationFromGame:(NSNotification *) notification

    if ([[notification name] isEqualToString:@"GameEndedNotification"])
    
        NSLog (@"Successfully received the test notification! %@", [self class]);
        NSLog(@"score: %d", [notification.userInfo[@"score"] intValue]);

        //get variables
        score = [notification.userInfo[@"score"] intValue];
        gameTracking = notification.userInfo[@"gameTracking"];

        //show the next view
        [self performSegueWithIdentifier:@"sg_showScore" sender:self];
    


- (IBAction)unwindToCocosViewController:(UIStoryboardSegue *)sender 
    //nothing goes there

这就是我初始化 cocos2d 游戏的方式:

-(id) initWithParameters:(NSArray *) parameters

    NSLog(@"init TheButton with parameters");

    // Apple recommend assigning self with supers return value
    self = [super init];
    if (!self) return(nil);

   gameParameters = parameters;

    // Enable touch handling on scene node
    [self setIsTouchEnabled:YES];

    // Create a colored background (Dark Grey)
    //CCNodeColor *background = [CCNodeColor nodeWithColor:[CCColor colorWithRed:0.6f green:0.6f blue:0.6f alpha:1.0f]];
    //[self addChild:background];

    CCMenuItem *starMenuItem = [CCMenuItemImage
                                itemFromNormalImage:@"ButtonStar.png" selectedImage:@"ButtonStarSel.png"
                                target:self selector:@selector(increasePoints:)];
    CGSize size = [[CCDirector sharedDirector] winSize];
    starMenuItem.anchorPoint = ccp(0.5f,0.5f);
    starMenuItem.position = ccp(size.width/2, size.height/2);
    CCMenu *starMenu = [CCMenu menuWithItems:starMenuItem, nil];
    starMenu.position = CGPointZero;
    [self addChild:starMenu];

    timeLabel = [CCLabelTTF labelWithString:@"0.00" fontName:@"Arial" fontSize:18.0f];
    //timeLabel.positionType = CCPositionTypeNormalized;
    timeLabel.position = ccp(30,size.height-10);
    // Add the time label
    [self addChild:timeLabel];
    NSLog(@"time: %@", [gameParameters objectAtIndex:0]);

    clicksLabel = [CCLabelTTF labelWithString:@"0" fontName:@"Arial" fontSize:18.0f];
    //clicksLabel.positionType = CCPositionTypeNormalized;
    clicksLabel.position = ccp(size.width - 20,size.height-10);
    // Add the time label
    [self addChild:clicksLabel];

    [self startGame];

    return self;



-(void) startGame

    clicks = 0;
    myTime = [[gameParameters objectAtIndex:0] intValue];

    [self schedule:@selector(update:)];


【问题讨论】:

【参考方案1】:

您不需要在-setupCocos2d 中重新添加 glView,因为它已经添加了。我不确定这是否是错误行为的唯一原因,但尝试将此方法调用从viewDidAppear-viewDidLoad,当从ScoreViewController 返回时,只需重置您的 Cocos2d 引擎(例如清除所有标签或移除敌人)而不重新创建视图。

但是,你的方法不是很好,我强烈建议你用 Cocos2d 制作所有场景,而不是 UIViewControllers。场景之间也有很好的过渡(至少在 Cocos2d 3.0 中)。

【讨论】:

我将方法放在 viewDidLoad 但现在场景是纵向而不是横向。另外,如何重置 Cocos2d 引擎?它加载了场景,但倒计时为 0,完成时分数相同。 @nabrugir 我所说的“重置引擎”的意思 - 将分数设置为 0,从头开始倒计时以及您在游戏开始前所做的一切。不知道为什么方向改变了。 我应该从哪里做这个?来自 cocosviewcontroller 还是来自游戏?可以举个例子吗? @nabrugir 我不知道你是如何设置分数的。在游戏开始时,您如何将倒计时和得分设置为适当的值?点击“再次播放”按钮后,您应该执行完全相同的操作 我在问题中添加了源代码。但是主要问题是我不知道如何在第二次加载游戏时调用 [self startgame],因为 onEnter 和 initWithParameters 都没有被调用。

以上是关于Cocos2D + Storyboards,实现Play Again功能并重新加载游戏场景的主要内容,如果未能解决你的问题,请参考以下文章

将项目从 XIB/NIB 移动到 Storyboards

如何在 cocos2d 环境之外实现 cocos2d 游戏的虚拟摇杆?

Silverlight & Blend动画设计系列五:故事板(StoryBoards)和动画(Animations)

Cocos2D实现上下滚动式状态窗口

cocos2d-实现读取.plist文件(使用数组CCArray)

如何为 cocos2d 应用程序设置单元测试?