[转注自官网]Cocos2d-x Tutorial 3 - 让精灵动起来(Glede Edition for 2.0.3)

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];
}

 

好那么完工了,生成一下,跑跑看,大师兄妖怪来了!

 

posted @ 2012-10-23 11:23  Shine Team  阅读(846)  评论(1编辑  收藏  举报