Cocos2dx:实现游戏关卡ScrollView方式(二)

原创 2016年04月20日 19:14:07

今天我们实现关卡的选择是使用ScrollView这个类。当然还有一些其他的方法,比如使用page view也可以,见上文Cocos2dx:实现游戏关卡PageView方式(一)。先说下整体的思路,ScrollView这个类是继承自CCLayer的,本身的触摸事件有些bug,所以网上一般将这个层的touch事件处理为false,而使用它的父节点来处理触摸事件,我们也是采用这个做法。先定义一个LevelScene类,将ScrollView加入进来,然后再定义一个layer层,这个层里边放的就是一些关卡的图片,然后将layer这个层作为ScrollView的内容添加进去。


代码如下:

头文件:


//
//  LevelScene.h
//  MapTest
//
//  Created by Alostz on 16/4/21.
//  游戏关卡
//

#ifndef LevelScene_h
#define LevelScene_h

#include "cocos-ext.h"
#include "cocos2d.h"

using namespace cocos2d::extension;
using namespace cocos2d;

class LevelScene : public Layer
{
public:
    
    bool init();
    
    CREATE_FUNC(LevelScene);
    
    //以下是注册触摸事件和实现各种的touch函数
    virtual bool TouchBegan(Touch * touch, Event * pEvent);
    virtual void TouchMoved(Touch * touch, Event * pEvent);
    virtual void TouchEnded(Touch * touch, Event * pEvent);
    virtual void TouchCancelled(Touch *touch, Event * event);
    
    //最后这个函数来校验每个关卡的位置,是各个关卡都位于屏幕的中央
    void adjustScrollView(float offset);
    
private:
    //将CCScrollView作为自己的层添加进来
    ScrollView * m_scrollView;
    
    //触摸点的位置
    Point m_touchPoint;
    
    //CCScrollView的便宜量
    Point m_offsetPoint;
    
    //当前为第几个关卡
    int m_nCurPage;
};

#endif /* LevelScene_h */

cpp代码:

//
//  LevelScene.cpp
//  MapTest
//
//  Created by Alostz on 16/4/21.
//
//

/*关卡选择类的具体实现*/
#include "LevelScene.h"
#include <math.h>	//用到了fabs()函数,用来求绝对值的

bool LevelScene::init()
{
    bool bRet = false;
    do
    {
        CC_BREAK_IF(!Layer::init());
        
        Size winSize = Director::getInstance()->getWinSize();
        
        //ScrollView继承自Layer,传入的参数是view size的大小
        //view size也就是人看到的大小,content size也就是内容的大小
        //这里设置为整个屏幕的大小,也就是我们通过设备的整个屏幕去看里边的内容
        ScrollView * scrollView = ScrollView::create(Size(winSize.width,winSize.height));
        
//***********方式1:我觉得挺好的****************/
        
//        //以下是ScrollView的一些常用函数
//        //设置是否有反弹的效果,反弹就是当超出scrollview的大小的时候回到原来的位置
//        scrollView->setBounceable(true);
//        
//        //        ScrollView默认锚点是在(0,0)处
//        scrollView->ignoreAnchorPointForPosition(false);
//        scrollView->setPosition(Point(winSize.width/2, winSize.height/2));
//        //设置滑动方向
//        scrollView->setDirection(ScrollView::Direction::HORIZONTAL);
//        
//
        
        //公共:创建一个Layer,将内容添加到Layer中,然后将这个layer添加到scrollview中
        Layer * layer = Layer::create();
        for(int i = 0;i<5;i++)
        {
            String * string = String::createWithFormat("%d.jpg", i+1);
            Sprite * sprite = Sprite::create(string->getCString());
            
            //将所有的精灵都放到屏幕的中间显示
            sprite->setPosition(Point(winSize.width/2,winSize.height/2) + Point(winSize.width*i,0));
            sprite->setContentSize(Size(400, 400));
            layer->addChild(sprite);
        }
        //设置scrollView中的内容,必须先设置内容再设置内容的大小
        scrollView->setContainer(layer);
        scrollView->setContentSize(Size(winSize.width*5, winSize.height));
        
//***********方式2:屏蔽scrollView这个层的触摸,采用其他的实现方法****************/

        //屏蔽scrollView这个层的触摸,采用其他的实现方法
        scrollView->setTouchEnabled(false);
        //设置里边内容的偏移量
        scrollView->setContentOffset(Point(0, 0));
        this->addChild(scrollView);
        
        m_scrollView = scrollView;
        this->m_nCurPage = 0;
        
        bRet = true;
        
        //让本层来接受触摸事件!!!!!!!!!!!!!!!!!!!!
        auto touchListener = EventListenerTouchOneByOne::create();
        touchListener->onTouchBegan = CC_CALLBACK_2(LevelScene::TouchBegan, this);
        touchListener->onTouchMoved = CC_CALLBACK_2(LevelScene::TouchMoved, this);
        touchListener->onTouchEnded = CC_CALLBACK_2(LevelScene::TouchEnded, this);
        touchListener->onTouchCancelled = CC_CALLBACK_2(LevelScene::TouchCancelled, this);
        touchListener->setSwallowTouches(true);
        _eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, this);

    } while(0);
    
    return bRet;
}


