编辑:通过足够的重写和评论,我已经运行它,将在下面为其他人发布最终结果。
编辑2:我一直在更新我自己的版本,并且我了解到原始编码器对 C++ 不是很好,您可能需要在使用之前检查其中的所有内容,查看下面的评论
cocos2d-x 目前可用的 CCScrollView 有一个主要缺陷:它搞砸了。
具体来说,cpp 函数标头与 .h 文件的标头不匹配。cpp 文件指的是 UIEvent 和 NSMutableArray,而不是 X-Platform。
滚动视图本身必须添加一个数组,这限制了您使用 for 循环创建菜单项(如果创建菜单项)的能力,因为您不能使用可变的,并且它们不会像彼此一样子类化iOS 所以你不能只使用一个可变的然后说 CCArray * array = mutable->getMutableArray() 或类似的。
此外,定义已经过时(尽管可以通过 cocos2d-x 网站上的翻译规则添加 CCX_SAFE_DELETE 来修复),并且各种随机模板试图创建甚至不在项目中的 NS 和 UI 对象,因为我不知道为什么。
基本思想是,除了使用可变数组之外,这个类太混乱了,无法翻译成 C++。我不相信作者编译了他拥有的版本,因为标题不匹配。我以为我下载了 cpp 和 .h 文件(每个都有 2 个),并且两者都有 UIEvent 而不是 CC 以及其他问题。
注意:我已经修复了上面的各种问题,并且在各个地方将 SelectorProtocol 更改为 CCObject,但它只是变得不堪重负。
也许我应该改用 Parallax 节点?
这太荒谬了,也许它对 Cocos2d 很好,但它不适用于 c2d-X。无论如何,我会重新编码和搜索,感谢您的任何建议!
编辑:这是我现在正在使用的课程。尚未完成编辑,但这些可以让任何人开始,并且不仅仅在 iPhone 上进行编译
标题:
#ifndef __CCSCROLLLAYER__
#define __CCSCROLLLAYER__
// CCScrollLayer.h
//
// Copyright 2010 DK101
// http://dk101.net/2010/11/30/implementing-page-scrolling-in-cocos2d/
//
// Copyright 2010 Giv Parvaneh.
// http://www.givp.org/blog/2010/12/30/scrolling-menus-in-cocos2d/
//
// Copyright 2011 Stepan Generalov
//
// Copyright 2011 Eli Yukelzon
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// Original source: https://github.com/cocos2d/cocos2d-iphone-extensions/tree/master/Extensions/CCScrollLayer
// Last updated: October 1, 2011
#include "cocos2d.h"
namespace cocos2d {
class CCScrollLayer;
class CCScrollLayerDelegate
{
public:
/** Called when scroll layer begins scrolling.
* Usefull to cancel CCTouchDispatcher standardDelegates.
*/
virtual void scrollLayerScrollingStarted(CCScrollLayer* sender) {}
/** Called at the end of moveToPage:
* Doesn't get called in selectPage:
*/
virtual void scrollLayerScrolledToPageNumber(CCScrollLayer* sender, unsigned int page) {}
};
/*
It is a very clean and elegant subclass of CCLayer that lets you pass-in an array
of layers and it will then create a smooth scroller.
Complete with the "snapping" effect. You can create screens with anything that can be added to a CCLayer.
*/
class CCScrollLayer : public CCLayer
{
int currentScreen; //added
int totalScreens;
float scrollWidth;
float scrollHeight;
float startWidth;
float startHeight;
int startSwipe;
public:
//CCScrollLayer();
~CCScrollLayer();
static CCScrollLayer* nodeWithLayers(CCArray* layers, int widthOffset);
bool initWithLayers(CCArray* layers, int widthOffset);
/** Updates all pages positions & adds them as children if needed.
* Can be used to update position of pages after screen reshape, or
* for update after dynamic page add/remove.
*/
void updatePages();
/** Adds new page and reorders pages trying to set given number for newly added page.
* If number > pages count - adds new page to the right end of the scroll layer.
* If number <= 0 - adds new page to the left end of the scroll layer.
* @attention Designated addPage method.
*/
void addPage(CCLayer* aPage, unsigned int pageNumber);
/** Adds new page to the right end of the scroll layer. */
void addPage(CCLayer* aPage);
/** Removes page if it's one of scroll layers pages (not children)
* Does nothing if page not found.
*/
void removePage(CCLayer* aPage);
/** Removes page with given number. Doesn nothing if there's no page for such number. */
void removePageWithNumber(unsigned int pageNumber);
/* Moves scrollLayer to page with given number & invokes delegate
* method scrollLayer:scrolledToPageNumber: at the end of CCMoveTo action.
* Does nothing if number >= totalScreens or < 0.
*/
void moveToPage(unsigned int pageNumber);
/* Immedeatly moves scrollLayer to page with given number without running CCMoveTo.
* Does nothing if number >= totalScreens or < 0.
*/
void selectPage(unsigned int pageNumber);
CC_SYNTHESIZE(CCScrollLayerDelegate*, m_pDelegate, Delegate);
/** Calibration property. Minimum moving touch length that is enough
* to cancel menu items and start scrolling a layer.
*/
CC_SYNTHESIZE(CGFloat, m_fMinimumTouchLengthToSlide, MinimumTouchLengthToSlide);
/** Calibration property. Minimum moving touch length that is enough to change
* the page, without snapping back to the previous selected page.
*/
CC_SYNTHESIZE(CGFloat, m_fMinimumTouchLengthToChangePage, MinimumTouchLengthToChangePage);
/** If YES - when starting scrolling CCScrollLayer will claim touches, that are
* already claimed by others targetedTouchDelegates by calling CCTouchDispatcher#touchesCancelled
* Usefull to have ability to scroll with touch above menus in pages.
* If NO - scrolling will start, but no touches will be cancelled.
* Default is YES.
*/
CC_SYNTHESIZE(bool, m_bStealTouches, StealTouches);
/** Whenever show or not white/grey dots under the scroll layer.
* If yes - dots will be rendered in parents transform (rendered after scroller visit).
*/
CC_SYNTHESIZE(bool, m_bShowPagesIndicator, ShowPagesIndicator);
/** Position of dots center in parent coordinates.
* (Default value is screenWidth/2, screenHeight/4)
*/
CC_SYNTHESIZE_PASS_BY_REF(CCPoint, m_tPagesIndicatorPosition, PagesIndicatorPosition);
/** Total pages available in scrollLayer. */
unsigned int getTotalScreens() const;
/** Current page number, that is shown. Belongs to the [0, totalScreen] interval. */
CC_SYNTHESIZE_READONLY(unsigned int, m_uCurrentScreen, CurrentScreen);
/** Offset, that can be used to let user see next/previous page. */
CC_SYNTHESIZE(CGFloat, m_fPagesWidthOffset, PagesWidthOffset);
/** Offset that can be used to let user see empty space over first or last page. */
CC_SYNTHESIZE(CGFloat, m_fMarginOffset, MarginOffset);
/** Array of pages CCLayer's */
CC_SYNTHESIZE_READONLY(CCArray*, m_pLayers, Pages);
protected:
// The x coord of initial point the user starts their swipe.
CGFloat m_fStartSwipe;
// Internal state of scrollLayer (scrolling or idle).
int m_iState;
bool m_bStealingTouchInProgress;
// Holds the touch that started the scroll
CCTouch* m_pScrollTouch;
//void visit();
//void moveToPageEnded();
unsigned int pageNumberForPosition(const CCPoint& position);
CCPoint positionForPageWithNumber(unsigned int pageNumber);
void claimTouch(CCTouch* pTouch);
void cancelAndStoleTouch(CCTouch* pTouch, CCEvent* pEvent);
//void registerWithTouchDispatcher();
bool ccTouchBegan(CCTouch* pTouch, CCEvent* pEvent);
void ccTouchMoved(CCTouch* pTouch, CCEvent* pEvent);
void ccTouchEnded(CCTouch* pTouch, CCEvent* pEvent);
//void ccTouchCancelled(CCTouch* pTouch, CCEvent* pEvent);
};
} //end namespace
#endif
CPP
// CCScrollLayer.cpp
// Museum
//
// Created by GParvaneh on 29/12/2010.
// Copyright 2010. All rights reserved.
// Ported to C++ by Lior Tamam on 03/04/2011
#include "CCScrollLayer.h"
using namespace cocos2d;
CCScrollLayer* CCScrollLayer::nodeWithLayers(CCArray* layers, int widthOffset)
{
CCScrollLayer *pRet = new CCScrollLayer();
if (pRet && pRet->initWithLayers(layers, widthOffset))
{
pRet->autorelease();
return pRet;
}
CCX_SAFE_DELETE(pRet);
return NULL;
}
bool CCScrollLayer::initWithLayers(CCArray* layers, int widthOffset)
{
if (CCLayer::init())
{
// Make sure the layer accepts touches
CCTouchDispatcher::sharedDispatcher()->addTargetedDelegate(this,0,true);
// Set up the starting variables
//if(!widthOffset)
{
// widthOffset = 0;
}
currentScreen = 1;
// offset added to show preview of next/previous screens
scrollWidth = (int)CCDirector::sharedDirector()->getWinSize().width - widthOffset;
scrollHeight = (int)CCDirector::sharedDirector()->getWinSize().height;
startWidth = scrollWidth;
startHeight = scrollHeight;
// Loop through the array and add the screens
unsigned int i;
for (i=0; i<layers->count(); i++)
{
CCLayer* l = (CCLayer*)layers->objectAtIndex(i);
//l->setAnchorPoint(ccp(0,0));
//l->setPosition(ccp((i*scrollWidth),0));
addChild(l);
}
// Setup a count of the available screens
totalScreens = layers->count();
return true;
}
else
{
return false;
}
}
void CCScrollLayer::setMaximumScrollHeight(float maxHeight)
{
//Make the offset match expected pixels (include the current screen if at ccp(0,0)
maxHeight -= CCDirector::sharedDirector()->getWinSize().height;
maximumScrollHeight = maxHeight;
}
CCScrollLayer::~CCScrollLayer()
{
CCTouchDispatcher::sharedDispatcher()->removeDelegate(this);
CCLayer::onExit();
}
bool CCScrollLayer::ccTouchBegan(CCTouch *touch, CCEvent *withEvent)
{
//
// CCPoint touchPoint = touch->locationInView();
// touchPoint = CCDirector::sharedDirector()->convertToGL(touchPoint);
//
// startSwipe = (int)touchPoint.y;
return true;
}
void CCScrollLayer::ccTouchMoved(CCTouch *touch, CCEvent *withEvent)
{
CCPoint touchPoint = touch->locationInView();
CCPoint prevPoint = touch->previousLocationInView();
touchPoint = CCDirector::sharedDirector()->convertToGL(touchPoint);
prevPoint = CCDirector::sharedDirector()->convertToGL(prevPoint);
CCPoint difference = ccp( touchPoint.x - prevPoint.x , touchPoint.y - prevPoint.y);
CCPoint currentPos = this->getPosition();
currentPos = ccp( currentPos.x, currentPos.y+difference.y);
if (currentPos.y > maximumScrollHeight)
{
currentPos.y = maximumScrollHeight;
//this->setPositionY(maximumScrollHeight);
}
else if (currentPos.y < 0)
{
currentPos.y = 0;
// this->setPositionY(0);
}
this->setPosition(currentPos);
}
/*
void CCScrollLayer::ccTouchEnded(CCTouch *touch, CCEvent *withEvent)
{
//CCPoint touchPoint = touch->locationInView();
//touchPoint = CCDirector::sharedDirector()->convertToGL(touchPoint);
int newX = (int)touchPoint.x;
if ( (newX - startSwipe) < -scrollWidth / 3 && (currentScreen+1) <= totalScreens )
{
// this->moveToNextPage();
}
else if ( (newX - startSwipe) > scrollWidth / 3 && (currentScreen-1) > 0 )
{
// this->moveToPreviousPage();
}
else
{
// this->moveToPage(currentScreen);
}
}
*/