博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Cocos2d-xna : 横版战略游戏开发实验4 Layer构建丰富的交互
阅读量:7049 次
发布时间:2019-06-28

本文共 6798 字,大约阅读时间需要 22 分钟。

本篇中主要介绍cocos2d-xna的CCLayer和CCMenu,在游戏开发中,只是使用前面提到的CCSprite和CCScene来完成丰富的交互行为是不够的,单体的界面元素操作只会增加UI开发的复杂程度,所以像CCLayer这样的成组操作可以为开发提供很好的便捷。这次拿关卡选择场景做操作实验,完成较为复杂的交互开发。

巧用CCMenuItem

拿出来咱们之前制作的资源文件,游戏设计中,将魏蜀吴三个国家分成不同的几个关卡,这样就要求我们在界面上需要对它们进行分开选择,先看看图片资源的准本情况,在GameUI01.plist里有这样的几个按钮文件:

用亮红色的按钮表示为选定的,而暗红色的表示可以点击,在标签头上,被选定的一定是不能点击的,所以可以巧用CCMenuItem的Enabled属性组合达到效果,打开SceneSelect.cs类,在构造中创建Tab按钮的地方把原有的代码修改一下,原来的只是用CCSpirte贴了一张展示图,详细的可以看上一篇,

首先创建该类的一个成员:

CCMenu story_tabs;

CCMenu story_tabs一会儿就能用的上了,下面再构造函数里写代码如下:

//上面的Tab按钮创建CCMenuItemSprite tab1 = CCMenuItemSprite.itemFromNormalSprite(    CCSprite.spriteWithSpriteFrameName("tab_shu2.png"),     CCSprite.spriteWithSpriteFrameName("tab_shu1.png"),    CCSprite.spriteWithSpriteFrameName("tab_shu1.png"),     this, click_story_tab);CCMenuItemSprite tab2 = CCMenuItemSprite.itemFromNormalSprite(    CCSprite.spriteWithSpriteFrameName("tab_wu2.png"),    CCSprite.spriteWithSpriteFrameName("tab_wu1.png"),    CCSprite.spriteWithSpriteFrameName("tab_wu1.png"),    this, click_story_tab);CCMenuItemSprite tab3 = CCMenuItemSprite.itemFromNormalSprite(    CCSprite.spriteWithSpriteFrameName("tab_wei2.png"),    CCSprite.spriteWithSpriteFrameName("tab_wei1.png"),    CCSprite.spriteWithSpriteFrameName("tab_wei1.png"),    this, click_story_tab);story_tabs = CCMenu.menuWithItems(tab1, tab2, tab3);//按照水平方向10个像素间隔分割story_tabs.alignItemsHorizontallyWithPadding(10);//转换为界面UI的坐标story_tabs.position = CCDirector.sharedDirector().convertToUI(new CCPoint(300, 72));//将第一个设置为不可点击tab1.Enabled = false;this.addChild(story_tabs);

该代码是创建了几个按钮并且组合到了一个CCMenu当中,这里需要特别说明的是,CCDirector.sharedDirector().convertToUI()方法,这个方法是将坐标转换成为UI坐标,要知道,在cocos2d里面坐标是用左下角向上的,而不是一般的左上角,用这个方法可以方便的转换。

现在运行不了,因为没有实现click_story_tab方法,下面在该类中实现方法:

