1.1. ScrollView滚动视图

滚动视图是一种常见的容器型控件,它里面可以放置其他组件。Cocos2d-x中的ScrollView本身也是一种Layout,所以也可以在其中使用线形或者相对布局。ScrollView的显示效果,主要是取决于:

setContentSize(),设置显示出来的区域大小“视口”。

setInnerContainerSize(),设置内部容器的大小,决定了拖动的区域大小;它必须大于或等于setContentSize()。

以及添加进内部的组件和布局位置。

ScrollView,内部的容器为innerLayout,我们的控件放在这个layout上。任一时刻拖动ScrollView,会在“视口”显示innerLayout的一部分:效果示意图如下:

拖动视口,改变的是内部容器innerLayout的位置偏移。则通过视口看到的内容得以改变:

注意,因此内部容器innerLayout上我们加入的控件,需要我们自己来摆放到正确的位置上。

#include "ui/UIScrollView.h"

ui:: ScrollView *scrollView = ui:: ScrollView ::create();

scrollView->setBackGroundColorType(ui:: Layout :: BackGroundColorType :: SOLID );

scrollView->setBackGroundColor( Color3B ::RED);

scrollView->setPosition( Vec2 (50, 100));

scrollView->setContentSize( Size (400, 300)); //外部显示的大小

scrollView->setBounceEnabled( true ); //是否开启拖动到头后的反弹效果

scrollView->setInnerContainerSize( Size (500, 500)); //内部的尺寸,决定了拖动的区域大小;它必须大于或等于setContentSize

//scrollView->setTouchEnabled(true);//是否允许拖动空白处滚动视图,默认为是;否的话,只能拖动里面的组件来滚动视图

scrollView->setDirection(ui:: ScrollView :: Direction :: VERTICAL ); //允许拖动的方向

scrollView->setLayoutType( Layout :: Type :: VERTICAL ); //垂直布局;ScrollView本身就是一种Layout

//绑定响应事件

scrollView->addEventListener( CC_CALLBACK_2 ( HelloWorld ::onScrollViewEvent, this ));

Button * button1 = Button ::create( "button.png" );

scrollView->addChild(button1);

Button * button2 = Button ::create( "potentiometerButton.png" );

scrollView->addChild(button2);

Button * button3 = Button ::create( "potentiometerProgress.png" );

scrollView->addChild(button3);

Button * button4 = Button ::create( "potentiometerTrack.png" );

scrollView->addChild(button4);

Button * button5 = Button ::create( "button_normal.png" );

scrollView->addChild(button5);

Button * button6 = Button ::create( "CloseNormal.png" );

scrollView->addChild(button6);

this ->addChild(scrollView);

void HelloWorld ::onScrollViewEvent( Ref * pSender , cocos2d::ui:: ScrollView :: EventType event )

ui:: ScrollView * scrollView = (ui:: ScrollView *) pSender ;

switch ( event )

case cocos2d::ui:: ScrollView :: EventType :: SCROLL_TO_TOP :

CCLOG ( "scrollView is scroll to top" );

break ;

case cocos2d::ui:: ScrollView :: EventType :: SCROLLING :

//CCLOG("scrollView is scrolling");

break ;

case cocos2d::ui:: ScrollView :: EventType :: SCROLL_TO_BOTTOM :

CCLOG ( "scrollView is scroll to bottom" );

break ;

case cocos2d::ui:: ScrollView :: EventType :: BOUNCE_TOP :

CCLOG ( "scrollView is bounce to top" );

break ;

case cocos2d::ui:: ScrollView :: EventType :: BOUNCE_BOTTOM :

CCLOG ( "scrollView is bounce to bottom" );

break ;

注意,由于cocos2d::extension库中也有ScrollView,为了避免编译时的冲突。建议类的名字写全路径,如:cocos2d::ui:: ScrollView 在使用Event时,同样也需要使用全路径:cocos2d::ui:: ScrollView :: EventType

最终效果如下:

初始位置:

拖动到最下面的位置:

由于我们设定了允许回弹,所以拖动到某一端时,还可以继续拖动一段距离,松开即可回弹:

1.2. TableView桌面视图

