Chapter3 – 让精灵动起来
在上一章中我们把主人公放到了场景中。但是只有他一个人显得很孤单,没有怪没有妖,我们给他造。
我们用一个void addTarget()函数来完成这项工作,怪物会以随机的宿舍从场景右侧进入从左侧飞出。
首先在HellowWroldScene.h中声明 void addTarget() 函数,然后在HelloWorldScene.cpp中加入源代码(别忘了在HelloWorldScene.cpp的开头使用USING_NS_CC;)
// cpp with cocos2d-x void HelloWorld::addTarget() { CCSprite *target = CCSprite::create("Target.png", CCRectMake(0,0,27,40) ); // 决定怪物出现的XY坐标 CCSize winSize = CCDirector::sharedDirector()->getWinSize(); int minY = target->getContentSize().height/2; int maxY = winSize.height - target->getContentSize().height/2; int rangeY = maxY - minY; // srand( TimGetTicks() ); int actualY = ( rand() % rangeY ) + minY; // 创建怪物的时候让它稍微出一些屏幕 // 怪物出现位置的Y坐标是随机的 target->setPosition( ccp(winSize.width + (target->getContentSize().width/2), actualY) ); this->addChild(target); // 通过设定怪物运动所需时间来决定他的速度 int minDuration = (int)2.0; int maxDuration = (int)4.0; int rangeDuration = maxDuration - minDuration; // srand( TimGetTicks() ); int actualDuration = ( rand() % rangeDuration ) + minDuration; // 创建action CCFiniteTimeAction* actionMove = CCMoveTo::create( (float)actualDuration, ccp(0 - target->getContentSize().width/2, actualY) ); CCFiniteTimeAction* actionMoveDone = CCCallFuncN::create( this, callfuncN_selector(HelloWorld::spriteMoveFinished)); target->runAction( CCSequence::create(actionMove, actionMoveDone, NULL) ); }
对应的objc代码
// objc with cocos2d-iphone -(void)addTarget { CCSprite *target = [CCSprite spriteWithFile:@"Target.png" rect:CGRectMake(0, 0, 27, 40)]; // Determine where to spawn the target along the Y axis CGSize winSize = [[CCDirector sharedDirector] winSize]; int minY = target.contentSize.height/2; int maxY = winSize.height - target.contentSize.height/2; int rangeY = maxY - minY; int actualY = (arc4random() % rangeY) + minY; // Create the target slightly off-screen along the right edge, // and along a random position along the Y axis as calculated target.position = ccp(winSize.width + (target.contentSize.width/2), actualY); [self addChild:target]; // Determine speed of the target int minDuration = 2.0; int maxDuration = 4.0; int rangeDuration = maxDuration - minDuration; int actualDuration = (arc4random() % rangeDuration) + minDuration; // Create the actions id actionMove = [CCMoveTo actionWithDuration:actualDuration position:ccp(-target.contentSize.width/2, actualY)]; id actionMoveDone = [CCCallFuncN actionWithTarget:self selector:@selector(spriteMoveFinished:)]; [target runAction:[CCSequence actions:actionMove, actionMoveDone, nil]]; }
在这里,我们设定的动作将actionMove和actionMoveDone串起来,使怪物结束运动之后会通过callfuncN_selector(HelloWorld::spriteMoveFinished) 会回调 HelloWorld::spriteMoveFinished() 方法,我们要在 HelloWorldScene.h声明它(记得CCNode的命名空间),也同样在HelloWorldScene.cpp里定义它,代码如下。
// cpp with cocos2d-x void HelloWorld::spriteMoveFinished(CCNode* sender) { CCSprite *sprite = (CCSprite *)sender; this->removeChild(sprite, true); }
objc代码
// objc with cocos2d-iphone -(void)spriteMoveFinished:(id)sender { CCSprite *sprite = (CCSprite *)sender; [self removeChild:sprite cleanup:YES]; }
TIPs:
1.关于 int rand() 随机函数,srand 和 rand都是c标准函数, 一招鲜吃遍天什么平台都能用。用系统毫秒时间作为种子就能得到一个不错的随机效果。
2.C++里是true和false,objc里有YES和NO。
3.我们知道C里有函数指针,但是C++你可以把一个类的静态成员函数用作函数指针传递,这没问题,但是非静态的成员函数做起来就比较麻烦了,objc里有@selector这个东西能够指定对象传递消息,为了能够继续保持这个习惯(事实上这很方便),cocos2d-x在C++里实现了类似的selector,可以参考他们的声明:cocos2dx\include\selector_protocol.h。一共有5种不同的回调类型:
- schedule_selector
- callfunc_selector
- callfuncN_selector
- callfuncND_selector
- menu_selector
根据定义去调用就可以了。比如对于函数
static CCCallFuncN * create(CCObject* pSelectorTarget, SEL_CallFuncN selector);
看到第二个参数是SEL_callFunN类型的回调函数,你就需要根据SEL_callFunN的定义:
typedef void (CCObject::*SEL_CallFuncN)(CCNode*);
去定义一个返回值是void,只有一个CCNode类型参数的函数(比如我们的HelloWorld::spriteMoveFinished),然后使用callFuncN_selector()宏,将函数名字括起来……像这样:
callFuncN_selector(HelloWorld::spriteMoveFinished)
这就是create第二个参数了!没跑。
言归正传我们继续造妖怪。然后我们要让妖怪隔几秒一段时间一只一只地进来,要在HelloWorld::init方法里添加如下代码:
// cpp with cocos2d-x // 每秒呼叫 HellowWorld::gameLogic 函数一次 this->schedule( schedule_selector(HelloWorld::gameLogic), 1.0 );
objc代码
// objc with cocos2d-iphone // Call game logic about every second [self schedule:@selector(gameLogic:) interval:1.0];
同样的我们要在HelloWorldScene.h声明一下gameLogic函数,要把它声明成public。然后在HelloWorldScene.cpp里实现如下:
// cpp with cocos2d-x void HelloWorld::gameLogic(float dt) { this->addTarget(); }
objc代码
// objc with cocos2d-iphone -(void)gameLogic:(float)dt { [self addTarget]; }
好那么完工了,生成一下,跑跑看,大师兄妖怪来了!