private void click_story_tab(CCObject sender){    //遍历story_tabs    foreach (var item in story_tabs.children)    {        //判断是否为CCMenuItem,如果是的话,排除sender以外的全部设定为true        if(item is CCMenuItem)            (item as CCMenuItem).Enabled = item != sender;    }}

也许初步看起来不太容易理解,其实这里做一下逻辑判断就行,用if else实现就是这样的:

if(item != sender)    (item as CCMenuItem).Enabled = false;else    (item as CCMenuItem).Enabled = true;

用什么方式都行,现在运行一下看看效果

当点击任何一个标签的时候就会呈现激活状态,而此时也会不能点击,好了,下面就要考虑如何实现对应的关卡内容了。

CCLayer

上一篇的代码中,只是用了for循环绘制了几个按钮然后让按钮触发跳转场景,很显然,现在有了分类的标签页,下面的对应的关卡也需要改变,如果使用很粗暴的方法(每个组单独写按钮,用是否可见管理)虽然能实现,但是管理起来不但麻烦,而且控制动画也就不方便了,下面我们用CCLayer图层来将这一大堆的按钮放在一起,关于层的概念如果玩过PS的朋友应该很容易理解,下面这张图当作简要的说明:

魏蜀吴不同的标签对应一个不同的图层,当点击对应时,图层发生发生变换,所以我们抽象一个关卡的图层类代码如下:

public class LayerLevels : CCLayer{    public LayerLevels()    {        //关卡选择层        CCPoint offset = new CCPoint(170, 180);        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);                CCMenu menu = CCMenu.menuWithItems(level);                //位置相对于左上的UI界面                menu.position = CCDirector.sharedDirector().convertToUI(new CCPoint(offset.x + 160 * i, offset.y + 85 * j));                this.addChild(menu);                //创建一个MenuItem,用作文本内容                CCMenuItem menuitem = new CCMenuItem();                //指定Arial的字体描述,保证fonts里有Arial.spritefont                var text = CCLabelTTF.labelWithString((j * 4 + i + 1).ToString(), "Arial", 12);                //将颜色指定为黑色                text.Color = new ccColor3B();                menuitem.addChild(text);                menu.addChild(menuitem);            }        }    }    private void click_level(CCObject sender)    {        //当关卡点击的时候会自动跳转到游戏场景        CCDirector.sharedDirector().pushScene(GameRoot.pSceneGame);    }    public void Show()    {        this.visible = true;    }    public void Hide()    {        this.visible = false;    }}

好了,现在回到SceneSelect.cs,将之前的按钮for循环全部去掉,只需要一行代码:

this.addChild(new LayerLevels());

运行看看:

有了关卡,图层显示,并且还有了关卡名字,其实这里你可以发挥一下,以后将来能自定义关卡名,但谨记汉字是显示不了的,这需要另外一个汉字解决方案,以后咱们再说。

为了更好了和将来拓展,我加入了Show()和Hide()两个方法,用来控制是否显示,下面我们马上就用的上啦。

但是点击对应的魏蜀吴还不能实现切换,下面考虑如何实现页面的切换,将标签都对应起来,建立一个字典:

Dictionary
dictLayerLevels = new Dictionary
();LayerLevels currentlayerlevers = null;

在SceneSelect构造函数中:

//添加测试层//this.addChild(new LayerLevels());//将标签对应到不同的LyerLevers 类中dictLayerLevels.Add(tab1, new LayerLevels() { visible = false });dictLayerLevels.Add(tab2, new LayerLevels() { visible = false });dictLayerLevels.Add(tab3, new LayerLevels() { visible = false });//将tab1显示为当前的关卡层showLayerLevels(dictLayerLevels[tab1]);//遍历并添加到界面中foreach (var item in dictLayerLevels.Values){    this.addChild(item);}

注意将之前的注释掉,现在这个没用,好了,然后实现showLayerLevels方法和在标签点击的事件中加入代码,变成这个样子:

private void click_story_tab(CCObject sender){    //遍历story_tabs    foreach (var item in story_tabs.children)    {        //判断是否为CCMenuItem,如果是的话,排除sender以外的全部设定为true        if(item is CCMenuItem)            (item as CCMenuItem).Enabled = item != sender;    }    showLayerLevels(dictLayerLevels[sender as CCMenuItem]);}private void showLayerLevels(LayerLevels layer){    if (currentlayerlevers != null)        currentlayerlevers.Hide();    layer.Show();    currentlayerlevers = layer;}

showLayerLevels可以保证之前的关卡层隐蔽掉,将新的显示出来。

但是现在点击上面的标签是没用的,因为没有任何的变化,只是可见和不可见,所以为了更清晰,下面将用CCAction来实现动画效果。

CCMoveTo

CCMoveTo意思很简单,让一个元素从当前的位置移动到指定的新位置,它的静态方法可以通过时间和坐标产生一个移动的CCAction,下面用它来实现图层的移动变化,这样当标签切换的时候,对应的更换也就可以直接看得到。那么打开LayerLevels类,把Show方法做一下修改:

public void Show(){    //将其显示出来    this.visible = true;    //把位置设置到最右边出屏幕外    this.position = new CCPoint(CCDirector.sharedDirector().getWinSize().width,0);    //指定移动到0,0点    CCMoveTo move = CCMoveTo.actionWithDuration(0.5f,new CCPoint(0,0));    //运行这个Action    this.runAction(move);}

好了,运行一下,看到了滑动效果了吗?这个效果,当然了,这个效果还不能通过手势来控制,只能点击上面的魏蜀吴。

更进一步,我们现在看这个效果还是有点别扭,就是之前页面是直接消失掉的,能不能跟滑动滚动走呢,这里就需要另外一个行为CCSequence队列行为来实现,队列行为在之前的一篇中有详细的说明:

我们将用上这个Action来实现Hide方法,当隐蔽动画完成之后将本图层隐蔽,改造Hide方法并添加回调方法:

public void Hide(){    //指定移动到最左边并超出屏幕    CCMoveTo move = CCMoveTo.actionWithDuration(0.5f,new CCPoint(-CCDirector.sharedDirector().getWinSize().width,0));    //执行一个队列行为,当移动完成后就会调用HideAniCompled    this.runAction(CCSequence.actionOneTwo(move, CCCallFunc.actionWithTarget(this, HideAniCompled)));}void HideAniCompled(){    this.visible = false;}

现在再运行一下:

当点击对应的标签时候就会发生变化,交互是否立即丰富了很多呢?现在你可以尝试自己做一些行为效果发挥想象力。

本篇主要对CCLayer和CCAction结合应用达到关卡选择场景的交互开发,没有做太多的其他考虑,在正式开发中,关卡选择界面和关卡设计紧密相关,对应数据的构建和设计至关重要,该部分在后面我们一步一步的完成它。

关于Action有很多的方法,有兴趣的朋友可以参看OpenXLive移植的cocos2d-xna里的test工程样本,里面展示了非常多的行为效果,例如放缩、切变、不透明等等,在这里就不再太多的讲解。

本篇例子工程:

本例工程名为:SanguoCommander4

posted on
2012-09-22 21:44 阅读(
...) 评论(
...)

转载于:https://www.cnblogs.com/nowpaper/archive/2012/09/22/2698465.html

你可能感兴趣的文章
python 字典操作
查看>>
httpd的一些知识点
查看>>
Apache开启Gzip压缩设置(转)
查看>>
分享一个牛逼的PHP无限极分类生成树方法,巧用引用(转)
查看>>
php_mcrypt.dll无法加载解决方法
查看>>
PHP5.4新特性(转)
查看>>
easyui在当前tab中直接加载url
查看>>
线程池原理
查看>>
leetcode-258-Add Digits
查看>>
python 某个目录下的所有文件列表
查看>>
HttpServlet详解
查看>>
转:Android之Tab分页标签的实现方法一-----TabActivity和TabHost的结合
查看>>
菜鸟修炼C语言小设计之——学生成绩管理系统
查看>>
Linux设备驱动工程师之路——设备模型(上)底层模型
查看>>
python基础补充
查看>>
常见图片格式详解
查看>>
关于JavaScript
查看>>
命名空间“Microsoft.Office.Interop”中不存在类型或命名空间名称“Excel”。是否缺少程序集引用 的另一种解决方案...
查看>>
MySQL技巧(一)
查看>>
python-os创建文件夹-create_dir_if_not_exist.py
查看>>