4

あいさつStackoverflow、

私は現在、開発中のcocos2d-xゲームにスクロールメニューを実装しようとしています。問題は、アイテムが私が望む方向と反対の方向にスクロールしていることです。たとえば、画面の下から上に指をドラッグすると、スプライトは元の位置に戻ります。

そして、指を上から下にドラッグすると、スプライトは指に追従します(境界に達するまで)。

これは私のコードです:

    /////////////////////
    //SCROLL VIEW + LAYER
    CCLayer *layer = CCLayer::create();
    layer->setContentSize( CCSizeMake( winSize.width, winSize.height ) );
    layer->addChild( menu );

    scrollView = CCScrollView::create();
    scrollView->retain();
    scrollView->setContentSize( CCSizeMake ( layer->getContentSize().width,  layer->getContentSize().height ) );
    scrollView->setDirection( CCScrollViewDirectionVertical );
    scrollView->setPosition( ccp( 0,0 ) );
    scrollView->setContainer( layer );

    this->addChild(scrollView);

    scrollView->setContentOffset( CCPointZero );

どんな提案や助けも大歓迎です。別のアプローチでスクロールメニューを作成するための他の回避策がある場合は、ぜひお聞かせください。

ありがとうございました!

よろしくアンドレアス

4

4 に答える 4

8

参照:cocos2dx / extends / GUI / CCScrollView / CCScrollView.cpp

具体的CCScrollView::minContainerOffsetにはCCScrollView::maxContainerOffset

CCScrollViewOpenGL座標で機能します(ウィンドウ座標ではありません)-値は(左、下)を基準にしており、正のY軸が上に向かっています。また、スクロールビューの位置とコンテナCCNode::setAnchorPointは(左、下)に固定されていることに注意してください。

下にスクロールすると(コンテンツを上に移動/プルしてカット/クリップの下のコンテンツを表示)、画面の下端の下にコンテンツが表示されますが、タッチ/ドラッグを離すとすぐに元にmaxContainerOffset戻り(0, 0)ます。ポジティブなコンテンツオフセットに移行しようとしました。

CCScrollViewとコンテナの座標

この図は、スクロールビューコンテナが作成/初期化されたときの状態を示しています。これは、子要素コンテナを設定および配置するときに「考える」状態または座標です。灰色の長方形(左、下)は、コンテナをスクロールするための有効な領域を示しています。コンテナのアンカーポイントがコンテナ内を移動すると想像してください。

コンテナが最初に上にスクロールされていることを確認するには(ウィンドウ座標で作業するときに期待すること)、それに応じてコンテンツオフセットを設定します(設定直後)。これにより、期待される結果/動作が得られます。

scrollView->setContentOffset(ccp(0.f, (scrollViewHeight-scrollContainerHeight)), false);

