切換髮射使用TileMap製作遊戲,在cocos2d-x中使用(三)

weixin_34162629發表於2013-05-04

查了好多資料,發現還是不全,乾脆自己整理吧,至少保證在我的做法正確的,以免誤導讀者,也是給自己做個記錄吧!

    

本篇部落格出自阿修羅道,轉載請註明出處:http://blog.csdn.net/fansongy/article/details/8881664

    遊戲麼,得有勝負、朋友。

    地圖編輯的一些方法,傳送門:http://www.cnblogs.com/andyque/archive/2011/05/07/2039481.html

    上面入加朋友:

void HelloWorld::addEnemy(int x,int y)
{
	CCSprite* enemy = CCSprite::create("enemy1.png");
	enemy->setPosition(ccp(x,y));
	addChild(enemy);
	//moveEnemy(enemy);
	m_enemies->addObject(enemy);
}

    接下來使朋友動移,這裡跟官方的不太一樣。我用採的是在螢幕上表現的怪能動移。

    做出來的有點小問題:isRunning數函乎似有問題,不能用。嫌費事自己沒寫類。

    所以有個小Bug,有興致的讀者可以改改,自己寫個子類,然後設定個動沒動的標記。

void HelloWorld::moveEnemy(CCSprite* enemy)
{ 
	CCPoint diff = ccpSub(m_player->getPosition(),enemy->getPosition());
	float angleRadians = atanf((float)diff.y / (float)diff.x);
	float angleDegrees = CC_RADIANS_TO_DEGREES(angleRadians);
	float cocosAngle =-1* angleDegrees;
	if (diff.x <0) {
		cocosAngle +=180;
	}
	enemy->setRotation(cocosAngle);	

	int x = m_player->getPosition().x;
	int y = m_player->getPosition().y;
	CCActionInterval* move = CCMoveBy::create(3.0f, ccpSub(m_player->getPosition(),enemy->getPosition()));
	enemy->runAction(CCSequence::create(move,
		CCCallFuncN::create(this,callfuncN_selector(HelloWorld::enemyMoveFinished)),NULL));
}

    

    環循的調回是要必的,因為玩家的置位會改更,目標標坐會變改。

//此處如此計劃因為玩家置位會發生變化,須要復重獲得
void HelloWorld::enemyMoveFinished(CCNode* node)
{
	CCSprite* enemy = (CCSprite*)node;
	moveEnemy(enemy);
}
void HelloWorld::checkMoveEnemy(CCPoint center)
{
	CCSize winSize = CCDirector::sharedDirector()->getWinSize();
	center = convertToNodeSpace(center);
	CCRect screen = CCRectMake(center.x-winSize.width/2,center.y-winSize.height/2,winSize.width,winSize.height);
	CCObject* e = NULL;
	CCARRAY_FOREACH(m_enemies,e)
	{
		CCSprite* enemy =  dynamic_cast<CCSprite*>(e);
		CCPoint temp = enemy->getPosition();
		CCPoint pos = convertToNodeSpace(temp);  

		if(screen.containsPoint(pos))
		{
			//此處會有復重呼叫的問題,即對已動移的怪呼叫runAction
			//if(enemy->isRunning()) //這個數函不能用?
			moveEnemy(enemy);
		}
	}
}

    有怪了就得打,接下來是發射飛鏢。

    因為是觸控,沒法用鍵盤那麼高階,這裡用採切換模式的方法,即動移和發射飛鏢兩種模式切換。

    切換的表現要用CCMenuItemToggle來做,把它放在CCMenu中,再放在ScoreLayer中。

    發射飛鏢就用之前那個最易簡的忍者遊戲的程式碼就行。

void HelloWorld::sendProjectile(CCSprite* projectile,CCPoint pos)
{

	int realX;

	CCPoint diff = ccpSub(pos, m_player->getPosition());
	if (diff.x >0)
	{
		realX = (m_tileMap->getContentSize().width) +
			(projectile->getContentSize().width/2);
	} 
	else {
		realX =-(m_tileMap->getContentSize().width) -
			(projectile->getContentSize().width/2);
	}
	float ratio = (float) diff.y / (float) diff.x;
	int realY = ((realX - projectile->getPositionX()) * ratio) + projectile->getPositionY();
	CCPoint realDest = ccp(realX, realY);

	// Determine the length of how far we're shooting
	int offRealX = realX - projectile->getPositionX();
	int offRealY = realY - projectile->getPositionY();
	float length = sqrtf((offRealX*offRealX) + (offRealY*offRealY));
	float velocity =480/1; // 480pixels/1sec
	float realMoveDuration = length/velocity;

	CCActionInterval* throwProjectile = CCMoveTo::create(realMoveDuration,realDest);
	projectile->runAction(CCSequence::create(throwProjectile,
		CCCallFuncN::create(this,callfuncN_selector(HelloWorld::projectileMoveFinished)),NULL));

}
    每日一道理
