该文是接续cocos2d-x.org网站上的
Tutorials:How to make a cocos2d-x simple game。
基本照搬子山龙王翻译的文章
(译)如何使用cocos2d开发一个简单的iphone游戏:旋转炮塔。(第二部分),把其中Object-c代码修改为c++代码。
1.准备工作:
阅读cocos2d-x.org网站上的
Tutorials,生成的代码可在此
下载
接下来,下载新的 player sprite 和 projectile sprite图片,然后把它们加到工程Resource文件夹里面。
然后,修改代码,把每个sprite添加进去。
HelloWorldScene.cpp的init方法中:
CCSprite *player = CCSprite::spriteWithFile("Player2.png");
HelloWorldScene.cpp的ccTouchesEnded方法中:
CCSprite *projectile = CCSprite::spriteWithFile("Projectile2.png");
注意,这一次我们并没有指定精灵的宽度和高度,而是让cocos2d替我们来处理这些事情。
编译并运行你的工程,如果一切顺利的话,你将会看到一个炮塔正在发射子弹。然后,这并不是很好,因为炮塔在射击的时候并没有面朝那个方向。因此,接下来让我们来解决这个问题。
2.旋转并射击
在我们旋转炮塔之前,首先,我们需要保存Player精灵的引用,以便后面旋转它的时候使用。打开HelloWorldScene.h,然后修改类文件并包含以下成员变量:
CCSprite *_player;
然后修改init方法中的代码,把Player对象加入到层(layer)中。代码如下:
//the new add player code
_player = CCSprite::spriteWithFile("Player2.png");
_player->setPosition( ccp(_player->getContentSize().width/2, winSize.height/2) );
this->addChild(_player);
//注释掉原来的添加player代码
//CCSprite *player = CCSprite::spriteWithFile("Player2.png");
//player->setPosition( ccp(player->getContentSize().width/2, winSize.height/2) );
//this->addChild(player);
好了,现在让我们取出player对象的引用并且旋转它吧!为了旋转它,我们首先需要计算出旋转的角度。为了解决这个问题,想想我们在高中时候学过的三角代数吧。还记得sin cos tan吗?为了便于理解,下面使用一张图来解释一下:tan = 对面/邻边。
如上所示,我们想要旋转的角度是arctangent(angle),即对offY/offX求arctangent运算。
然而,这里还有两件事情,我们需要放在心上。首先,当我们计算actangent(offY/offX)的时候,这个结果是弧度,但是cocos2d使用的却是角度。还好,cocosd2d提供了一个非常方便的宏,可以使得角度和弧度之间方便转化。
第二点,我们假定上面的图中angle的偏转是正20度,但是,cocos2d里面顺时针方向为正(而不是上图所示的逆时针为正)。让我们看到下面这个图:
因此,为了得到正确的方向,我们把运算结果乘以一个-1就可以了。比如,如果我们把上面那幅图片里的角度乘以-1的话,我们就得够得到-20度,这个角度其实就是逆时针方向的20度。(感觉老外说话好啰嗦啊,聪明的读者恐怕早就明白了吧!:)
好了,讲得够多了!让我们来写一点代码吧。在ccTouchesEnded里面加入以下代码,添加位置在你的projectile->runAction之前。
//Determine angle to face
float angleRadians = atanf((float)offRealY/(float)offRealX);
float angleDegrees = CC_RADIANS_TO_DEGREES(angleRadians);
float cocosAngle =-1* angleDegrees;
_player->setRotation(cocosAngle);
编译并运行工程,现在我们的炮塔在射击的时候可以改变方向了。
3.旋转之后再射击
目前来说还不错,但是有一点点怪。因为,这个炮塔好像突然一下跳到一个方向射击,有点不够流畅。我们可以解决这个问题,但是在这之前,我们需要重构一下代码。
首先,打开HelloWorldScene.h,然后在你的类里添加如下成员变量:
CCSprite *_nextProjectile;
然后,修改你的ccTouchesEnded方法,并且添加一个新的方法,叫做finishShoot,如下所示:
if (_nextProjectile !=NULL){
return;
}
// Choose one of the touches to work with
CCTouch* touch = (CCTouch*)(touches->anyObject());
CCPoint location = touch->locationInView();
location = CCDirector::sharedDirector()->convertToGL(location);
if(location.x <= 20) return;
// Set up initial location of projectile
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
_nextProjectile = CCSprite::spriteWithFile("Projectile2.png");
_nextProjectile->retain();
_nextProjectile->setPosition(ccp(20,winSize.height/2));
// Determinie offset of location to projectile
int offX = location.x - _nextProjectile->getPosition().x;
int offY = location.y - _nextProjectile->getPosition().y;
// Bail out if we are shooting down or backwards
if(offX<0)
{
return;
}
// Ok to add now - we've double checked position
//this->addChild(_nextProjectile);
// Determine where we wish to shoot the projectile to
int realX = winSize.width + (_nextProjectile->getContentSize().width/2);
float ratio = (float)offY / (float)offX;
int realY = (realX * ratio) + _nextProjectile->getPosition().y;
CCPoint realDest = ccp(realX, realY);
// Determine the length of how far we're shooting
int offRealX = realX - _nextProjectile->getPosition().x;
int offRealY = realY - _nextProjectile->getPosition().y;
float length = sqrtf((offRealX * offRealX) + (offRealY*offRealY));
float velocity = 480/1; // 480pixels/1sec
float realMoveDuration = length/velocity;
//Determine angle to face
float angleRadians = atanf((float)offRealY/(float)offRealX);
float angleDegrees = CC_RADIANS_TO_DEGREES(angleRadians);
float cocosAngle =-1* angleDegrees;
float rotateSpeed =0.5/ M_PI; // Would take 0.5 seconds to rotate 0.5 radians, or half a circle
float rotateDuration = fabs(angleRadians * rotateSpeed);
_player->runAction(CCSequence::actions(CCRotateTo::actionWithDuration((ccTime)rotateDuration,cocosAngle),
CCCallFunc::actionWithTarget(this,callfunc_selector(HelloWorld::finishShoot)),
NULL
));
//_player->setRotation(cocosAngle);
_nextProjectile->runAction( CCSequence::actions(CCMoveTo::actionWithDuration(realMoveDuration, realDest),
CCCallFuncN::actionWithTarget(this, callfuncN_selector(HelloWorld::spriteMoveFinished)),
NULL) );
// Add to projectiles array
_nextProjectile->setTag(2);
//_projectiles->addObject(_nextProjectile);
void HelloWorld::finishShoot() {
// Ok to add now - we've finished rotation!
this->addChild(_nextProjectile);
_projectiles->addObject(_nextProjectile);
// Release
_nextProjectile->release();
_nextProjectile = NULL;
}
这看上去好像有许多代码,但是,实际上我们改动的并不多--大部分只是做一些小小的重构。下面是我们所修改的内容的一个列表:
1.在函数开头检查nextProjectile的值是否为nil。这意味着我们当前的touch事件正发生在射击过程之中。也就是说,炮塔已经发射出一个子弹了。
2.之前,我们使用一个projectile的局部变量,并把它加入到了当前的场景中。在这个版本中,我们增加了一个nextProjectile的成员变量,但是并没有马上加到当前场景中。因为后要还要使用。
3.定义炮塔旋转的角度,半秒钟旋转半个圆。记住,一个圆有2 PI个弧度。
4.计算旋转特定的角度需要多长时间,这里是拿弧度乘以速度。
5.接下来,我们使用一个sequence action来旋转我们的炮塔。最后,调用一个函数,把projectile加入到当前场景当中去。
好,大功告成!编译并运行工程,现在炮塔可以旋转,并且很流畅地射击了!
全部代码下载:
simpleGame2.zip
分享到:
相关推荐
如何制作一个简单的游戏 Cocos2d-x 2.0.4 本文实践自 Ray Wenderlich 的文章《How To Make A Simple iPhone Game with Cocos2D 2.X Tutorial》,文中使用Cocos2D,我在这里使用Cocos2D-x 2.0.4进行学习和移植 ...
在第一篇《如何制作一个简单的游戏》基础上,增加旋转炮塔功能,原文《How To Make A Simple iPhone Game with Cocos2D 2.X Part 2》,在这里继续以Cocos2d-x进行实现。有关源码、资源等在文章下面给出了地址。 ...
原文《How To Make A Simple iPhone Game with Cocos2D 2.X Part 3》,在这里继续以Cocos2d-x进行实现。有关源码、资源等在文章下面给出了地址。 http://blog.csdn.net/akof1314/article/details/8293383
Cocos2D-iPhone (Cocos2D-Swift) is a robust yet simple-touse 2D game framework for iPhone. If you are just starting with game programming, Cocos2D will enable you to make your first game in no time. ...
You’ll learn everything from importing 3D art assets into your iPhone game to using Cocos2d for iPhone and iPad. This book shares the secrets of the coolest iPhone apps being built today by the best...