Cocos2d—X遊戲開發之CCScrollView(滑動檢視)(十三)
阿新 • • 發佈:2019-01-07
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宣告.cpp實現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); };
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