自己把自己說服了,是一種理智的勝利;自己被自己感動了,是一種心靈的昇華;自己把自己征服了,是一種人生的成功。

    

void HelloWorld::projectileMoveFinished(CCNode* object)
{
	CCSprite* p = (CCSprite* )object;
	if(p)
	{
		removeChild(p,true);
		m_projectiles->removeObject(p);
	}
}

    碰撞檢測也一樣,查檢飛鏢與朋友否是相遇,另外要入加朋友與玩家相遇的邏輯。

void HelloWorld::checkHit(float dt)
{
	CCArray* projectilesToDelete = new CCArray;
	CCArray* targetToDelete = new CCArray;
	CCObject* it = NULL;
	CCObject* jt = NULL;
	CCRect playerRect = CCRectMake(
				m_player->getPositionX() - m_player->getContentSize().width/2,
				m_player->getPositionY() - m_player->getContentSize().height/2,
				m_player->getContentSize().width,
				m_player->getContentSize().height);

	CCARRAY_FOREACH(m_projectiles,it)
	{
		CCSprite * projectile = dynamic_cast<CCSprite*>(it);
		CCRect projectileRect = CCRectMake(
			projectile->getPositionX() - projectile->getContentSize().width/2,
			projectile->getPositionY() - projectile->getContentSize().height/2,
			projectile->getContentSize().width,
			projectile->getContentSize().height);
		CCARRAY_FOREACH(m_enemies,jt)
		{
			CCSprite* target = dynamic_cast<CCSprite*>(jt);
			CCRect targetRect = CCRectMake(
				target->getPositionX() - target->getContentSize().width/2,
				target->getPositionY() - target->getContentSize().height/2,
				target->getContentSize().width,
				target->getContentSize().height);
			if(projectileRect.intersectsRect(targetRect))
			{
				targetToDelete->addObject(target);
			}
			
		}
		CCARRAY_FOREACH(targetToDelete,jt)
		{
			CCSprite* delTarget = dynamic_cast<CCSprite*>(jt);
			m_enemies->removeObject(delTarget,true);
			this->removeChild(delTarget,true);
		}
		if(targetToDelete->count() >0)
		{
			projectilesToDelete->addObject(projectile);
		}
		targetToDelete->removeAllObjects();
	}
	CCARRAY_FOREACH(projectilesToDelete,it)
	{
		CCSprite* delProject = dynamic_cast<CCSprite*>(it);
		m_projectiles->removeObject(delProject);
		this->removeChild(delProject,true);
	}
	CCARRAY_FOREACH(m_enemies,jt)
	{
		CCSprite* target = dynamic_cast<CCSprite*>(jt);
		CCRect targetRect = CCRectMake(
				target->getPositionX() - target->getContentSize().width/2,
				target->getPositionY() - target->getContentSize().height/2,
				target->getContentSize().width,
				target->getContentSize().height);

		if(playerRect.intersectsRect(targetRect))
		{
			GameOverSecne *gameOverScene = GameOverSecne::create();
			gameOverScene->getLayer()->getLabel()->setString("You Lose!");
			CCDirector::sharedDirector()->replaceScene(gameOverScene);
		}
	}
	targetToDelete->release();
	projectilesToDelete->release();
}

    最後加上勝負介面:吃掉西瓜就贏,遇到怪物就輸。

    用的之前易簡忍者遊戲的那個GameOverScene。體具可以看我的碼源。

    編譯執行吧,少年。

    我覺感我這版遊戲,關卡計劃還是有點難的,打了半天才贏...

    

    等過CSDN稽核,上碼源:

    

    

    

文章結束給大家分享下程式設計師的一些笑話語錄: 看到有人回帖“不頂不是中國人”,他的本意是想讓帖子沉了。

相關文章