使用C++进行Cocos2d-x游戏开发入门过程中的要点解析

 更新时间:2015年12月24日 16:21:23   投稿:goldensun  
这篇文章主要介绍了使用C++进行Cocos2d-x游戏开发入门过程中的要点解析,主要针对画面变化以及触摸响应方面,需要的朋友可以参考下

总结了下,新手引导的要点有以下几个:

  • 画面的变化.
  • 触摸和按钮响应.
  • 逻辑处理及代码组织.

下面我们就详细讲述这几个要点:

一.画面的变化.

对个这个不同的游戏的做法不尽相同,归结起来大概有这么几种:

1.画面整体变暗

这个比较简单,cocos2d就有现成接口:


CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
//第一个参数是颜色ccc4(r,g,b,a) a取值(0~255),越大越不透明 下面两个参数为宽高,不传默认为屏幕大小
CCLayerColor* pLayer=CCLayerColor::create(ccc4(0,0,0,200),visibleSize.width,visibleSize.height);
//CCLayerColor* pLayer=CCLayerColor::create(ccc4(0,0,0,200));
addChild(pLayer,100);

效果如下:

20151224161245055.png (300×207)

然后你可以在这层之上添加精灵,最后的效果可能是这个样子的:

20151224161304281.jpg (300×200)

注:图片源自网络,如果有版权问题~你丫去死吧! 请联系我!

2.局部高亮

比较简单的方法是准备几张张局部高亮的图片,随着引导进度变化而切换!优点是可以做的比较精美,缺点是资源量会比较大!另一种方法是在画面整体变暗的基础上抠掉部分区域,还好cocos2d提供了CCClippingNode接口(2.1+版)!

CCClippingNode类比较复杂,但我们只用明白两个东西就好:一个是CCClippingNode的Stencil,一个CCClippingNode的Child,怎么理解呢?请看下图:

20151224161337076.jpg (300×225)

这个东西相信大家都有印象吧,上面的图案(镂空部分)就是 CCClippingNode的Stencil(模板),实体部分就是CCClippingNode的child(底板),是不是很好明白,让我们用代码来实现吧:

//创建cliper对象
CCClippingNode* pClip=CCClippingNode::create();
addChild(pClip);
//加入灰色的底板
CCLayerColor* pColor=CCLayerColor::create(ccc4(0,0,0,200));
pClip->addChild(pColor);

让我来加入模板:

