步骤如下:
1.使用上一篇的工程;
2.下载本游戏所需的资源,将资源放置"Resources"目录下:
删除旧的资源player.png和projectile.png;
3.在HelloWorldScene.cpp文件,init函数,修改创建玩家精灵:
_player = Sprite::create("player2.png");
在
onTouchesEnded
函数,修改创建子弹精灵:
Sprite* projectile = Sprite::create("projectile2.png");
4.编译运行,可以看到炮塔发射出了子弹,但是有一点奇怪,射击的时候,炮塔并没有朝向那个方向,如下图所示:
5.计算炮塔旋转的角度。看下面图:
数学的知识就是,tan(angle) = 对边 / 邻边,利用反正切angle = arctan(对边 / 邻边),这时计算出的是弧度,用CC_RADIANS_TO_DEGREES宏转换成角度。另外在数学中,逆时针为正,在Cocos2D-x中,顺时针为正,就如下图所示:
需要将最后计算出的角度乘以-1。在onTouchesEnded函数里,添加如下代码在projectile精灵runAction之前:
float angleRadians = atanf((float)offRealY / (float)offRealX);float angleDegrees = CC_RADIANS_TO_DEGREES(angleRadians);float cocosAngle = -1 * angleDegrees;_player->setRotation(cocosAngle);
7.编译运行,这时就可以看到炮塔旋转射击了。如下图所示:
8.旋转再射击。炮塔的旋转是瞬间完成的,这不符合现实,需要让它有个动作移动炮塔的方向。在HelloWorldScene.h文件中,添加如下声明:
Sprite* _nextProjectile;
在构造函数里面,添加如下:
_player = NULL;_nextProjectile = NULL;
修改
onTouchesEnded
函数,并且添加finishShoot方法,代码如下:
void HelloWorld::onTouchesEnded(const std::vector<Touch *> &touches, cocos2d::Event *event)
{if (_nextProjectile != NULL) {return;}Touch* touch = touches.front();Point location = this->convertTouchToNodeSpace(touch);Size winSize = Director::getInstance()->getWinSize();_nextProjectile = Sprite::create("projectile2.png");_nextProjectile->retain();_nextProjectile->setScale(2);_nextProjectile->setPosition(Point(20, winSize.height / 2));Point 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;Point realDest = Point(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);RotateTo* rotate = RotateTo::create(rotateDuration, cocosAngle);CallFunc* callFc = CallFunc::create(std::bind(&HelloWorld::finishShoot, this));_player->runAction(Sequence::create(rotate,callFc, NULL));_nextProjectile->runAction(Sequence::create(MoveTo::create(realMoveDuration, realDest),CallFuncN::create(std::bind(&HelloWorld::spriteMoveFinished, this,_nextProjectile)), NULL));_nextProjectile->setTag(2);}void HelloWorld::finishShoot()
{this->addChild(_nextProjectile);_projectiles->addObject(_nextProjectile);_nextProjectile->release();_nextProjectile = NULL;
}
在函数开头检验_nextProjectile变量,如果非空表示炮塔正在旋转中。不把_nextProjectile立即加到场景中,等待旋转完毕再加入场景。炮塔旋转的速度,为半秒钟旋转半个圆,计算所旋转角度所需的时间。
9.编译运行,可以看到炮塔可以在旋转后进行射击了,如下图所示:
参考资料:
1.How To Make A Simple iPhone Game with Cocos2D 2.X Part 2
http://www.raywenderlich.com/25791/rotating-turrets-how-to-make-a-simple-iphone-game-with-cocos2d-2-x-part-2
2.(译)如何使用cocos2d开发一个简单的iphone游戏:旋转炮塔。(第二部分)
http://www.cnblogs.com/zilongshanren/archive/2011/03/28/1997820.html
非常感谢以上资料,本例子源代码附加资源
下载地址
:
http://pan.baidu.com/s/16Bp7h
如文章存在错误之处,欢迎指出,以便改正。欢迎大家留言讨论技术!