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;
}

效果如圖



示例代碼下載




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章