(cocos2d-x)ScrollView(CCScrollView)の動きをiOSのUIScrollViewっぽくする

最近cocoStudioが出て、cocos2d-x用のUIScrollViewやらUIListViewやらが出たので、今後使わなくなる可能性もあるが、現状まだScrollViewの方を多く使うのでメモ。

ScrollViewは初期状態のままだとiOSのUIKit.frameworkのUIScrollViewと違い、限界以上にスクロールを引っ張ったときのバウンスの挙動が現在タップしている地点まで移動してしまうので、ScrollViewの中を直接いじって限界以上に引っ張るほど移動しにくくなる用にしてUIScrollViewっぽくした。

ただ、減速度などの計算をするのが面倒だったので簡易的なものにしたので、きちんと実装したい人は減速度とかをちゃんと計算した方がいいと思います。
以下コード(CCScrollView.cppのonTouchMoved一部を書き換えています)


		newX     = _container->getPosition().x + moveDistance.x;
                newY     = _container->getPosition().y + moveDistance.y;

                //追加ここから
                const Point minOffset = this->minContainerOffset();
                const Point maxOffset = this->maxContainerOffset();

                int divisionNum = 20;
                float offsetWeight;

                float widthDiff = 0.0f;
                if (getContentSize().width < getViewSize().width) {
                    widthDiff = getContentSize().width - getViewSize().width;
                }
                if (minOffset.x > newX) {
                    offsetWeight = newX - minOffset.x;
                    offsetWeight /= divisionNum;
                    if (offsetWeight > -1)
                        offsetWeight = -1;
                    newX = newX - (moveDistance.x + (moveDistance.x / offsetWeight)) ;
                    moveDistance.x = 0.0f;
                } else if (maxOffset.x < newX){
                    offsetWeight = newX - maxOffset.x;
                    offsetWeight /= divisionNum;
                    if (offsetWeight < 1)
                        offsetWeight = 1;
                    newX = newX - (moveDistance.x - (moveDistance.x / offsetWeight)) ;
                    moveDistance.x = 0.0f;
                }

                if (minOffset.y > newY) {
                    offsetWeight = newY - minOffset.y;
                    offsetWeight /= divisionNum;
                    if (offsetWeight > -1)
                        offsetWeight = -1;
                    newY = newY - (moveDistance.y + (moveDistance.y / offsetWeight)) ;
                    moveDistance.y = 0.0f;
                } else if (maxOffset.y  < newY){

                    offsetWeight = newY - maxOffset.y;
                    offsetWeight /= divisionNum;
                    if (offsetWeight < 1)
                        offsetWeight = 1;
                    newY = newY - (moveDistance.y - (moveDistance.y / offsetWeight)) ;
                    moveDistance.y = 0.0f;
                }
                //ここまで
 

                _scrollDistance = moveDistance;
                this->setContentOffset(Point(newX, newY));


divisionNumの値を変えると減速の度合いを変えられるようになっています。
ただ、まだ縦の挙動しか確認してないので他のスクロールにするとバグるかもしれないです。

//2014/1/9 追記
2点修正しました。
ContainerのサイズがViewSize以下だと上に引っ張ったときの動きがおかしくなっていたところと、
小数点以下同士の割り算になっていた部分の修正をしました

//2014/8/7 追記2
コメントいただいていた部分(半年ぐらいブログを放置していたので今更ですが)の修正を行いました
ただ、cocos2d-x-3.0rc1以降では、既にバウンスの機能が実装されているので、
上記実装を行わずともCCScrollView.cppのBOUNCE_BACK_FACTORをいじってやれば
割と望み通りのバウンスの挙動ができると思います(戻るときの動きが少し気になりますが)

~ by ころさめ : 12月 18, 2013.

3件のフィードバック to “(cocos2d-x)ScrollView(CCScrollView)の動きをiOSのUIScrollViewっぽくする”

  1. cocoStudioだとScrollViewの実装は簡単なのでしょうか?

  2. } else if (maxOffset.x < newX){

    この条件に入る時の挙動がバウンスせずに右斜め上に移動しました。

    縦の挙動しか確認してないとのことなので横スクロールバグだと思うのですが、確認と修正をお願いすることは可能でしょうか?

  3. よくよく見てみたら、newYに代入してるようでした。
    newXのミスっぽいです。

    – newY = newX – (moveDistance.x – (moveDistance.x / offsetWeight)) ;
    + newX = newX – (moveDistance.x – (moveDistance.x / offsetWeight)) ;

コメントを残す