在第一篇《 如何制作一个简单的游戏》基础上,增加旋转炮塔功能

步骤如下:
1.使用上一篇的工程;
2.下载本游戏所需的资源,将资源放置" Resources"目录下:
如何制作一个简单的游戏(2) Cocos2d-x 2.0.4_cocos2d-x
删除旧的资源 player.png和 projectile.png;
3.在 HelloWorldScene.cpp文件, init函数,修改创建玩家精灵:
1
 
CCSprite *player = CCSprite::create( "player2.png");
ccTouchesEnded函数,修改创建子弹精灵:
1
 
CCSprite *projectile = CCSprite::create( "projectile2.png");
4.编译运行,可以看到炮塔发射出了子弹,但是有一点奇怪,射击的时候,炮塔并没有朝向那个方向,如下图所示:
如何制作一个简单的游戏(2) Cocos2d-x 2.0.4_iphone_02
5.接下去,就是让炮塔可以旋转射击。在 HelloWorldScene.h文件中,添加如下代码:
1
 
cocos2d::CCSprite *_player;
修改 HelloWorldScene.cpp文件中的 init函数,如下:
1
2
3
 
_player = CCSprite::create( "player2.png");
_player->setPosition(ccp(_player->getContentSize().width /  2, winSize.height /  2));
this->addChild(_player); 
6.计算炮塔旋转的角度。看下面图:
如何制作一个简单的游戏(2) Cocos2d-x 2.0.4_Cocos2d-x_03
数学的知识就是,tan(angle) = 对边 / 邻边,利用反正切angle = arctan(对边 / 邻边),这时计算出的是弧度,用CC_RADIANS_TO_DEGREES宏转换成角度。另外在数学中,逆时针为正,在Cocos2D-x中,顺时针为正,就如下图所示:
如何制作一个简单的游戏(2) Cocos2d-x 2.0.4_iphone_04
需要将最后计算出的角度乘以-1。在 ccTouchesEnded函数里,添加如下代码在projectile精灵runAction之前:
1
2
3
4
 
float angleRadians = atanf(( float)offRealY / ( float)offRealX);
float angleDegrees = CC_RADIANS_TO_DEGREES(angleRadians);
float cocosAngle = - 1 * angleDegrees;
_player->setRotation(cocosAngle);
7.编译运行,这时就可以看到炮塔旋转射击了。如下图所示:
如何制作一个简单的游戏(2) Cocos2d-x 2.0.4_iphone_05
8.旋转再射击。炮塔的旋转是瞬间完成的,这不符合现实,需要让它有个动作移动炮塔的方向。在 HelloWorldScene.h文件中,添加如下声明:
1
 
cocos2d::CCSprite *_nextProjectile;
在构造函数里面,添加如下:
1
2
 
_player =  NULL;
_nextProjectile =  NULL;
修改 ccTouchesEnded函数,并且添加 finishShoot方法,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
 
void HelloWorld::ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent)
{
     if (_nextProjectile !=  NULL)
    {
         return;
    }
    

    CCTouch *touch = (CCTouch*)pTouches->anyObject();
    CCPoint location =  this->convertTouchToNodeSpace(touch);

    CCSize winSize = CCDirector::sharedDirector()->getWinSize();
    _nextProjectile = CCSprite::create( "projectile2.png");
    _nextProjectile->retain();
    _nextProjectile->setPosition(ccp( 20, winSize.height /  2));

    CCPoint offset = ccpSub(location, _nextProjectile->getPosition());

     if (offset.x <=  0)
    {
         return;
    }

     int realX = winSize.width + _nextProjectile->getContentSize().width /  2;
     float ratio = ( float)offset.y / ( float)offset.x;
     int realY = realX * ratio + _nextProjectile->getPosition().y;
    CCPoint realDest = ccp(realX, realY);

     int offRealX = realX - _nextProjectile->getPosition().x;
     int offRealY = realY - _nextProjectile->getPosition().y;
     float length = sqrtf(offRealX * offRealX + offRealY * offRealY);
     float velocity =  480 /  1;
     float realMoveDuration = length / velocity;

     float angleRadians = atanf(( float)offRealY / ( float)offRealX);
     float angleDegrees = CC_RADIANS_TO_DEGREES(angleRadians);
     float cocosAngle = - 1 * angleDegrees;
     float rotateDegreesPerSecond =  180 /  0. 5;
     float degreesDiff = _player->getRotation() - cocosAngle;
     float rotateDuration = fabs(degreesDiff / rotateDegreesPerSecond);
    _player->runAction(CCSequence::create(CCRotateTo::create(rotateDuration, cocosAngle),
        CCCallFunc::create( this, callfunc_selector(HelloWorld::finishShoot)),  NULL));

    _nextProjectile->runAction(CCSequence::create(CCMoveTo::create(realMoveDuration, realDest), 
        CCCallFuncN::create( this, callfuncN_selector(HelloWorld::spriteMoveFinished)),  NULL));

    _nextProjectile->setTag( 2);

    CocosDenshion::SimpleAudioEngine::sharedEngine()->playEffect( "pew-pew-lei.wav");
}

void HelloWorld::finishShoot()
{
     this->addChild(_nextProjectile);
    _projectiles->addObject(_nextProjectile);

    _nextProjectile->release();
    _nextProjectile =  NULL;
}
在函数开头检验_nextProjectile变量,如果非空表示炮塔正在旋转中。不把_nextProjectile立即加到场景中,等待旋转完毕再加入场景。炮塔旋转的速度,为半秒钟旋转半个圆,计算所旋转角度所需的时间。
9.编译运行,可以看到炮塔可以在旋转后进行射击了,如下图所示:
如何制作一个简单的游戏(2) Cocos2d-x 2.0.4_Cocos2d-x_06