注意,目前至最新版cocos2d-x3.9为止,TableView是属于extension库的,它继承自extension库的ScrollView,而不是UI库中的ScroolView。

TableView是ScrollView的子类,是一种特殊的ScrollView。

它跟ScrollView类似,可以横向、纵向添加子节点。但TableView是为了解决容器内部出现大量类型相同、但内容数值不同的子节点时,一次性创建过多的子节点而占用大量资源的问题。TableView只会在需要时创建内部单元格(子节点TableViewCell),隐藏在可见区域之外的cell会被重复利用。

比如我们在传统的ScrollView中创建4个子节点,大体效果如下:

其中节点1完全不可见,被隐藏了起来。

我们在TableView中,可以重复利用这些“被隐藏起来的、类型相同的单元格”。在节点1被完全隐藏、不可见时(位于视图可见区域以外),而同时右边的节点4需要被显示出来。我们可以在这一霎那动态的创建节点4,但这样做我们并没有最佳的利用资源,因为随着后续的节点越来越多,TableView内部的单元格cell会越来越多。

但经过观察,节点1是已经完全显示不出来的,因此我们可以拿节点1这个对象出来,放到节点4应当出现的位置,然后把其上的信息修改为节点4应当显示的信息。如图所示:

这样一来,上述示例情况下,我们永远只需要创建3个单元格即可达到创建N个节点的效果。这3个单元格一直被重复利用。但须注意的是,比如在TableView视图上滑动时,任一单元格节点上的值,应当予以更新。

使用起来需要以下几个步骤:

1.在场景类的头文件中:

#include "extensions/GUI/CCScrollView/CCTableView.h"

USING_NS_CC_EXT ;

//实现TableViewDelegate接口,以响应触摸事件

//实现TableViewDataSource接口,以在创建内部Cell时提供必要数据

class HelloWorld : public cocos2d:: Layer , public TableViewDelegate , public TableViewDataSource

......

//for TableViewDelegate

virtual void tableCellTouched( TableView * table, TableViewCell * cell);

//for TableViewDataSource

virtual TableViewCell * tableCellAtIndex( TableView *table, ssize_t idx);

virtual ssize_t numberOfCellsInTableView( TableView *table);

virtual Size tableCellSizeForIndex( TableView *table, ssize_t idx);

TableViewDelegate提供了触摸事件等接口。在事件发生时回调这些方法。

TableViewDataSource提供了TableView的数据源,在创建TableView及内部单元时,回调相应的方法,我们在这些方法中定制视图和具体的内容。

2.在相应的cpp文件中创建TableView并实现这些接口

//init()方法中

//当前类作为数据源,视图大小为500,400

TableView * tbView = TableView ::create( this , Size (500, 400));

tbView->setDelegate( this ); //当前类作为事件代理

tbView->setDirection( ScrollView :: Direction :: HORIZONTAL ); //TableView中单元格的方向

tbView->setPosition( Vec2 (100, 50));

tbView->setVerticalFillOrder( TableView :: VerticalFillOrder :: TOP_DOWN ); //设定垂直填充方向

this ->addChild(tbView);

tbView->reloadData(); //从dataSource数据源加载数据,视图将被刷新

//实现各种必要接口

//界面上点击任何一个cell时,会调用此函数

void HelloWorld ::tableCellTouched( TableView * table , TableViewCell * cell )

CCLOG ( "table cell touched at index:%d" , cell ->getIdx());

TableViewCell * HelloWorld ::tableCellAtIndex( TableView * table , ssize_t idx )

//出队一个空闲的(没有被显示出来时,认为是空闲的)cell,重复利用它

TableViewCell * tbCell = table ->dequeueCell();

string strIndex = StringUtils::format( "cell%d" , idx );

//如果没有空闲的cell,则创建一个

if (tbCell == NULL )

tbCell = TableViewCell ::create();

Sprite * sp = Sprite ::create( "potentiometerButton.png" );

sp->setAnchorPoint( Vec2 ::ZERO);

sp->setPosition( Vec2 ::ZERO);

tbCell->addChild(sp);

Label *label = Label ::createWithTTF(strIndex.c_str(), "fonts/arial.ttf" , 24, Size ::ZERO, TextHAlignment :: CENTER );

label->setPosition( Vec2 (40, 40));