より完全な例は、以下の編集されたコードにあります。

  1. ウィンドウ座標(正のY軸を下向き)でスクロールできるようにする「修正」は、拡張子を調整することです。これには、cocos2dxライブラリを再構築する必要があり、すべてのプロジェクト(他のサンプルコードでも)に影響します。

    /*
    // (StackOverflow Post Edit: This hack is not required.)
    CCPoint CCScrollView::maxContainerOffset()
    {
        // Default CCPointZero;
        return ccp(0.0f, m_pContainer->getContentSize().height*m_pContainer->getScaleY() - m_tViewSize.height);
    }
    CCPoint CCScrollView::minContainerOffset()
    {
        // Default Y = m_tViewSize.height - m_pContainer->getContentSize().height*m_pContainer->getScaleY();
        return ccp(m_tViewSize.width - m_pContainer->getContentSize().width*m_pContainer->getScaleX(), 
               0.f);
    }
    */
    
  2. 邪魔にならない ハックScrollViewインスタンスを-1にスケーリングし、コンテナノードのも-1にスケーリングすることです。また、逆スケールを考慮して子ノードを再配置する必要があります。両方のレベルでのスケーリングの結果、コンテンツ(子ノード)がまっすぐに表示されます(反転されません)。ScrollViewを-1にスケーリングした結果、予想される方向にスクロールが実行されます。ただし、この「修正」はX軸のスクロールも反転するため、垂直方向にスクロールする場合にのみ適しています( )。CCScrollViewDirectionVertical

    CCSize winSize = CCDirector::sharedDirector()->getWinSize();
    CCLayer* scrollContainer = CCLayer::create(); // Container for the scroll view
    scrollContainer->setAnchorPoint(CCPointZero); // CCScrollView does this too when it's set as the container.
    
    // Content for the container
    CCSprite *tallContentA = CCSprite::create("TallContentA.png");
    tallContentA ->setPosition(ccp(winSize.width*0.5f, winSize.height*0.9f));
    CCSprite *tallContentB = CCSprite::create("TallContentB.png");
    tallContentB ->setPosition(ccp(winSize.width*0.5f, winSize.height*0.1f));
    scrollContainer->addChild(tallContentA, 2);
    scrollContainer->addChild(tallContentB, 2);
    
    float scrollContainerHeight = tallContentA->getContentSize().height + tallContentB->getContentSize().height;
    scrollContainer->setPosition(CCPointZero);
    scrollContainer->setContentSize(CCSizeMake(winSize.width, scrollContainerHeight*1.05f));
    
    // Set up scroll view
    CCScrollView* scrollView = CCScrollView::create(winSize, scrollContainer);
    scrollView->setPosition(CCPointZero);
    scrollView->setDirection(CCScrollViewDirectionVertical);
    // ScrollView initializes at the (left, bottom). The container also gets positioned relative to that and goes Y-up.
    // Pre-set it to the value CCScrollView::minContainerOffset will return when it's scrolled to the top
    // (note, this is a negative number, indicating the touch moving downwards, i.e. it's pre-scrolled such that the top of the content is visible when we begin)
    scrollView->setContentOffset(ccp(0.f, (winSize.height-scrollContainerHeight*1.05f)), false);
    /*
    // (StackOverflow Post Edit: This hack is not required.)
    // Hack: CCScrollView's maxContainerOffset is (0, 0) and minContainerOffset is (difference between view and content size which is negative)
    // It's designed to be (left, bottom) based and positive scrolling means showing stuff above the top of the screen.
    // Since we're using it in terms of Window coordinates ((left, top) based), we scale the scroll view
    // and it's container's children by -1 and position the children differently
    // (eg. Y position winSize.height*0.1f was changed to winSize.height*0.9f)
    // We can't just set the scroll view's Y scale to -1 because CCNode::getScale asserts that X and Y scale must be the same.
    scrollView->setScale(-1.f);
    tallContentA->setScale(-1.f);
    tallContentB->setScale(-1.f);
    */
    
    addChild(scrollView);
    

また、上記の2つの修正は相互に排他的であることに注意してください。両方を適用しないでください。

cocos2d-xフォーラムでも今すぐ回答してください。

于 2013-04-24T14:04:17.403 に答える
3

@ Zennichimaro、

@PATの答えは正しく、本質的に簡略化されたバージョンです

そのことを念頭に置いて、次の3つのことが重要であることに注意してください。

  1. CCScrollView::setViewSize()-これは明らかに見逃しました。表示可能なスペースの幅と高さである必要があります(青いボックス、フルスクリーンにする場合はwindowSize全体だと思います)

  2. CCScrollView::setContentSize()-これはsetContentOffsetとは異なり、これをsetContentOffsetと間違えたようです。とにかく、これはコンテナ全体のサイズに設定する必要があります(赤いボックス、おそらくあなたのサイズになりますccp(windowSize.width,2496.0f)

  3. CCScrollView::setContentOffset()-一番上が最初に表示されるように配置する場合、最小値と最大値は、回答の小さな灰色の長方形のボックスで指定されます(灰色のボックス、おそらくあなたのものになりますccp(0.0f, windowSize.height-2496.0f)

于 2013-12-10T03:15:48.173 に答える
3

短い答えは次のようになります。

scrollView->setContentOffset(scrollView->minContainerOffset());

アンカーポイントは左下隅にあるため、初期オフセットはゼロではなく、負の数です。

于 2014-03-15T17:13:25.703 に答える
0

誰かがmmoゲームのチャットテーブルのようにスクロールビューを作成したい場合(メッセージを下部に追加し、その下部に自動スクロールする)、おそらく誰かがこれを便利に見つけるでしょう:

ChatTableView.hのコードの一部

//tableView dataSource is vector of strings
class ChatTableView :public Layer, public TableViewDataSource, public TableViewDelegate
{
public:
    vector<string> n_msglist;
    TableView* pTableView;
    void addMsg(string text);
private:

};

//part of the code of my ChatTableView.cpp
void Init(){
    pTableView = TableView::create(this, VisibleRect::getVisibleRect().size, NULL);
    pTableView->setDirection(ScrollView::Direction::VERTICAL);
    pTableView->setVerticalFillOrder(TableView::VerticalFillOrder::TOP_DOWN);
    pTableView->setDelegate(this);
    pTableView->setBounceable(false);

} 
void ChatTableView::addMsg(string text){

    n_msglist.push_back(text); //adds string to vector
    pTableView->reloadData(); //reloads data with newly updated vector and scroll back to top
    pTableView->setContentOffset(pTableView->maxContainerOffset()); //scrolls to bottom
}
于 2014-08-03T17:39:29.123 に答える