Cocos2d-xna : 横版战略游戏开发实验3 Scene和Director场景切换

在上一篇中,使用CCSprite和CCMenu构建了开始场景,并且说明了关于优化程序内容的问题,一个好的游戏会有很多的场景场景组合,每个场景管理自身的脚本也就是规则,在整个游戏中是如何跳转场景的呢?先看下图:

本图来自Elvis的CCDirector类解析配图,先不用看太全面,只需要看最上面的就行了,前面说过,整个游戏有一个导演(CCDirector)在管理整个场景,为了让切换场景完成的更好,需要按照之前的场景制作方法将其他的场景补齐,即例如关卡选择界面、游戏界面、游戏结束界面的完成。

完成全部的场景

在制作前需要生成图片资源

QQ截图20120916221030

上面的资源中,包含了基本场景的元素,和一张用来演示游戏界面的示意图,打开TexturePackerGUI,将它们组合,由于有几张比较大的图,制作的时候看看是否有浪费,也可以将它们分成多个plist,比如说,我这次将一定会用上的图片打包到GameUI01.plist,而预览图就打包到了GameUI02.plist中,将它们添加到Content里:

image

好了,现在有了两个资源plist,GameUI01在SceneStart类中载入过,为了保证资源载入的统一性,建立一个GameRoot的类,并用静态的方法取得,不要忘记将SceneStart里的addSpriteFramesWithFile删除:

public class GameRoot

{

    public static void InitializeResource()

    {

        CCSpriteFrameCache.sharedSpriteFrameCache().addSpriteFramesWithFile("GameUI01", "images/GameUI01");

        CCSpriteFrameCache.sharedSpriteFrameCache().addSpriteFramesWithFile("GameUI02", "images/GameUI02");

    }

}

注意要把GameRoot.InitializeResource();添加到AppDelegate.cs的applicationDidFinishLaunching函数中,注意要添加到场景跳转的前面一行,这样场景在构建的时候就会先载入了图片资源。

也许有更好的方案,比如放在一个Loading界面里面,在这里GameRoot还有其他的作用,就如它的名字当成游戏根来处理,我们可以在这里将所有的场景集合管理,采用单例的方式完成全局的控制访问,我们可以这样做:

//通过一个全局的根来管理整个游戏的所有场景实例

public class GameRoot

{

    public static void InitializeResource()

    {

        CCSpriteFrameCache.sharedSpriteFrameCache().addSpriteFramesWithFile("GameUI01", "images/GameUI01");

        CCSpriteFrameCache.sharedSpriteFrameCache().addSpriteFramesWithFile("GameUI02", "images/GameUI02");

    }

        

    private static SceneStart _SceneStart;

    public static SceneStart pSceneStart

    {

        get

        {

            if (_SceneStart == null)

                _SceneStart = new SceneStart();

            return _SceneStart;

        }

    }



    private static SceneSelect _SceneSelect;

    public static SceneSelect pSceneSelect

    {

        get

        {

            if (_SceneSelect == null)

                _SceneSelect = new SceneSelect();

            return _SceneSelect;

        }

    }

    private static SceneGame _SceneGame;

    public static SceneGame pSceneGame

    {

        get

        {

            if (_SceneGame == null)

                _SceneGame = new SceneGame();

            return _SceneGame;

        }

    }

    private static SceneOver _SceneOver;

    public static SceneOver pSceneOver

    {

        get

        {

            if (_SceneOver == null)

                _SceneOver = new SceneOver();

            return _SceneOver;

        }

    }

}

由于比较长,给折叠了,在这里可以保证唯一的单例完成统一管理,在游戏的任何地方,都可以呼唤GameRoot取得场景实例了。

下面是SceneSelect类的代码,选择界面如果想做的复杂的话就得这么搞了,当然这样也更有趣,本篇该类代码只是实现了基本功能,未来在用到CCAction类的时候将它做到更完美:

public class SceneSelect : CCScene

{

    public SceneSelect()

    {

        base.init();

        //背景图

        CCSprite background = CCSprite.spriteWithSpriteFrameName("bg_select.png");

        background.anchorPoint = new CCPoint(0, 0);

        this.addChild(background);



        CCMenuItemSprite btn_back = CCMenuItemSprite.itemFromNormalSprite(

            CCSprite.spriteWithSpriteFrameName("btn_back1.png"),

            CCSprite.spriteWithSpriteFrameName("btn_back2.png"),

            this, click_back);

        CCMenu menu = CCMenu.menuWithItems(btn_back);

        menu.position = new CCPoint(666,32);

        this.addChild(menu);



        CCSprite tab1 = CCSprite.spriteWithSpriteFrameName("tab_shu1.png");

        CCSprite tab2 = CCSprite.spriteWithSpriteFrameName("tab_wu2.png");

        CCSprite tab3 = CCSprite.spriteWithSpriteFrameName("tab_wei2.png");

        tab1.position = new CCPoint(115, 430);

        tab2.position = new CCPoint(335, 430);

        tab3.position = new CCPoint(575, 430);

        this.addChild(tab1);

        this.addChild(tab2);

        this.addChild(tab3);



        CCPoint offset = new CCPoint(150, 150);

        for (int i = 0; i < 4; i++)

        {

            for (int j = 0; j < 3; j++)

            {

                CCMenuItemSprite level = CCMenuItemSprite.itemFromNormalSprite(

                    CCSprite.spriteWithSpriteFrameName("btn_level1.png"),

                    CCSprite.spriteWithSpriteFrameName("btn_level2.png"),

                    this, click_level);

                menu = CCMenu.menuWithItems(level);

                menu.position = new CCPoint(offset.x + 160 * i,offset.y + 85 * j);

                this.addChild(menu);

            }

        }

    }

