过关小游戏常带一个关卡界面,分页显示不同的关卡,可左右滑动。cocos2d-x中竟然不带类似cocoa中UIScrollView的控件,只好自己从继承CCLayerColor开始写新类,姑名之CCPageLayer。
初始化时要确定高度和显示宽度(为了简化代码,让页宽等于显示宽度,这样符合笔者的需求):
1 bool CCPageLayer::init(const float &width, 2 const float &height) 3 { 4 if (CCLayerColor::init()) { 5 this->setOpacity(255); 6 size_ = CCSizeMake(width, height); 7 data_source_ = NULL; 8 delegate_ = NULL; 9 this->setIsTouchEnabled(true); 10 11 return true; 12 } else { 13 return false; 14 } 15 }
笔者没有在这个函数中设置layer的contentSize,因此把传入参数暂存于size_中。
为了避免初始化接口过于庞大,不易维护,笔者创建了CCPageLayerDataSource抽象类,用于获取其余数据:
1 class CCPageLayerDataSource 2 { 3 public: 4 virtual PagesCount getPagesCount() = 0; 5 virtual CCLayer *layerOfPageIndex(const PagesCount &c) = 0; 6 };
在类中则有CCPageLayerDataSource *类型的弱引用指针成员:
1 CCPageLayerDataSource *data_source_;
初始化完之后,使用者可以设置data_source_:
1 layer->setDataSource(this);
如此在CCPagerLayer::onEnter函数中可完整初化:
1 void CCPageLayer::onEnter() 2 { 3 DASSERT(data_source_ != NULL); 4 CCLayerColor::onEnter(); 5 6 PagesCount c = data_source_->getPagesCount(); 7 this->setContentSize(CCSizeMake(c * size_.width, size_.height)); 8 this->addLayersOfEachPage(); 9 cur_page_ = 0; 10 }
DASSERT宏在debug环境下为assert。
addLayersOfEachPage函数会调用data_source->layerOfPageIndex(const PageCount &c)来获得每页的layer。
初始化完之后,希望让layer随手指左右移动:
1 bool CCPageLayer::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent) 2 { 3 began_touch_x = getTouchPosition(*pTouch).x; began_layer_x = getNodeLeft(*this); 4 return true; 5 }
1 //因为为会被频繁调用,也许内联效率上好些。 2 inline void CCPageLayer::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent) 3 { 4 CCPoint now = getTouchPosition(*pTouch); 5 setNodeLeft(this, began_layer_x + now.x - began_touch_x); 6 }
目前只是让layer随手指移动,手指离开后不会不会自动定位。自动定位需要重写ccTouchEnded:
1 void CCPageLayer::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent) 2 { 3 float now_x = getNodeLeft(*this); 4 int t = (began_layer_x - now_x) / CHNAGE_PAGE_DIS; 5 int page_inc = t / fabs(t); 6 int to_page = cur_page_ + page_inc; 7 if (this->isPageIndexLegal(to_page)) { 8 this->moveToPage(to_page); 9 } else { 10 this->moveToPage(cur_page_); 11 } 12 }
完整代码:https://github.com/chncwang/cocos2d-x_classes.git
以上代码经过测试。
这样就实现了CCPageLayer的基本功能,当然有一些可以改进之处:
1) 增加一些代理接口,让CCPageLayer在执行某些动作时(如换页)可以执行代理接口;
2) 改善不同页layer的内存管理(这个的内容就多得去了,话说cocoa中的UITableView类的设计堪为典范)。
and so on...