Cocos2d—X游戏开发之CCScrollView(滑动视图)(十二)

CCScrollView在Cocos2d-X引擎中主要使用在图片尺寸远大于屏幕尺寸的时候使用。

总体来说,使用起来比较简单。

一个是CCScrollView控件本身,一个是CCScrollViewDelegate代理。

#1.现在我们先来看CCScrollView的主要方法:

 */
//滑动方向
typedef enum {
	kCCScrollViewDirectionNone = -1,
    kCCScrollViewDirectionHorizontal = 0,
    kCCScrollViewDirectionVertical,
    kCCScrollViewDirectionBoth
} CCScrollViewDirection;

class CCScrollView;

class CCScrollViewDelegate
{
public:
    virtual ~CCScrollViewDelegate() {}
    virtual void scrollViewDidScroll(CCScrollView* view) = 0;  //滑动调用
    virtual void scrollViewDidZoom(CCScrollView* view) = 0;  //缩放调用
};


/**
 * ScrollView support for cocos2d for iphone.
 * It provides scroll view functionalities to cocos2d projects natively.
 */
class CCScrollView : public CCLayer
{
public:
    CCScrollView();
    virtual ~CCScrollView();

    bool init();
    virtual void registerWithTouchDispatcher();

    /**
     * Returns an autoreleased scroll view object.
     *
     * @param size view size
     * @param container parent object
     * @return autoreleased scroll view object
     */
    static CCScrollView* create(CCSize size, CCNode* container = NULL);

    /**
     * Returns an autoreleased scroll view object.
     *
     * @param size view size
     * @param container parent object
     * @return autoreleased scroll view object
     */
    static CCScrollView* create();

    /**
     * Returns a scroll view object
     *
     * @param size view size
     * @param container parent object
     * @return scroll view object
     */
    bool initWithViewSize(CCSize size, CCNode* container = NULL);


    /**
     * Sets a new content offset. It ignores max/min offset. It just sets what's given. (just like UIKit's UIScrollView)
     *
     * @param offset new offset
     * @param If YES, the view scrolls to the new offset
     */
    void setContentOffset(CCPoint offset, bool animated = false);
    CCPoint getContentOffset();
    /**
     * Sets a new content offset. It ignores max/min offset. It just sets what's given. (just like UIKit's UIScrollView)
     * You can override the animation duration with this method.
     * 设置新的容器坐标
     * @param offset new offset
     * @param animation duration
     */
    void setContentOffsetInDuration(CCPoint offset, float dt); 

    void setZoomScale(float s);
    /**
     * Sets a new scale and does that for a predefined duration.
     * 设置CCScrollView的缩放
     * @param s a new scale vale
     * @param animated if YES, scaling is animated
     */
    void setZoomScale(float s, bool animated);

    float getZoomScale();

    /**
     * Sets a new scale for container in a given duration.
     *
     * @param s a new scale value
     * @param animation duration
     */
    void setZoomScaleInDuration(float s, float dt);
    /**
     * Returns the current container's minimum offset. You may want this while you animate scrolling by yourself
     */
    CCPoint minContainerOffset();
    /**
     * Returns the current container's maximum offset. You may want this while you animate scrolling by yourself
     */
    CCPoint maxContainerOffset(); 
    /**
     * Determines if a given node's bounding box is in visible bounds
     *
     * @return YES if it is in visible bounds
     */
    bool isNodeVisible(CCNode * node);
    /**
     * Provided to make scroll view compatible with SWLayer's pause method
     */
    void pause(CCObject* sender);
    /**
     * Provided to make scroll view compatible with SWLayer's resume method
     */
    void resume(CCObject* sender);


    bool isDragging() {return m_bDragging;} 
    bool isTouchMoved() { return m_bTouchMoved; }
    bool isBounceable() { return m_bBounceable; } //是否开启弹性滑动,默认true,false滑动失效
    void setBounceable(bool bBounceable) { m_bBounceable = bBounceable; }

    /**
     * size to clip. CCNode boundingBox uses contentSize directly.
     * It's semantically different what it actually means to common scroll views.
     * Hence, this scroll view will use a separate size property.
     */
    CCSize getViewSize() { return m_tViewSize; } 
    void setViewSize(CCSize size);