label->setTag(1);

tbCell->addChild(label);

else //原来那个cell对象拿来复用,但其上的信息应当按照实际index进行更新

Label * label = ( Label *)tbCell->getChildByTag(1);

label->setString(strIndex.c_str());

return tbCell;

//创建每个cell时,会自动调用此函数,获得某个index下该单元的尺寸

Size HelloWorld ::tableCellSizeForIndex( TableView * table , ssize_t idx )

if ( idx == 2)

return Size (120, 120);

return Size (80, 80);

//创建TableView时,会自动调用此函数,获得应当需要创建多少个cell单元

ssize_t HelloWorld ::numberOfCellsInTableView( TableView * table )

return 10; //它确定了TableView一共有多少个cell单元

最终效果如下:

由于我们在tableCellSizeForIndex中进行了判断,若要创建的cell单元格的index为2,则返回Size(120, 120)。因此下标为2的单元格占的大小比其他单元格都要大。

若我们把init()方法中创建TableView时的排列方向进行修改,如:

tbView->setDirection( ScrollView :: Direction :: VERTICAL ); //TableView中单元格的方向

则最终效果如下:

1.3. PageView页面视图

容器型控件,一次显示一页,每个页面之间左右拖拽实现切换。

静止效果,第1页和第3页不可见:

拖拽中的效果,中间蓝框部分可见,其余不可见:

注意,上图中蓝色框为可见部分大小(也就是控件的content size)与页面的大小没有关系。而每一页的大小应当保持一致。

创建PageView控件,然后再创建每一页,每一页必须是一个“Layout”类型(或子类型)的,然后PageView再把每一页添加进去。PageView的可显示部分大小,通过setContentSize()来设定。每个页面Layout的大小,也通过其setContentSize()方法来设定。PageView和页面Layout之间的大小关系,应当提前予以设计。

#include "ui/UIPageView.h"

#include "ui/UILayout.h"

PageView * pageView = PageView ::create();

pageView->setContentSize( Size (300, 400));

pageView->setPosition( Vec2 (50, 100));

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

Layout *layout = Layout ::create();

layout->setLayoutType( Layout :: Type :: ABSOLUTE );

layout->setContentSize( Size (300, 400));

layout->setBackGroundColorType( Layout :: BackGroundColorType :: SOLID );

switch (i)

case 0:

layout->setBackGroundColor( Color3B ::BLUE);

break ;

case 1:

layout->setBackGroundColor( Color3B ::YELLOW);

break ;

case 2:

layout->setBackGroundColor( Color3B ::GREEN);

break ;

string str = StringUtils::format( "第%2d页" , i + 1);

Label *label = Label ::createWithTTF(G2U(str.c_str()), "fonts/abc.ttf" , 24);

label->setPosition( Vec2 (150, 380));

layout->addChild(label);

Button * button1 = Button ::create( "button.png" );

button1->setPosition( Vec2 (150, 300));

layout->addChild(button1);

Button * button2 = Button ::create( "potentiometerButton.png" );

button2->setPosition( Vec2 (150, 240));

layout->addChild(button2);

Button * button3 = Button ::create( "potentiometerProgress.png" );

button3->setPosition( Vec2 (150, 160));

layout->addChild(button3);

pageView->addPage(layout);

//绑定page view的事件响应

pageView->addEventListener( CC_CALLBACK_2 ( HelloWorld ::onPageViewEvent, this ));

this ->addChild(pageView);

void HelloWorld ::onPageViewEvent( Ref * pSender , cocos2d::ui:: PageView :: EventType event )

PageView * pageView = ( PageView *) pSender ;

//根据手册,page view目前只有一种事件!

switch ( event )

case PageView :: EventType :: TURNING :

CCLOG ( "pageView is turrning" );

break ;

最终效果如下:

静态状态:

切换中的状态:

1.4. ListView列表视图

ListView列表视图控件,是一种特殊的ScrollView(ListView类继承自ScrollView)。它提供了纵向或者横向的添加条目,按照列表的方式来管理内部的item。可以方便的获取当前选中的条目,并动态的添加、删除指定下标的条目。

#include "ui/UIListView.h"

#include "ui/UILayout.h"

//创建ListView控件

