binxindoudou

(转自收音机的百度空间:http://hi.baidu.com/amigoradio/item/c7e3928c6d9bb2ccb071547b)

之前项目中使用CCScrollLayer的方法实现的了滚动效果。具体可以参考    这个帖子

当时CCScrollLayer只支持横向的滚动,但自己修改一下源码就可以支持纵向的滚动了,比较简单

这次项目中美术画的滚动效果不是全屏滚动,而是屏幕中间有一块300x300的区域,所有的道具需要在这里面横向滚动。

这个区域外面是一块半透明效果的图,所以没法使用CCScrollLayer来做,因为这个类不能裁剪区域,把多余的区域裁剪掉。

这种效果如果用ios的原生UIScrollView来做,是非常简单的,设置scrollView的frame可视的区域,然后设置contentSize内容区域

但看来效果不好,因为cocos2d里面引入UIScrollView很麻烦,而且UIScrollView里面要放入很多CCSpirte组装好的效果,

这样做非常麻烦,做起来代码也长也繁琐。所以找了一下资料就放弃这种方案了。

还是把精力集中在改造CCScrollLayer上,在cocos2d的社区找到一个CCScrollView的帖子,实现了UIScrollView的效果。

但我能力有限没能看明白怎样使用,也没明白他的原理。还找到一个帖子说CCScrollView限制很多,不建议使用。

但从CCScrollView我发现了opengl的glClipPlane,opengl的区域裁剪函数。

 

我的想法:做一个scrollLayer,scrollLayer中设置类似frame的显示区域,将frame之外的区域都裁剪掉,然后将要scroll的道具

加入到另一个layer中,再将这个装满道具的layer放入到scrollLayer中,scrollLayer中通过触摸事件来控制里面装道具的layer的

左右移动。这样可以达到UIScrollView的方法。具体看下面代码,从ccScrollLayer修改来的

1)首先加入下面方法,实现layer的裁剪,里面的几个数组我们之后在说

 

-(void) beforeDraw {

    GLfloat planeTop[]    = {0.0f, -1.0f, 0.0f, area.origin.y+area.size.height}; 

    GLfloat planeBottom[] = {0.0f, 1.0f, 0.0f, -area.origin.y};

    GLfloat planeLeft[]   = {1.0f, 0.0f, 0.0f, -area.origin.x};

    GLfloat planeRight[]  = {-1.0f, 0.0f, 0.0f, area.origin.x+area.size.width};

    

    glClipPlanef(GL_CLIP_PLANE0, planeTop);

    glClipPlanef(GL_CLIP_PLANE1, planeBottom);

    glClipPlanef(GL_CLIP_PLANE2, planeLeft);

    glClipPlanef(GL_CLIP_PLANE3, planeRight);

    glEnable(GL_CLIP_PLANE0);

    glEnable(GL_CLIP_PLANE1);

    glEnable(GL_CLIP_PLANE2);

    glEnable(GL_CLIP_PLANE3);

}

-(void) afterDraw {

    glDisable(GL_CLIP_PLANE0);

    glDisable(GL_CLIP_PLANE1);

    glDisable(GL_CLIP_PLANE2);

    glDisable(GL_CLIP_PLANE3);

}

 

2)修改visit方法,原ccScrollLayer中的visit内容包含分页的效果,但我不需要所以去掉了,这里主要是加入了

beforeDraw和afterDraw的调用

 

- (void) visit{

    [self beforeDraw];

[super visit];

    [self afterDraw];

}

3)修改initWithLayer和nodeWithLayer的方法,主要是修改了方法名和参数传入一个layer,因为layer中有很多东西,不方便传NSarray 

-(id) initWithViews:(CCNode *) view widthOffset: (int) widthOffset total:(int) total frame:(CGRect) rect{

if ( (self = [super init]) )

{

self.isTouchEnabled = YES;

scrollWidth_ = widthOffset;//一个元素的宽度,也就是每次滚动的大小,为了达到好的效果自己慢慢调吧

        totalScreens_ = total;    //在layer中计算好长度,也就是要滚动多少次达到最后一个元素

        currentScreen_ = 1;  //当前为第一个元素,也就是左边第一个

        area = rect;          //定义了显示区域的左下角和高宽

 

self.minimumTouchLengthToSlide = 30.0f;

self.minimumTouchLengthToChangePage = 100.0f;

        self.showPagesIndicator = YES;

 

        view.tag = SCROLLVIEWTAG;

        [selfaddChild:view];

}

return self;

}

 

4)修改moveToPage方法,把self改为上面添加的layer

CCNode *node = [selfgetChildByTag:SCROLLVIEWTAG];

 

id changePage = [CCMoveToactionWithDuration:0.3 position:ccp(-((page-1)*scrollWidth_),0)];

[node runAction:changePage];

5)修改ccTouchMoved方法,把self改为上面添加的layer

 

if (state_ == kCCScrollLayerStateSliding){

        CCNode *node = [selfgetChildByTag:SCROLLVIEWTAG];

        node.position = ccp((-(currentScreen_-1)*scrollWidth_)+(touchPoint.x-startSwipe_),0);

}

ccscrollLayer中的方法不变,下面的调用的方法

 

 

        CCLayer *layer = [DeskItemLayernode]; //创建一个放置好很多桌椅的layer

        CGRect rect = CGRectMake(60, 0, 360, 320); //设置可以显示的区域

        CCScrollView *scroll = [CCScrollViewnodeWithViews:layer widthOffset:90 total:layer.layerLong frame:rect];

        scroll.minimumTouchLengthToSlide = 20.0;

        scroll.minimumTouchLengthToChangePage = 50.0;

        [selfaddChild:scroll]; //增加这个scrollLayer

 

关于opengl的glClipPlanef方法,其实我也不明白这个函数,百度和google之后还是不明白。

还是建议大家去看opengl的书,做做例子来搞懂。下面说下我自己的理解

GL_CLIP_PLANE0 从0-5 是6个面,可以代表上下左右前后,还可以自己添加自己定义的面

 

 GLfloat plane[]    = {a,b,c,d}; 这个参数方程,我是一点都没看明白。。。。。。。

但我拿实际的代码调试出来了,abc是一个系数,分别代表xyz的方向,值有正负之分。d为具体的数值

比如 

GLfloat plane[]    = {1.0,0.0,0.0,-100.0}; 就是裁剪掉屏幕左边100个像素宽度的一个矩形区域

 

GLfloat plane[]    = {1.0,1.0,0.0,-100.0};就是裁剪掉屏幕左边的100个像素的一个三角形,左下角

 

GLfloat plane[]    = {2.0,1.0,0.0,-100.0};就是裁剪掉屏幕左边50个像素宽度的一个矩形区域

 

 

 

 

 glClipPlanef的信息可以参考这里 http://blog.csdn.net/sxzly/article/details/2295642

 

(转自收音机的百度空间:http://hi.baidu.com/amigoradio/item/c7e3928c6d9bb2ccb071547b)

分类:

技术点:

相关文章:

  • 2021-08-06
  • 2021-11-10
  • 2021-11-29
  • 2021-11-29
  • 2020-02-22
猜你喜欢
  • 2021-10-14
  • 2021-12-12
  • 2021-09-09
  • 2021-10-27
  • 2021-08-20
  • 2021-09-27
  • 2021-12-25
相关资源
相似解决方案