//创建drawnode对象
CCDrawNode *m_pAA=CCDrawNode::create();
static ccColor4F green = {0, 1, 0, 1};
static CCPoint rect[4]={ccp(-50,50),ccp(50,50),ccp(50,-50),ccp(-50,-50)};
//用上面的数据保存一个100x100的矩形
m_pAA->drawPolygon(rect, 4, green, 0, green);
//设置到屏幕的中心
m_pAA->setPosition(ccp(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
//设置为pclip的模板
pClip->setStencil(m_pAA);

CCDrawNode是用来绘制几何图形的,drawPolygon使用绘制多边形,参数为顶点数组,顶点数量,边框宽度,和填充颜色!这里要注意一点:千万不要addChild(m_pAA);因为一旦addchild,m_pAA就会被绘制出来,我们是要用它做剪裁!他会在CCClippingNode内部被使用!

我们会看到这样的效果:

20151224161409119.png (246×300)

额,貌似和我们想想的不太一样啊,为什么呢?那是因为CCClippingNode有一个选项是是否反向,既显示Stencil呢还是child减去Stencil的部分!默认为显示显示镂空(Stencil)部分(false),因此我们要改变选项:

//是否反向?
pClip->setInverted(true);

效果如下,是不是很棒:

20151224161439723.png (237×300)

3.组合效果(将2的矩形改成圆,再加上图片)

让我们先看这张图片,是不是很棒?右下角黄色矩形区域是高亮的,在配上图片说明,很不错的效果!

20151224161456152.png (300×231)

让我们来实现类似的效果吧,用到的资源:

20151224161524560.png (101×115)

//创建cliper
CCClippingNode* pClip=CCClippingNode::create();
pClip->setInverted(true);
addChild(pClip);
//添加底板
CCLayerColor* pColor=CCLayerColor::create(ccc4(0,0,0,200));
pClip->addChild(pColor);

//绘制圆形区域
static ccColor4F green = {0, 1, 0, 1};//顶点颜色,这里我们没有实质上没有绘制,所以看不出颜色
float fRadius=55.0f;//圆的半径
const int nCount=100;//圆形其实可以看做正多边形,我们这里用正100边型来模拟园
const float coef = 2.0f * (float)M_PI/nCount;//计算每两个相邻顶点与中心的夹角
static CCPoint circle[nCount];//顶点数组
for(unsigned int i = 0;i <nCount; i++) {
 float rads = i*coef;//弧度
 circle[i].x = fRadius * cosf(rads);//对应顶点的x
 circle[i].y = fRadius * sinf(rads);//对应顶点的y
}
CCDrawNode *pStencil=CCDrawNode::create();
pStencil->drawPolygon(circle, nCount, green, 0, green);//绘制这个多边形!

//动起来
pStencil->runAction(CCRepeatForever::create(CCSequence::createWithTwoActions(CCScaleBy::create(0.05f, 0.95f),
 CCScaleTo::create(0.125f, 1))));
pStencil->setPosition(ccp(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));

//设这模板
pClip->setStencil(pStencil);

//添加圆和手的图片
CCSprite*pCircle=CCSprite::create("circle.png");
pCircle->setPosition(ccp(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
pCircle->runAction(CCRepeatForever::create(CCSequence::createWithTwoActions(CCScaleBy::create(0.05f, 0.95f),
 CCScaleTo::create(0.125f, 1))));
addChild(pCircle);

CCSprite* pHand=CCSprite::create("hand.png");
pHand->setAnchorPoint(ccp(0.0f,1.0f));
pHand->setPosition(ccp(pCircle->getContentSize().width/2,pCircle->getContentSize().height/2));
pCircle->addChild(pHand);

上面是全部的代码,效果图如下(动态的会更好)没有加圆圈和手之前和之后:

20151224161556795.png (279×300)20151224161617351.png (300×289)

那么如何改变高亮区域得位置呢?很简单,只用改变pStencil的位置即可!可以考虑记为成员变量在ccTouchesBegan中改变位置,这样就会高亮区域就会跟着你的鼠标走啦!

二.触摸和按钮响应

1.开启触摸 阻止穿透响应 判断落点

让我们继续看下面的这张图片:

20151224161655490.png (300×231)

这张图片中应该只有右下角的”冒险”按钮能够响应的到,在这里说下思路:

为了让其他区域的按钮响应不到,我们应该提高上层(CClayer)的响应优先级为-128和按钮一样,这样的话如果上层(CClayer)后加入游戏addchild的话,会先收到触摸消息.
在收到触摸消息ccTouchBegan时,判断点击的地方是否在黄色矩形区域中,在的话return false 交给下层的按钮去响应,否则return true 阻止消息继续传递.
下面是代码片段:
1).开启触摸

bool CTeachLayer::init()
{
 if (!CCLayer::init())
 {
 return false;
 }
 setTouchEnabled(true);
 return true;
}

2).提升触摸响应优先级为-128

void CTeachLayer::registerWithTouchDispatcher()
{
//使用-128和CCMenu优先级相同,并且吞掉事件true//
CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, -128, true);
CCLayer::registerWithTouchDispatcher();
}

3).在ccTouchBegan判断触点

bool CTeachLayer::ccTouchBegan( CCTouch* pTouch, CCEvent* pEvent )
{
    //得到触摸位置
 CCPoint touchPoint = pTouch->getLocation();
    //声明一个右下角100x50的矩形
 CCRect m_obRect=CCRectMake(
 CCDirector::sharedDirector()->getVisibleSize().width-100,
 CCDirector::sharedDirector()->getVisibleSize().height-50,
 100,
 50);
    //判断点是否在矩形中
 if (m_obRect.containsPoint(touchPoint))
 {
 return false;
 }
 return true;
}

大功告成,快去试一下吧!

2.精确命中

手机上和电脑上的触摸事件的区别在于:电脑上我们是用鼠标点击,而手机上使用手指去摁,触摸的精度的高低不言而喻!让我们来看下面这张图片:

20151224161739882.png (300×187)

让我们看右上角的X号按钮,在手机上点击它来说应该是很困难的!他的真实尺寸应该是红色矩形的区域(假设:50x50),为了让玩家在引导时,能够很方便的点击到它,我们将实际的可触摸区域设置为蓝色区域(假设:100x100),这样应该很好点到了吧!

这样会有一个新的问题,如果点击到红色和蓝色之间的区域,下面的x按钮时响应不到的,那么怎么办呢?我们需要修改touch的数据(设置为按钮的正中心),然后touch事件将会以新的数据向下传递!这样下面的按钮就能响应到了!