ListView * listView = ListView ::create();

listView->setDirection( ListView :: Direction :: VERTICAL ); //垂直排列item(纵向)

listView->setBackGroundColorType( Layout :: BackGroundColorType :: SOLID );

listView->setBackGroundColor( Color3B ::RED);

listView->setPosition( Vec2 (50, 100));

listView->setTouchEnabled( true );

//创建一个“模型”,ListView可以用它克隆出来多个item!

Layout * default_item = Layout ::create();

Button * button = Button ::create( "button.png" );

default_item->setContentSize(button->getContentSize());

button->setPosition( Vec2 (default_item->getContentSize().width / 2, default_item->getContentSize().height / 2));

button->setTitleText( "model button" );

default_item->addChild(button);

listView->setItemModel(default_item); //ListView绑定该模型

//我们listView的大小是要根据内容来设定的。所以先设定内容大小,再设定listView大小

listView->setContentSize( Size (default_item->getContentSize().width, 500));

//根据设定的“模型”,连续克隆出来3个并插入末尾

listView->pushBackDefaultItem();

listView->pushBackDefaultItem();

listView->pushBackDefaultItem();

//插入自定义(非模型)的item

//插入一个按钮

Button * customButton = Button ::create( "button.png" );

customButton->setTitleText( "button1" );

listView->pushBackCustomItem(customButton);

//把一个layout当做一个item插入

Layout *customItem2 = Layout ::create();

customItem2->setLayoutType( Layout :: Type :: ABSOLUTE );

customItem2->setContentSize( Size (300, 400));

customItem2->setBackGroundColorType( Layout :: BackGroundColorType :: SOLID );

customItem2->setBackGroundColor( Color3B ::YELLOW);

string str = StringUtils::format( "测试条目" );

Label *label = Label ::createWithTTF(G2U(str.c_str()), "fonts/abc.ttf" , 24);

label->setPosition( Vec2 (150, 380));

customItem2->addChild(label);

Button * button1 = Button ::create( "button.png" );

button1->setPosition( Vec2 (150, 300));

customItem2->addChild(button1);

Button * button2 = Button ::create( "potentiometerButton.png" );

button2->setPosition( Vec2 (150, 240));

customItem2->addChild(button2);

Button * button3 = Button ::create( "potentiometerProgress.png" );

button3->setPosition( Vec2 (150, 160));

customItem2->addChild(button3);

listView->pushBackCustomItem(customItem2);

listView->addEventListener(( ListView :: ccListViewCallback ) CC_CALLBACK_2 ( HelloWorld ::onPageViewEvent, this ));

this ->addChild(listView);

void HelloWorld ::onListViewEvent( Ref * pSender , cocos2d::ui:: ListView :: EventType event )

switch ( event )

case ListView :: EventType :: ON_SELECTED_ITEM_START :

CCLOG ( "on selected item start" );

break ;

case ListView :: EventType :: ON_SELECTED_ITEM_END :

CCLOG ( "on selected item end" );

break ;

最终效果如下:

1.5. RichText多格式文本

1.5.1. 基本用法

RichText多格式文本控件,也称富文本。它提供了一般文本框所不能提供的一些丰富功能,比如同一个文本框内不同问的颜色不同、字体不同、字号不同,图、文混编等等。

#include "ui/UIRichText.h"

RichText * richText = RichText ::create();

richText->setPosition( Vec2 (visibleSize.width / 2, visibleSize.height / 2));

richText->setContentSize( Size (300, 400));

//ture,忽略自身的size,使用内部纹理的size;若一个字符串很长,richText长度会跟着变长。

//false的话反之。若字符串过长,会让其“自动换行”

richText->ignoreContentAdaptWithSize( false );

//richText->setVerticalSpace(50);//设置行间距

//RichText中的字符串不能强制换行,\n没有效果

RichElementText * re1 = RichElementText ::create(1, Color3B ::WHITE, 255, G2U( "测试字符串1\n" ), "fonts/abc.ttf" , 24);

RichElementText * re2 = RichElementText ::create(2, Color3B ::RED, 255, G2U( "测试字符串2\n" ), "fonts/abc.ttf" , 36);