    private void click_back(CCObject s)

    {

    }

    private void click_level(CCObject sender)

    {

    }

}

场景选择的实现效果:

QQ截图20120916222431

选择关卡的场景里,全部都跳转到SceneGame中,以后将对应的关卡进行设计。

下面是游戏场景SceneGame的代码,这里的Code只是贴了一张图,然后加了一个“出征”按钮,这个出征按钮在本例中将做成游戏结束的触发器:

public class SceneGame : CCScene

{

    public SceneGame()

    {

        base.init();

        //背景图

        CCSprite background = CCSprite.spriteWithSpriteFrameName("bg_game.png");

        background.anchorPoint = new CCPoint(0, 0);

        this.addChild(background);

        //返回按钮

        CCMenuItemSprite btn_attack = CCMenuItemSprite.itemFromNormalSprite(

            CCSprite.spriteWithSpriteFrameName("btn_soldierattack1.png"),

            CCSprite.spriteWithSpriteFrameName("btn_soldierattack2.png"),

            this, click_attack);

        CCMenu menu = CCMenu.menuWithItems(btn_attack);

        menu.position = new CCPoint(732, 36);

        this.addChild(menu);

    }

    private void click_attack(CCObject sender)

    {}

}

代码效果如下:

QQ截图20120916222716

最后一个是结束场景:

public class SceneOver : CCScene

{

    public SceneOver()

    {

        base.init();

        //背景图

        CCSprite background = CCSprite.spriteWithSpriteFrameName("bg_over.png");

        background.anchorPoint = new CCPoint(0, 0);

        this.addChild(background);

        //文字

        CCSprite title = CCSprite.spriteWithSpriteFrameName("text_over.png");

        title.position = new CCPoint(CCDirector.sharedDirector().getWinSize().width / 2, CCDirector.sharedDirector().getWinSize().height / 2 + 150);

        this.addChild(title);

        //返回按钮

        CCMenuItemSprite btn_back = CCMenuItemSprite.itemFromNormalSprite(

            CCSprite.spriteWithSpriteFrameName("btn_back1.png"),

            CCSprite.spriteWithSpriteFrameName("btn_back2.png"),

            this, click_back);

        CCMenu menu = CCMenu.menuWithItems(btn_back);

        menu.position = new CCPoint(666, 32);

        this.addChild(menu);

    }

    private void click_back(CCObject s)

    {}

}

效果如下:

QQ截图20120916222936

 

场景切换 Transition

好了, 我们现在完成了基本的场景,现在要进行场景的切换操作,下面将会用上三个CCDirector类方法:

popScene() : 返回到上一个场景

pushScene(CCScene pScene) :切换到一个指定的场景

replaceScene(CCScene pScene) :替换掉当前的场景

在CCDirector中场景管理是一个队列,写说明还是比较麻烦,下面画张图来表示一下:

QQ截图20120916223757

如图示意,场景队列内部已经帮你管理好了,所以不用考虑太多。

那么在代码中如何体现呢?只需要对对应的委托事件进行处理就行了,例如在开始界面点击“开始”就会pushScene到SceneSelect场景,而点击返回则执行popScene,replaceScene就很简单了,用于在游戏结束的时将SceneGame替换成为SceneOver。

所添加的代码如下:

SceneStart:

private void click_start(CCObject sender)

{

    CCDirector.sharedDirector().pushScene(GameRoot.pSceneSelect);

}

SceneSelect:

private void click_back(CCObject s)

{

    CCDirector.sharedDirector().popScene();

}

private void click_level(CCObject sender)

{

    CCDirector.sharedDirector().pushScene(GameRoot.pSceneGame);

}

SceneGame:

private void click_attack(CCObject sender)

{

    CCDirector.sharedDirector().replaceScene(GameRoot.pSceneOver);

}

SceneOver:

private void click_back(CCObject s)

{

    CCDirector.sharedDirector().popScene();

}

现在运行一下效果,点击按钮看切换。

QQ截图20120916224716

转场效果 Effect

最后说一说,转场的效果,点击直接变化是不是显得非常的单调?更加绚丽的转场效果在引擎中已经提供了,可以看cocos2d-xna代码中的transition部分,几十个切换效果任由选择:

QQ截图20120916224926

具体的用法非常简单,例如我们在开始界面点击“开始”按钮的时候,进行一个CCTransitionFade转场效果,这个效果可以让屏幕一黑,然后变成新的场景,在SceneStart.cs中click_start方法里加入如下代码:

private void click_start(CCObject sender)

{

    var s = CCTransitionFade.transitionWithDuration(0.5f, GameRoot.pSceneSelect);

    CCDirector.sharedDirector().pushScene(s);

}

这种一般情况下要折腾很久的切换效果,在引擎里只是一行代码而已,不同的Transition有不同的参数,有兴趣的朋友可以参看OpenXLive移植的cocos2d-xna里的test工程样本,里面展示了非常多的切场效果,在这里就不再太多的演示了。

本篇例子工程:https://github.com/Nowpaper/SanguoCommander_cocos2dxna_Sample
本例工程名为:SanguoCommander3

本篇主要讲述了场景的深度制作和Transition用法,主要是对场景Scene内容,下篇中将使用CCLayer,还会结合CCAction完成复杂的界面互动编写。

你可能感兴趣的:(cocos2d-x)