    CCNode * getContainer();
    void setContainer(CCNode * pContainer);  //设置,获取容器的一对方法

    /**
     * direction allowed to scroll. CCScrollViewDirectionBoth by default.
     */
    CCScrollViewDirection getDirection() { return m_eDirection; }
    virtual void setDirection(CCScrollViewDirection eDirection) { m_eDirection = eDirection; }   //设置,获取CCScrollView的对齐方向

    CCScrollViewDelegate* getDelegate() { return m_pDelegate; }
    void setDelegate(CCScrollViewDelegate* pDelegate) { m_pDelegate = pDelegate; }  //设置代理对象

    /** override functions */
    // optional
    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);

    virtual void setContentSize(const CCSize & size); //设置容器大小
    virtual const CCSize& getContentSize() const;

	void updateInset();
    /**
     * Determines whether it clips its children or not.
     */
    bool isClippingToBounds() { return m_bClippingToBounds; }
    void setClippingToBounds(bool bClippingToBounds) { m_bClippingToBounds = bClippingToBounds; }

    virtual void visit();
    virtual void addChild(CCNode * child, int zOrder, int tag);
    virtual void addChild(CCNode * child, int zOrder);
    virtual void addChild(CCNode * child);
    void setTouchEnabled(bool e);
private:
    /**
     * Relocates the container at the proper offset, in bounds of max/min offsets.
     *
     * @param animated If YES, relocation is animated
     */
    void relocateContainer(bool animated);
    /**
     * implements auto-scrolling behavior. change SCROLL_DEACCEL_RATE as needed to choose
     * deacceleration speed. it must be less than 1.0f.
     *
     * @param dt delta
     */
    void deaccelerateScrolling(float dt);
    /**
     * This method makes sure auto scrolling causes delegate to invoke its method
     */
    void performedAnimatedScroll(float dt);
    /**
     * Expire animated scroll delegate calls
     */
    void stoppedAnimatedScroll(CCNode* node);
    /**
     * clip this view so that outside of the visible bounds can be hidden.
     */
    void beforeDraw();
    /**
     * retract what's done in beforeDraw so that there's no side effect to
     * other nodes.
     */
    void afterDraw();
    /**
     * Zoom handling
     */
    void handleZoom();

protected:
    CCRect getViewRect();
    
    /**
     * current zoom scale
     */
    float m_fZoomScale;
    /**
     * min zoom scale
     */
    float m_fMinZoomScale;
    /**
     * max zoom scale
     */
    float m_fMaxZoomScale;
    /**
     * scroll view delegate
     */
    CCScrollViewDelegate* m_pDelegate;

    CCScrollViewDirection m_eDirection;
    /**
     * If YES, the view is being dragged.
     */
    bool m_bDragging;

    /**
     * Content offset. Note that left-bottom point is the origin
     */
    CCPoint m_tContentOffset;

    /**
     * Container holds scroll view contents, Sets the scrollable container object of the scroll view
     */
    CCNode* m_pContainer;
    /**
     * Determiens whether user touch is moved after begin phase.
     */
    bool m_bTouchMoved;
    /**
     * max inset point to limit scrolling by touch
     */
    CCPoint m_fMaxInset;
    /**
     * min inset point to limit scrolling by touch
     */
    CCPoint m_fMinInset;
    /**
     * Determines whether the scroll view is allowed to bounce or not.
     */
    bool m_bBounceable;

    bool m_bClippingToBounds;

    /**
     * scroll speed
     */
    CCPoint m_tScrollDistance;
    /**
     * Touch point
     */
    CCPoint m_tTouchPoint;
    /**
     * length between two fingers
     */
    float m_fTouchLength;
    /**
     * UITouch objects to detect multitouch
     */
    CCArray* m_pTouches;
    /**
     * size to clip. CCNode boundingBox uses contentSize directly.
     * It's semantically different what it actually means to common scroll views.
     * Hence, this scroll view will use a separate size property.
     */
    CCSize m_tViewSize;
    /**
     * max and min scale
     */
    float m_fMinScale, m_fMaxScale;
    /**
     * scissor rect for parent, just for restoring GL_SCISSOR_BOX
     */
    CCRect m_tParentScissorRect;
    bool m_bScissorRestored;
};