让我们看看代码吧:

bool CTeachLayer::ccTouchBegan( CCTouch* pTouch, CCEvent* pEvent )
{
 CCPoint touchPoint = pTouch->getLocation();

 if (!CGlobal::s_bTeach)
 {
 return false;
 }
    //假设按钮在(300,200)的位置,那么蓝色矩形如下:
 CCRect m_obRect=CCRectMake(
 250,
 150,
 100,
 100);

 if (m_obRect.containsPoint(touchPoint))
 {
        //得到蓝色矩形的中心点(300,200)
 CCPoint pos=ccp(m_obRect.getMidX(),m_obRect.getMidY());
        //这里要转化为UI坐标系(左上角为0,0点)
 pos=CCDirector::sharedDirector()->convertToUI(pos);
        //设置触摸信息
 pTouch->setTouchInfo(pTouch->getID(),pos.x,pos.y);
 return false;
 }

 return true;
}

三.逻辑处理及代码组织

这里我大概说下新手引导的架构,代码肯定贴不出来,太多太乱,说的不对的地方,欢迎大家拍砖吐槽!>_<

1.首先创建了一个CTeachLayer继承自CCLayer,添加到游戏的最上层(UI层之上),记住,要先添加游戏的其层,最后添加CTeachLayer,可以保存全局指针!

2.用一个枚举记下你要引导的所有步骤,在根据枚举值去设置高亮的位置及触摸区域!可以记下当前引导的进度,以方便下次继续引导!

3.游戏逻辑中免不了要判断引导(例:出第3波怪的时候引导玩家使用清屏道具),用全局的指针去设置引导的步骤!

4.引导完成后移除CTeachLayer,游戏开始!

相关文章

  • C++ protobuf中对不同消息内容进行赋值的方式总结(set_、set_allocated_、mutable_、add_)

    C++ protobuf中对不同消息内容进行赋值的方式总结(set_、set_allocated_、mutable_、

    这篇文章主要给大家介绍了关于C++ protobuf中对不同消息内容进行赋值的方式总结,主要使用的是set_、set_allocated_、mutable_、add_,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-03-03
  • C++详细讲解对象的构造

    C++详细讲解对象的构造

    当在参数化构造函数中声明对象时,必须将初始值作为参数传递给构造函数。对象声明的常规方法可能不起作用。构造函数可以显式或隐式调用,让我们一起了解对象的构造
    2022-04-04
  • 详解C++泛型装饰器

    详解C++泛型装饰器

    这篇文章主要为大家介绍了C++的泛型装饰器,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2021-11-11
  • C++超详细讲解析构函数

    C++超详细讲解析构函数

    既然在创建对象时有构造函数(给成员初始化),那么在销毁对象时应该还有一个清除成员变量数据的操作咯,析构函数与构造函数功能相反,析构函数不是完成对象的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成类的一些资源清理工作
    2022-06-06
  • C++可变参数的函数与模板实例分析

    C++可变参数的函数与模板实例分析

    这篇文章主要介绍了C++可变参数的函数与模板,非常重要的概念,需要的朋友可以参考下
    2014-08-08
  • C语言的变量与常量 字符字符串与转义字符详解

    C语言的变量与常量 字符字符串与转义字符详解

    这篇文章主要介绍了详解C语言的变量与常量 字符字符串与转义字符,包括其之间的区别是C语言入门学习中的基础知识,需要的朋友可以参考下
    2021-10-10
  • C语言新手初阶教程之三子棋实现

    C语言新手初阶教程之三子棋实现

    相信大家在小时候都用纸和笔与小伙伴们玩过一个经典的游戏之井字棋,即三子棋,下面这篇文章主要给大家介绍了关于C语言新手初阶教程之三子棋实现的相关资料,需要的朋友可以参考下
    2022-01-01
  • .h和.cpp文件的区别(zt)详细介绍

    .h和.cpp文件的区别(zt)详细介绍

    特别是对源文件和头文件的概念,需要深入对它了解,本文将详细介绍,需要了解的朋友可以参考下
    2012-11-11
  • 对C++默认构造函数的一点重要说明

    对C++默认构造函数的一点重要说明

    下面小编就为大家带来一篇对C++默认构造函数的一点重要说明。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-12-12
  • C语言中const和指针的秘密你知道吗

    C语言中const和指针的秘密你知道吗

    这篇文章主要为大家详细介绍了C语言中const和指针的秘密,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-02-02

最新评论