読者です 読者をやめる 読者になる 読者になる

夏までにiPhone アプリつくってみっか!

趣味でiPhone/Androidアプリを開発し、日々勉強した事を書いています。オープンワールド系レースゲームをUnityで開発中です。

【偽スペースハリアー】CCRenderTextureで影の重なりが濃くなるのを防ぐ

cocos2d スペースハリアー TravelShooting JP

偽スペハリでドラゴンの影同士が重なり合うとその部分が濃くなるという問題がありましたので少し強引な方法で修正しました。
たぶんここに書いてある方法は他の条件だと上手く行かない場合があると思います。

まず、問題となっている現象はこれです。
f:id:takujidev:20131215092129p:plain
影が重なった部分の色が濃くなり、その部分が重なるとさらに濃くなってしまっています。

そして、修正した結果がこれです。
f:id:takujidev:20131215092150p:plain
影の部分は一定の濃さになっています。

cocos2dのCCRenderTextureという機能を使って全ての影を不透明の黒で画面いっぱいのサイズのレンダーテクスチャーに描き込み、レンダーテクスチャーのopacityを下げて表示するという方法を使ってみました。
このCCRenderTextureというのが少々厄介で、なぜか背景は透過するのに他のスプライトは透過しないという謎の動きを見せたので、vertexZを背景と他のスプライトの間に設定しています。
何れにしても影スプライトのvertexZは無視されてCCRenderTextureのvertexZの位置に影が描かれるので、置き場所は他のキャラクターと背景の間しかないですが。

CCRenderTextureに描き込むスプライトは自分の子ノードでなくてもいいのですが、今回のように影の描画に使う場合は子ノードにした方が良いでしょう。
そうしないと、本来の親ノードの描画とCCRenderTexureの描画で2回表示されてしまいます。
私はここでしばらく悩みました。

コードはこうなっています。

- (id)init
{
    CGSize winsize = [CCDirector sharedDirector].winSize;
    if ((self = [super initWithWidth:winsize.width height:winsize.height pixelFormat:kCCTexture2DPixelFormat_RGBA8888])) {
        self.position = ccp(winsize.width/2.0 ,winsize.height/2.0);
        self.vertexZ = -1000.0;
        self.sprite.opacity = 60;
        [self scheduleUpdate];
    }
    return self;
}


- (void)update:(ccTime)delta
{
    [self beginWithClear:0.0 g:0.0 b:0.0 a:0.0];
    
    for (CCSprite* node in self.children) {
        CGPoint position = node.position;
        position.x += self.contentSize.width/2.0; // (0, 0)は左下なので表示前にx座標を画面半分だけ補正する
        node.position = position;
        [node visit];
        position.x -= self.contentSize.width/2.0; // 補正した座標を元に戻す
        node.position = position;
    }
    
    [self end];
}

このゲームでは全てのオブジェクトの原点は画面中央下部に設定しており、影スプライトの座標もそれを想定した値になっています。
従いまして、
CCRenderTextureの子ノードの本来の原点はCCRenderTextureの左下となりますので、普通に表示すると画面サイズの半分左にずれて表示されてしまいます。
これを防ぐために子ノードを描き込む前に座標をオフセットし、書き込み後に戻すという操作をしています。

なお、CCRenderTextureを使用すると負荷が増大します。

影修正前の負荷
f:id:takujidev:20131215101301p:plain

影修正後の負荷
f:id:takujidev:20131215101335p:plain

とは言え、iPhone4Sではまだ余裕があります。