微信経典飛行機大戦の4:弾丸層の完全な解析


飛行機が弾丸を発射するには、弾丸層で以下のいくつかの態様を処理する必要がある.
1.弾丸のレンダリング効果
2.弾丸の初期位置と飛行効果
3.弾丸の管理と回収
4.弾丸層が提供する他のインタフェース
この節では,この4つの側面から弾丸層を完全に解析する.
1.弾丸のレンダリング効果
弾丸の追加とレンダリングは、ロットレンダリングが1回で完了するため、CCSpriteBatchNodeを採用しています.
bool BulletLayer::init()
{
	bool bRet=false;
	do
	{
		CC_BREAK_IF(!CCLayer::init());

		CCTexture2D* texture = CCTextureCache::sharedTextureCache()->textureForKey("ui/shoot.png");
		bulletBatchNode = CCSpriteBatchNode::createWithTexture(texture);
		this->addChild(bulletBatchNode);

		bRet=true;
	} while (0);
	return bRet;
}

void BulletLayer::AddBullet(float dt)
{
	CCSprite* bullet = CCSprite::createWithSpriteFrameName("bullet1.png");
	bulletBatchNode->addChild(bullet); //          bulletBatchNode 
        //this->addChild(bullet);             
}

そして呼び出し
this->schedule(schedule_selector(BulletLayer::AddBullet),0.01f); 

ここでは時間間隔を0.01秒に設定し,弾丸は柱状に見えるが,後で詳細に分析する.
2.弾丸の初期位置
弾丸の初期位置は飛行機のヘッド位置にあるが、飛行機はゲーム中にプレイヤーのタッチに伴って位置が変化するため、弾丸の初期位置は飛行機のリアルタイム位置を基準に追加すべきである.
	//       
	CCPoint planePosition = PlaneLayer::sharedPlane->getChildByTag(AIRPLANE)->getPosition();
	CCPoint bulletPosition = ccp(planePosition.x, planePosition.y + PlaneLayer::sharedPlane->getChildByTag(AIRPLANE)->getContentSize().height/2);
	bullet->setPosition(bulletPosition);

3.弾丸の飛行効果
弾丸の飛行効果は、X方向が変わらず、Y方向が移動することです.そして弾丸が発射されると、独立した個体であり、飛行機の移動に伴って移動することはできない.また,各弾丸の初期Yも必ずしも同じではないので,まず各弾丸の運動時間を算出しなければならない.
	float length=CCDirector::sharedDirector()->getWinSize().height+bullet->getContentSize().height/2-bulletPosition.y; //    ,       
	float velocity=320/1; //    :320pixel/sec
	float realMoveDuration=length/velocity; //    

	CCFiniteTimeAction* actionMove=CCMoveTo::create(realMoveDuration,ccp(bulletPosition.x,CCDirector::sharedDirector()->getWinSize().height+bullet->getContentSize().height/2));
	CCFiniteTimeAction* actionDone=CCCallFuncN::create(this,callfuncN_selector(BulletLayer::bulletMoveFinished)); //            

	CCSequence* sequence=CCSequence::create(actionMove,actionDone,NULL);
	bullet->runAction(sequence);

4.弾丸の管理と回収
cococos 2 d−xが提供する配列クラスCCArrayを用いて,作成したいくつかの精霊を管理した.また、必要でない場合は、そこから削除し、画面から削除することができます.
CCArray::create関数がautoReleaseを呼び出しているため、呼び出し作成後に手動でretainを行い、使用範囲を超えて解放されないようにしながら、構造関数でreleaseを行いメモリ漏洩を防止する必要があります.
(1)弾丸を管理するCCArrayメンバー変数ポインタの作成
	CCArray* m_pAllBullet;

(2)弾丸層の構造関数と析出関数
BulletLayer::BulletLayer(void)
{
	bulletBatchNode=NULL;
	m_pAllBullet=CCArray::create();
	m_pAllBullet->retain();
}

BulletLayer::~BulletLayer(void)
{
	m_pAllBullet->release();
	m_pAllBullet=NULL;
}

(3)弾丸の回収:弾丸がスクリーンを飛び出した後の呼び出し関数
void BulletLayer::bulletMoveFinished(CCNode* pSender)
{
	CCSprite* bullet=(CCSprite*)pSender;
	this->bulletBatchNode->removeChild(bullet,true); //    
	m_pAllBullet->removeObject(bullet); //  CCArray
	
}

5.弾丸層の他のインタフェース
(1)弾丸発射開始
//      
void BulletLayer::StartShoot(float delay)
{
	this->schedule(schedule_selector(BulletLayer::AddBullet),0.20f,kCCRepeatForever,delay);
}

(2)弾丸発射停止
//      
void BulletLayer::StopShoot()  //       
{
	this->unschedule(schedule_selector(BulletLayer::AddBullet));
}

(3)ある弾丸を削除する
//      
void BulletLayer::RemoveBullet(CCSprite* bullet) //         ,          
{
	if(bullet!=NULL)
	{
		this->bulletBatchNode->removeChild(bullet,true);
		this->m_pAllBullet->removeObject(bullet);
		
	}
}

弾丸層の解析が完了した後,GameLayer層のinit関数に弾丸層を加え,弾丸の発射開始を実行し,効果を見てみた.
		//  bulletLayer
		this->bulletLayer=BulletLayer::create();
		this->addChild(bulletLayer);
		this->bulletLayer->StartShoot();