RichElementText * re3 = RichElementText ::create(3, Color3B ::BLUE, 255/2, G2U( "测试字符串3\n" ), "fonts/abc.ttf" , 24);

RichElementText * re4 = RichElementText ::create(4, Color3B ::GREEN, 255, G2U( "测试字符串4\n" ), "fonts/abc.ttf" , 24);

RichElementText * re5 = RichElementText ::create(5, Color3B ::YELLOW, 255, G2U( "测试字符串5\n" ), "fonts/abc.ttf" , 24);

richText->pushBackElement(re1);

richText->pushBackElement(re2);

richText->pushBackElement(re3);

richText->pushBackElement(re4);

richText->pushBackElement(re5);

RichElementText * re6 = RichElementText ::create(5, Color3B ::YELLOW, 255, G2U( "今天天气不错" ), "fonts/abc.ttf" , 24);

RichElementImage * re7 = RichElementImage ::create(7, Color3B ::RED, 255, "smile.png" );

richText->pushBackElement(re6);

richText->pushBackElement(re7);

// 目前 通过骨骼动画,实现RichText中的某个element的动画效果! //cocostudio::ArmatureDataManager::getInstance()->addArmatureFileInfo("cocosui/100/100.ExportJson");

//cocostudio::Armature *pAr = cocostudio::Armature::create("100");

//pAr->getAnimation()->play("Animation1");

//RichElementCustomNode* recustom = RichElementCustomNode::create(1, Color3B::WHITE, 255, pAr);

//richText->pushBackElement(recustom);

this ->addChild(richText);

最终效果如下:

其中蓝色字符串透明度为一半。

1.5.2. 手工换行

暂未找到RichText支持换行的方法,在上述效果中,由于我们设置了richText->ignoreContentAdaptWithSize( false );,字符串会根据RichText的contentSize来自动换行(根据宽度),但“\n”这种换行符是无效的。因此,目前想到的思路是,在ListView中添加RichText作为其item。

#include "ui/UIRichText.h"

#include "ui/UIListView.h"

ListView * listView = ListView ::create();

listView->setBackGroundColorType( Layout :: BackGroundColorType :: GRADIENT ); //渐变色

listView->setBackGroundColor( Color3B ::RED, Color3B ::BLUE);

listView->setContentSize( Size (400, 500));

listView->setPosition( Vec2 (50, 100));

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

RichText * richText = RichText ::create();

richText->setContentSize( Size (400, 100));

richText->setPosition( Vec2 (visibleSize.width / 2, visibleSize.height / 2));

//ture,忽略自身的size,使用内部纹理的size;若一个字符串很长,richText长度会跟着变长。

//false的话反之。若字符串过长,会让其“自动换行”

richText->ignoreContentAdaptWithSize( false );

string player = StringUtils::format( "玩家%d:" , i + 1);

RichElementText * rePlayer = RichElementText ::create(0, Color3B ::YELLOW, 255, G2U(player.c_str()),

"fonts/abc.ttf" , 24);

RichElementText * re1 = RichElementText ::create(1, Color3B ::WHITE, 255, G2U( "今天天气不错," ),

"fonts/abc.ttf" , 24);

RichElementImage * re2 = RichElementImage ::create(2, Color3B ::RED, 255, "smile.png" );

RichElementText * re3 = RichElementText ::create(3, Color3B ::BLUE, 255, G2U( "心情也好起来了!" ),

"fonts/abc.ttf" , 24);

Sprite * sp = Sprite ::create( "pentacle.png" );

//动画不起作用,因为RichElementCustomNode本身不是Node子类,无法作为sprite的parent

//sp->runAction(RepeatForever::create(RotateBy::create(1, 360)));

//只通过骨骼动画,实现RichText中的某个element的动画效果!

//cocostudio::ArmatureDataManager::getInstance()->addArmatureFileInfo("cocosui/100/100.ExportJson");

//cocostudio::Armature *pAr = cocostudio::Armature::create("100");

//pAr->getAnimation()->play("Animation1");

//RichElementCustomNode* recustom = RichElementCustomNode::create(1, Color3B::WHITE, 255, pAr);

//richText->pushBackElement(recustom);

RichElementCustomNode * re4 = RichElementCustomNode ::create(4, Color3B ::BLACK, 255, sp);

