How to make a cocos2d-x simple game(第二部分)_C/C++_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > C/C++ > How to make a cocos2d-x simple game(第二部分)

How to make a cocos2d-x simple game(第二部分)

 2012/4/23 12:43:29  dongk  程序员俱乐部  我要评论(0)
  • 摘要:该文是接续cocos2d-x.org网站上的Tutorials:Howtomakeacocos2d-xsimplegame。基本照搬子山龙王翻译的文章(译)如何使用cocos2d开发一个简单的iphone游戏:旋转炮塔。(第二部分),把其中Object-c代码修改为c++代码。1.准备工作:阅读cocos2d-x.org网站上的Tutorials,生成的代码可在此下载接下来,下载新的playersprite和projectilesprite图片,然后把它们加到工程Resource文件夹里面
  • 标签:Make
该文是接续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
  • simpleGame.zip (171.9 KB)
  • 下载次数: 2
  • simpleGame2.zip (172.3 KB)
  • 下载次数: 0
发表评论
用户名: 匿名