いちおくまんえん

最近はcocos2d-xでゲームアプリ「いちおくまんえん」の制作がメインです。 あとアニメも少々・・

Tiledとcocos2d-xでマップを作る 表示順をいい感じにする

えー、大変苦戦しております(;´∀`)


当たり判定とかその辺はあちこち見てまわてったらある程度分かったので後回し中

このチュートリアルみたいにやればたぶん出来るよねーwww.raywenderlich.com


それで、今何をやってるかというと、表示の優先度決めをどうするかをごにゃごにゃやってます。


あれです。文章で説明出来る気がしない・・・。

f:id:ichiokumanyen:20150421232419j:plain

こう、今いる場所によってどっちが上に表示されるかを決めたいんです。

最初は机全部、椅子全部、とかでレイヤー分けてやってたんですが、
机と椅子の間、椅子と机の間にプレイヤー表示させる時に、全部まとめて表示順を切り替えるとおかしくなる事に気づいたΣ(゚д゚lll)

基本的に下にある方が表示優先度高い。同じタイル上に乗ってる時の表示順がタイルによって異なる。

これをどうにかする為には同じレイヤーに全部載せておいて、LocalZOderを適宜変えていくか、GlobalZOrderで管理するしかない。・・はず。


ただでさえタイル周りややこしいのに自分でGlobalZOrderをいい感じに制御出来る自信は全くない!


なので、LocalZOderで何とかする。



あれ( ゚д゚)そういやTestCppのTileMapになんかいい感じに表示順が変わるやつあったような!


あった。なんか2種類あるZorderのものとVertexZとかいうもの。

これでサクッと出来ちゃうんじゃね(・∀・)

しかし、甘かった。


Zorderのものは1ラインごとにレイヤー用意して、そのラインのY座標を超えてるかでプレイヤーレイヤーのZorderを切り替える方法。

VertexZの方はTiledのレイヤーにcc_vertexzというカスタムプロパティを用意して、移動せんでいいやつは適当なマイナス値(恐らくマップサイズのx * yした値以上?)をあてて、自動で変化してほしい方はautomaticを指定するという方法っぽい。

試してみた。


何か3D的な動きして気持ち悪い。
いや、意図してうまく作ればいい感じになるのかもしれない!

だが私の作りたいものは普通の二次元のものだ!

タイルマップのチラツキとかどうにかするのに何かDirectorで何とかTestを無効にしたらいいとかあった気がするので調べて既に適用済み。

cc.Director:getInstance():setDepthTest(false)

そしてついでにこちらのスライドにもあったprojectionの設定も適用してみる

www.slideshare.net

cc.Director:getInstance():setProjection(cc.DIRECTOR_PROJECTION2_D)

これで綺麗に二次元で表示されるようにはなったけどやはり、Z軸ポジションからの表示優先がうまく効かない(´・ω・`)

上の内容を一部だけ適用したり、いろいろ組み合わせ変えてやってみたけどダメだ・・。

ほんとに元からTMXLayerに存在してたタイルを動かすんじゃなく、後から関係ないSprite足して適用出来るんだろうか。


うーん。


CCFastTMXLayerの中身を見てみよう。

なるほど、分からん(^q^)

ついでにCCTMXLayerと何が違うのか見てみたら、draw周りの作りが根本的に違う様子。
普通の方はSpriteBatchNodeを継承してて、Fastの方はNodeを継承。
Fastの方は色々バッファを持っていて無駄な処理を極力排除してそうな感じ。
あと後からaddChildが普通に出来る点が優秀。

普通の方もaddChildくらい出来るだろうと思っていたら機能しないようにされててAssertで殺される('A`)

OpenGLとかなんのこっちゃな私にはどっちも肝心の描画周りで何しているのかさっぱりである!


とりあえず早い方を使いたいし、3次元とか興味ないのでZ軸とか使わない、LocalZorderいじくる方法でいく!

これなら何とかなる!と思ったけどそう簡単にはいかなかった。

やはり同じテクスチャじゃない画像を間に挟むとうまくいかないのかなー。
サンプル通りにタイルを取得して動かす方法はもちろんうまくいく。


・・・ん?

なんかgetTileAtで取得したタイルだけ何かZorder合ってなくね?(;・∀・)
一番上にきてるような・・・。

うん、一番上に乗っかっている。

もしかして?と、このタイルにプレイヤーのSprite重ねてみる。

あれ?うまくいく(;・∀・)


なんでか分からないけど正しいorderで表示されるようになった。

なら!!と全部触ってみる。

for x=0, 49, 1 do
    for y=0, 49, 1 do
        local tile = autoOrderlayer:getTileAt( cc.p(x,y) )
        if tile then
            print(string.format("tile exists. x: %d, y: %d, tag: %d", x, y, tile:getTag()))
            print(string.format("localZ: %d", tile:getLocalZOrder()))
            -- 特殊設定したいタイルのorderをいじくってみるテスト
            -- プレイヤーと同じタイル上にいる時は1段分オーダーを増やしてる
            if y == 11 or y==17 or (y == 13 and x ~= 12) then
                tile:setLocalZOrder(tile:getLocalZOrder() + 50)
            end
        end
    end
end

うん、luaの制御構文まじ分かんない(^q^)

新しいSpriteとして用意されて性能がた落ちになるのではと懸念があったけど、
見た感じGL callの数とかに変化な・・・。あれ?減ってる。良くなってる?(;・∀・)

なら結果オーライということで!

一応こんな感じです。


あ、Windowsのキャプチャソフトいいのあったら教えて下さい(o・ω・o)

今回は何も検討せず検索して一番上に出てきた、BandicamとかいうGOMPlayerと同じとこ?のソフト使いました。

普通に音も取れるし、マウスの動きとクリックイベントも分かりやすく表示出来るので、何となく使う分にはいい感じです。

やっぱり動画は分かりやすくていいですね。積極的につかってこー。



一応プレイヤーの方の表示順切り替えてる部分のソース

local function onTouchMoved(touch, event)
    local diff = touch:getDelta()
    local node = layer:getChildByTag(kTagMoveChara)
    local currentPosX, currentPosY= node:getPosition()
    print(string.format("x: %d, y: %d ", currentPosX, currentPosY))
    node:setPosition(cc.p(currentPosX + diff.x/2, currentPosY + diff.y/2))
    local p = CC_POINT_POINTS_TO_PIXELS(cc.p(node:getPosition()))
    local newZ = (16*50-p.y)/16*50+p.x/16+50
    print(string.format("newZ: %d", newZ))
    node:setLocalZOrder( newZ )
end

テスト用なのであれなコードですが!
テスト用じゃなくてもきっとあれなコード書いてますが( ゚д゚ )クワッ!!