richText->pushBackElement(rePlayer);

richText->pushBackElement(re1);

richText->pushBackElement(re2);

richText->pushBackElement(re3);

richText->pushBackElement(re4);

listView->pushBackCustomItem(richText);

this ->addChild(listView);

最终效果如下:

Cocos2d-x 3.9教程9. Cocos2d-x中基于布局的容器控件1.1. ScrollView滚动视图滚动视图是一种常见的容器型控件,它里面可以放置其他组件。Cocos2d-x中的ScrollView本身也是一种Layout,所以也可以在其中使用线形或者相对布局。ScrollView的显示效果,主要是取决于:setContentSize(),设置显示出来的区域
转:http://www. cocos2d-x .org/docs/manual/framework/native/gui/container/zhGUI 容器 层的使用-UI ScrollView 滚动视图 除了 布局 容器 ,我们常用的还有滚动层 容器 ,它可以扩大我们的显示 控件 ,当内容元素很多时,尤为有用。可以设置为两个方向,横向或者是竖向。 UI ScrollView * scroll
这个例子是基于 cocos2dx ,利用cocosBuilder制作的例子。这个例子改造自spriter的官方例子(spriter的官方为http://www.brashmonkey.com/spriter.htm)。 详细请参考博文:[ cocos2dx 开发技巧4]工具CocosBuilder的使用--复杂动画:http://blog.csdn.net/stalendp/article/details/8760957
8. Cocos2d-x 的4种 布局 Cocos2d-x 一共有4种 布局 :ABSOLUTE(绝对 布局 )、HORIZONTAL(水平 布局 )、VERTICAL(垂直 布局 )和RELATIVE(相对 布局 )。 注意,只有在绝对 布局 内部,组件使用 set Position()方法来指定其位置。另外三种 布局 的组件, set Position()方法将不起任何作用!必须通过 在上一篇文章 已经分析了使用 ScrollView 的一些问题,那么这一篇提供一些解决方案: 默认情况下 scrollView 的滚动区域大小和 scrollView 的大小(可视区域)相同, 我们可以通过get Inner ContainerS ize 方法获取滚动区域大小,然后把我们的子 控件 从上往下加即第一个 控件 坐标getInne
这周刚刚开始接触 cocos2d-x ,第一次打开helloword的就懵了不知道该干嘛。所以这里记录一下方便日后查找。 #include "main.h" #include "AppDelegate.h" #include "cocos2d.h" #include"CCGL View .h" USING_NS_CC; int APIENTRY _tWinMain(HINSTANCE hInstanc
大家好,我是红孩儿.经过一年左右业余时间的持续开发,《红孩儿工具箱》已经初步完成了一些不错的功能,大家可以用它来辅助我们基于 Cocos2d-x 的游戏开发工作,帮助我们提升工作效率,实现一些复杂的场景和动画效果。好啦,废话不多讲,今天我来讲解一下如何使用红孩儿工具箱制作小游戏-《打地鼠》
探索Cocos2D-JS:一款强大的游戏开发框架 项目地址:https://gitcode.com/faint2death/cocos2d-js Cocos2D-JS 是一个开源的游戏引擎,它允许开发者使用JavaScript语言创建跨平台的2D游戏和交互式应用。这款项目的目的是简化游戏开发过程,提供高效的性能,并使代码能够在Web、iOS和Android等平台上无缝运行。 Cocos2...
最近开始学习 cocos2d-x 的功能,主要是了解了其功能框架,并做了点小界面。 现在小结一下 cocos2d-x 的功能框架。 1.主要功能框架由下面几个组成:CCDirector, CCScene, CCLayer, CCNode, CCSprite, CCAction,CCObject等 1)CCDirector是整个游戏引擎的总指挥,就像拍电影的导演,由它控制F
(转载请注明出处:http://blog.csdn.net/buptgshengod)      说到碰撞检测,最简单直观的例子就是超级玛丽里的吃金币功能,当两个物体碰撞在一起产生一定的效果。下面上图介绍下这章的实例。当机器人a走到机器人b的身上时,机器人b消失。 2.具体实现方式 其实思路很简单,就是规定每个精灵有他们自己的一个作用范围,当两个精灵的作用范围重