#2.现在看下示例代码:

.h声明
class HelloWorld : public cocos2d::CCLayer, public CCScrollViewDelegate
{
private:
    
    CCScrollView *scroll ;
    float xOffSet;
    float yOffSet;
    
public:
    
    virtual bool init();
    static cocos2d::CCScene* scene();
    void menuCloseCallback(CCObject* pSender);
    CREATE_FUNC(HelloWorld);
    
    virtual void scrollViewDidScroll(CCScrollView* view);
    virtual void scrollViewDidZoom(CCScrollView* view);
   
    
};

.cpp实现

bool HelloWorld::init()
{
    // 1. super init first
    if ( !CCLayer::init() )
    {
        return false;
    }

    CCSize winSize = CCDirector::sharedDirector()->getWinSize();
    
    
    //设置scrollView的大小,为显示的view的尺寸
    scroll = CCScrollView::create(CCSizeMake(960, 640));
    
    CCSprite *bg = CCSprite::create("11.png");
    
    //bg->setPosition(ccp(winSize.width/2, winSize.height/2));
    //容器的锚点是(0,0)
    bg->setPosition(ccp(0, 0));
    
    CCMenuItemImage *back = CCMenuItemImage::create("Icon.png", "Icon.png");
    back->setPosition(CCPoint(200, 200));
    bg->addChild(back);
    
    //bg->setAnchorPoint(ccp(0.5, 0.5));
    //scroll->setAnchorPoint(ccp(0, 0));
    
    //设置容器
    scroll->setContainer(bg);
        
    //是开启弹性效果,关闭的话就不用使用这个控件
    //scroll->setBounceable(false);
    bool flag = scroll->isBounceable();
    CCLog("flag: %d",flag);
    
    //设置滑动方向
    //kCCScrollViewDirectionHorizontal——水平滑动
    //kCCScrollViewDirectionVertical——垂直滑动
    scroll->setDirection(kCCScrollViewDirectionBoth);
    
    //设置容器大小
    scroll->setContentSize(CCSizeMake(978, 2189));
    //触摸有效
    this->setTouchEnabled(true);
    CCSize scrollSize = scroll->getContentSize();
    CCLog("scrollSize: %f %f",scrollSize.width,scrollSize.height);
    
    //设置代理为自身
    scroll->setDelegate(this);
    this->addChild(scroll);
    
    //黑边防御坐标
    xOffSet = winSize.width - scrollSize.width;
    yOffSet = winSize.height - scrollSize.height;
    
    
    
    return true;
}

void HelloWorld::scrollViewDidScroll(CCScrollView* view)
{
    static int flag = 0;
    CCLog("Scroll %d",flag++);
    
    CCPoint offSet = this->scroll->getContentOffset();
    CCLog("offSet : %f %f",offSet.x,offSet.y);
    if (offSet.x < this->xOffSet || offSet.y < this->yOffSet) {
        
        CCLog("scrollView 已经出现黑边问题了!");
        
        if (offSet.x < this->xOffSet ) {
            CCLog("scrollView X轴 出现黑边问题了!");
            this->scroll->setContentOffset(CCPoint(this->xOffSet, offSet.y));
        }else{
            CCLog("scrollView Y轴 已经出现黑边问题了!");
            this->scroll->setContentOffset(CCPoint(offSet.x, this->yOffSet));
        }
    }
    
    if (offSet.x > 0 || offSet.y > 0) {
        CCLog("scrollView 已经出现黑边问题了!");
        
        if (offSet.x > 0 ) {
            CCLog("scrollView X轴 出现黑边问题了!");
            this->scroll->setContentOffset(CCPoint(0, offSet.y));
        }else{
            CCLog("scrollView Y轴 已经出现黑边问题了!");
            this->scroll->setContentOffset(CCPoint(offSet.x, 0));
        }
        
    }
    
}

#3.现在,我们来看下效果

原图的尺寸是978*2189










原文地址:https://www.cnblogs.com/james1207/p/3268706.html