bool LevelScene::TouchBegan(Touch * touch, Event * pEvent)
{
    //用开始的触摸点和scroll的偏移量初始化以下的成员变量
    this->m_touchPoint = touch->getLocation();
    this->m_offsetPoint = this->m_scrollView->getContentOffset();
    
    //以下的这一点特别要注意,大家可以先注释掉以下的这句话然后运行程序,会发现如果触摸不是很快
    //的时候不会有什么问题,但是如果触摸进行的很快,关卡的位置偏移的就不会正确,以下的代码正是解决这个问题到
    if((int)this->m_offsetPoint.x % ((int)Director::getInstance()->getWinSize().width) == 0)
    {
        return true;
    }
    return false;
}


/*以下代码的整体含义就是当手指移动的时候,让关卡跟随手指移动,当移动结束的时候,判断结束点和开始
 触摸点的位置,对关卡的位置做相应的处理*/

//设置关卡跟随手指的方向移动
void LevelScene::TouchMoved(Touch * touch, Event * pEvent)
{
    Point point = touch->getLocation();
    Point direction = point - this->m_touchPoint;
    
    //Point spriteDirection = ccpAdd(this->m_offsetPoint,direction);
    //只在x方向偏移
    Point spriteDirection = Point(direction.x + this->m_offsetPoint.x,0);
    this->m_scrollView->setContentOffset(spriteDirection);
}

//以下的代码是重点,当结束触摸的时候,为了使关卡显示在屏幕的中间,我们需要这么做
void LevelScene::TouchEnded(Touch * touch, Event * pEvent)
{
    Point endPoint = touch->getLocation();
    float distance = endPoint.x-this->m_touchPoint.x;
    //手指移动的距离小于20的时候,就将偏移量作为0处理
    if(fabs(distance) < 20)
    {
        this->adjustScrollView(0);
    }
    else
    {
        //将偏移量作为参数传进来
        this->adjustScrollView(distance);
    }
}

//以下的代码是重点,当结束触摸的时候,为了使关卡显示在屏幕的中间,我们需要这么做
void LevelScene::TouchCancelled(Touch * touch, Event * pEvent)
{
   
}

//调整关卡的最终位置
void LevelScene::adjustScrollView(float offset)
{
    Size winSize = Director::getInstance()->getWinSize();
    // 我们根据 offset 的实际情况来判断移动效果
    //如果手指往左划,offset大于0,说明页面在减小,往右增大
    if (offset < 0)
        m_nCurPage ++;
    else if (offset > 0)
        m_nCurPage --;
    
    //不允许超出最左边的一页和最右边的一页
    if (m_nCurPage < 0)
        m_nCurPage = 0;
    else if (m_nCurPage > 4)
        m_nCurPage = 4;
    
    Point adjustPoint = Point(-winSize.width * m_nCurPage , 0);
    //这个函数比setContentOffset多了一个参数,第二个参数是设置时间的,就是用多长的时间来改变偏移量
    this->m_scrollView->setContentOffsetInDuration(adjustPoint, 0.3f);
}




调用方式:


bool HelloWorld::init()
{
    //////////////////////////////
    // 1. super init first
    if ( !Layer::init() )
    {
        return false;
    }
    
    Size winSize = Director::getInstance()->getWinSize();
    Size visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();
    
    //添加背景图片
    Sprite * sprite = Sprite::create("background.jpg");
    sprite->setPosition(Point(visibleSize.width/2, visibleSize.height/2));
    this->addChild(sprite);
    
    //添加CCScrollView层
    LevelScene * scrollView = LevelScene::create();
    this->addChild(scrollView);

    return true;
}


文中使用scrollview采用了两种方式实现;第一种比较简单;第二站在父层实现touch事件处理。




版权声明:本文为博主原创文章,未经博主允许不得转载。

react native scrollview深入详解触摸滚动事件

大家都知道scrollview的几个属性和方法:详细的方法请参考: 江清清专栏:React Native控件之ScrollView组件讲解(14) 这里我就讲解下scrollview的...
  • liu__520
  • liu__520
  • 2016年12月15日 21:37
  • 7925

从ScrollView嵌套EditText的滑动事件冲突分析触摸事件的分发机制以及TextView的简要实现和冲突的解决办法

本篇文章假设读者没有任何的触摸事件基础知识,所以我们会从最基本的触摸事件分发处说起。 ScrollView为什么会出现嵌套EditText出现滑动事件冲突呢?相信你会有这种疑问,我们来看这么一种情...
  • u011064099
  • u011064099
  • 2016年04月21日 16:15
  • 3707

cocos2dx关卡选择界面设计

重点内容 做游戏时候经常用到关卡选择,写了个关卡选择界面逻辑类,关卡解锁,关卡类型显示,打过的关卡星级评定,一共六大关,每个大关10个小关,ui使用cocostudio编辑,代码如下: Level...
  • u011388741
  • u011388741
  • 2015年06月09日 11:25
  • 1083

cocos2d-x 关卡选择界面(CCScrollView的使用)

今天要写一个关卡选择界面。 百度了下,采用了CCScrollView来实现。 具体CCScrollView的使用就不介绍了。 百度大把。(关键字: CCScrollView详解) 这里,主要通过...
  • hitwhylz
  • hitwhylz
  • 2014年04月13日 17:30
  • 3940

【cocos2d-x 】解决scrollview上的menu拖动问题以及menu item在可视区外仍能触发的问题

在使用cocos2d-x的scroll view的时候,会遇到两个问题: 1)scroll view上放menu时,如果拖动menu scroll view不会被拖动,如果scroll view上全...
  • hj3601947
  • hj3601947
  • 2016年09月11日 16:06
  • 911

Android实践之ScrollView中滑动冲突处理

在Android开发中,如果是一些简单的布局,都很容易搞定,但是一旦涉及到复杂的页面,特别是为了兼容小屏手机而使用了ScrollView以后,就会出现很多点击事件的冲突,最经典的就是ScrollVie...
  • xiaohanluo
  • xiaohanluo
  • 2016年08月05日 17:08
  • 16689

【玩转cocos2d-x之十五】关卡选择的设计

这节介绍一下游戏中帮助界面和关卡选择的设计,其实都是一样的,关键在于美工。这里采用自定义TableView层来实现。 1.导入头文件和设定空间 因为TableView相关的类是在扩展包里面,所...
  • jackyvincefu
  • jackyvincefu
  • 2013年10月23日 09:35
  • 7198

Cocos2d-x 3.2 大富翁游戏项目开发ScrollView关卡选择

  • 2014年12月17日 00:32
  • 1.36MB
  • 下载

Android 解决 ListView的item中嵌套ScrollView,ScrollView拦截ListView的Item点击事件的解决办法

前沿:有时候,listview 的item要显示的字段比较多,考虑到显示问题,item外面不得不嵌套ScrollView来实现,于是问题来了,当listview需要做点击事件时,由于ScrollVie...
  • jky_yihuangxing
  • jky_yihuangxing
  • 2016年10月28日 14:36
  • 859

UIScrollView的作用原理,实现scrollView传递touch事件给子视图

我们知道当多个视图进行叠加的时候,touch事件是作用到最上面的视图上,但是如果父视图是UIScrollView,如果默认,可能touch子视图会造成UIScrollView的滚动。 UIScrol...
  • backapace
  • backapace
  • 2013年09月02日 11:03
  • 5679
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Cocos2dx:实现游戏关卡ScrollView方式(二)
举报原因:
原因补充:

(最多只允许输入30个字)