Cocos2d-x学习(七):cocos2d-x中ScrollView的简单实现

在游戏关卡选择,道具店之中经常会用到类似于ScrollView的控件,之前用AndEngine引擎的时候简单的实现了一个,(AndEngine滑动菜单传送门),考虑到手头的游戏以后也会用到,就先用cocos2d-x简单的实现了一下!原理非常类似,android中的app(比如微博,qq)也是类似的原理!


1.设计思路

自定义ScrollView继承于CCLayer,固定其每页的大小(ios上假设480x320),每一页是一个子层(也是继承于CCLayer),由使用者根据需求丰富,依次水平方向添加到ScrollView中(垂直方向的原理类似)!在ScrollView中实现触摸监听,如果是滑动事件,执行滚屏的操作,并且在触摸事件完成后跳转到当前页;如果是点击事件,则根据当前页交由子层处理。

2.ScrollView类

#ifndef ScrollView_ScrollView_h
#define ScrollView_ScrollView_h

#include "cocos2d.h"

USING_NS_CC;

// 屏幕尺寸
const float WINDOW_WIDTH = 480.0f;
const float WINDOW_HEIGHT = 320.0f;

// 触摸误差
const int TOUCH_DELTA = 5;

class ScrollView: public CCLayer
{
private:
    // 按下点
    CCPoint m_TouchDownPoint;
    // 抬起点 配合使用判断是否为点击事件
    CCPoint m_TouchUpPoint;
    // 当前触摸点
    CCPoint m_TouchCurPoint;
    
private:
    // 总页数
    int m_Page;
    // 当前显示页
    int m_CurPage;
    
private:
    // 存储所有页层
    CCArray *m_PageLayer;
    
private:
    // 跳转页
    void goToPage();
    
public:
    ScrollView();
    ~ScrollView();
    
    virtual bool init();
    
    LAYER_NODE_FUNC(ScrollView);

public:
    // 初始化相关
    virtual void onEnter();
    virtual void onExit();
    
    // 触摸事件相关
    virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
    virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);
    virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);
    virtual void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent);
    
public:
    // 添加页
    void addPage(CCLayer *pPageLayer);

};

#endif
CCPoint 成员是为了判断触摸事件相关,

addPage(CCLayer *pLayer) 是提供的外部接口,向ScrollView中添加子层,

void goToPage() 在触摸事件完成后根据当前偏移量跳转到指定页码

CCArray *m_PageLayer 用来存储所有的子层

3.判断规则

(1) 移动事件

根据触摸的点与当前ScrollView所在位置,得到ScrollView的偏移量

void ScrollView::ccTouchMoved(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
{
    // 移动
    CCPoint touchPoint = CCDirector::sharedDirector()->convertToGL(pTouch->locationInView());
    CCPoint posPoint = CCPointMake(getPositionX() + touchPoint.x - m_TouchCurPoint.x, getPositionY());
    setPosition(posPoint);
    m_TouchCurPoint = touchPoint;
}

(2) 触摸事件完成

得到用户按下和抬起的坐标偏移量,和触摸误差作比较,如果大于触摸误差,则认为是滑动;如果小于触摸误差,则认为是点击。

如果是点击,则交由当前的子层处理

如果是滑动,则根据滑动的偏移量来决定是否滑动到哪一页

void ScrollView::ccTouchEnded(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
{
    m_TouchUpPoint = CCDirector::sharedDirector()->convertToGL(pTouch->locationInView());
    // 计算按下和抬起的偏移量
    float off = (m_TouchUpPoint.x - m_TouchDownPoint.x) * (m_TouchUpPoint.x - m_TouchDownPoint.x) + (m_TouchUpPoint.y - m_TouchDownPoint.y) * (m_TouchUpPoint.y - m_TouchDownPoint.y);
    
    if (off < (TOUCH_DELTA * TOUCH_DELTA)) {
        // 点击
        // 向子Layer发送Click消息
        ((CCLayer*) m_PageLayer->objectAtIndex(m_CurPage))->ccTouchBegan(pTouch, pEvent);
    }
    else {
        // 滑动结束
        int offset = getPositionX() - m_CurPage * (-WINDOW_WIDTH);
        if (offset > WINDOW_WIDTH / 2) {
            // 上一页
            if (m_CurPage > 0) {
                --m_CurPage;
            }
        }
        else if (offset < -WINDOW_WIDTH / 2) {
            // 下一页
            if (m_CurPage < (m_Page - 1)) {
                ++m_CurPage;
            }
        }

        // 执行跳转动画
        goToPage();
    }
}

4.测试

写了一个测试层TestLayer,主要用来测试接收触摸事件

bool TestLayer::ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
{
    CCLOG("I am %d", getTag());
    
    return true;
}
简单的输出一个标记,可根据需求再具体分发触摸事件

5.用法

循环了10个子层,每层随机了一个背景色,用来区别各个子层,分别加入到ScrollView对象中

bool ScrollViewScene::init()
{
    bool bRet = false;
    
    do {
        CC_BREAK_IF(!CCScene::init());
        
        ScrollView *scrollView = ScrollView::node();
        
        CCSize winSize = CCDirector::sharedDirector()->getWinSize();
        for (int i=0; i<10; ++i) {
            CCLayer *layer = TestLayer::node();
            layer->setAnchorPoint(CCPointZero);
            layer->setTag(i);
            scrollView->addPage(layer);
        }
        
        this->addChild(scrollView);
        
        bRet = true;
    } while (0);
    
    return bRet;
}

效果如图

Cocos2d-x学习(七):cocos2d-x中ScrollView的简单实现_第1张图片

示例代码下载




你可能感兴趣的:(游戏,android,测试,存储,float,layer)