5.3 在Cocos2d-x中实现动作的监听
在上一节中,已经实现了使用Cocos2d-x实现动作组合的功能,相信读者也已经可以通过组合完成一些比较复杂的动作了。但是在实际使用Cocos2d-x时,还会经常需要改变动作的状态以达到某些连贯性的操作,比如英雄先向前冲刺,然后翻一个跟头,这就需要使用连续性的组合运动。那么本节将学习在Cocos2d-x中连续运行不同动作的功能,其核心代码如范例5-3所示,完整项目需查看源文件中的ChapterFive03项目进行参考。
【范例5-3】连续执行不同的动作。
01 bool HelloWorld::init() 02 { 03 if ( !Layer::init() ) 04 { 05 return false; 06 } 07 //设置背景颜色为白色,并加入到场景中 08 auto* background = LayerColor::create(ccc4(255, 255, 255, 255)); 09 addChild(background); 10 //将两张卡片插入到场景中去,其中一张卡片使其旋转90度达到“看不见”的目的 11 myCard1 = Sprite::create("mycard01.png"); 12 myCard2 = Sprite::create("mycard02.png"); 13 myCard1->setPosition(360, 180); 14 myCard1->setScale(0.5f); 15 myCard1->setAnchorPoint(Vec2(0.5f, 0.5f)); 16 addChild(myCard1); 17 myCard2->setPosition(360, 180); 18 myCard2->setScale(0.5f); 19 myCard2->setAnchorPoint(Vec2(0.5f, 0.5f)); 20 myCard2->setRotation3D(Vec3(0, 82.5f, 0)); //实际效果为以y轴为轴心旋转90度 21 addChild(myCard2); 22 auto* rotateby = RotateBy::create(1.5f, Vec3(0, 82.5f, 0)); //实际动作为以y轴为轴心旋转90度 23 //创建动作监听 24 auto* callFunc = CallFunc::create(CC_CALLBACK_0(HelloWorld:: rotateCard, this)); 25 auto* sequence = Sequence::create(rotateby, callFunc,NULL); 26 myCard1->runAction(sequence); 27 return true; 28 } 29 void HelloWorld::rotateCard() //回调函数,内容为使第二张卡片以y轴为轴心旋转90度 30 { 31 auto* rotateby = RotateBy::create(1.5f, Vec3(0, 97.5f, 0)); 32 myCard2->runAction(rotateby); 33 }
运行程序之后可以看到,在初始状态下一张卡牌显示在场景中央,而当它转动到90度时,将会显示出另一面的图案,如图5-6和图5-7所示。
图5-6 卡牌正面
图5-7 卡牌背面
实现这个效果的原理很简单,只需要在场景中插入两张尺寸、位置均相同的卡牌。其中第一张作为正面,直接放置在场景中,而第二张卡牌先旋转90度,因为这是2D游戏,卡牌是没有厚度的,因此在用户的角度看来第二张卡牌是看不见的。这一部分在范例中是由第11~21行处的代码实现的。
当动作开始时,首先让第一张卡牌执行动作翻转90度,如范例第26行所示。该动作在第22行被定义,虽然执行的是旋转90度,但是经过试验发现默认情况下由于渲染的原因,其旋转的前半个圆周(视觉效果上的)实际上是使用82.5作为参数。
在第24行中创建了一个动作触发器,实际上并没有监听的功能,而是在被执行时触发其中的rotateCard方法,如范例29~33行所示。创建动作触发器之后还要将它绑定在动作上,如第25行所示。实际上这并不能认为是一种绑定,而是将两个动作加入到了一个队列中,当执行完一个动作之后再执行下一个,只不过其中的动作是调用某个方法,看起来很像是事件监听而已。
提示:Sequence类的create方法中可以包含多个参数,即可以连续执行多个动作,只要最终以NULL作为最后一个参数结尾即可。
在本章最后所介绍的RPG回合制游戏的战斗场景中,也将会使用该方法来演示如何保证战斗的不断进行。