0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

cocos2d-HTML5で、LabelTTFを各文字バラバラに扱う

Posted at

cocos2d-x、スーツ仕事の隙間で遊んでいるだけだし、なんだかんだ疑問が生じてライブラリソースの中を読んじゃうので、なかなか進まない。で、今回はLabelの話。

なお、バージョンは cocos2d-x v3.17.2。

LabelTTF

LabelTTFって便利だけど、1文字ずつバラバラに扱いたいケースって結構ある気がする。ググったら、全部まとめてsetOpacity(0)にして、1文字ずつ透明度をいじくる方法が出てきた。それでもまあ良いけど、いずれ不満になるよね。だって、1文字ずつ現れる瞬間にすすすっとY軸方向にちょっぴり動きながら表示されるとか、昔のエロゲなんかでも割とあった気がするし、せっかくゲームエンジンを使っているんだから、その辺凝れるようにしておきたい。お遊びとしては、ちょっくら Quizlet みたいなのを作ってみようかと思っているので、そういうのがあると、問題文を見たときに目が滑らなくて済むからいいな、と思っているのです。エロゲのシステムじゃなくてごめん。

で、公式のhelloworldを弄ってみる。試しに、

        /////////////////////////////
        // 3. add your codes below...
        // add a label shows "Hello World"
        // create and initialize a label
        var helloLabel;
        var text = "bunbuku chagama この道はいつか来た道…… Hello World";
        helloLabel = new cc.LabelTTF(text, "Arial", 38);
        helloLabel.x = size.width / 2;
        helloLabel.y = size.height / 2 + 200;
        var fullsize = helloLabel.getContentSize().width;
        this.addChild(helloLabel, 5);
        cc.log("fullsize: "+fullsize);

        var sumsize = 0;
        for(var i in text){
            helloLabel = new cc.LabelTTF(text[i], "Arial", 38);
            var chsize = helloLabel.getContentSize().width;
            helloLabel.x = size.width / 2 - fullsize / 2 + sumsize + chsize / 2;
            helloLabel.y = size.height / 2 + 280;
            sumsize += chsize;
            this.addChild(helloLabel, 5);
        }
        cc.log("sumsize: "+sumsize);

とやったら、見事にズレました。 cc.LabelTTF.getContentSize().width を足していくんじゃあ駄目みたい。表示結果を見てみると、カーニングが反映されてない。カーニングの仕組みを考えれば、そりゃそうだ。でも、やーん、ということで、ライブラリ内の CCLabelTTF.js をざっくり読んで「ずる」しないと無理だって判りました。 cc.LabelTTF._renderCmd._measure(str) で、実際上の文字送り幅がわかります。プライベート前提のメソッドを呼ぶのは嫌ですが、「別途隠しcanvasを作って測定するコードを書き起こす」のはもっと嫌です。だって、そんなことを始めたら、フォント指定文字列の解釈とかも含めて、ごっそり書き増しだよ。楽して遊ぼうと思ってCocos2d-xを使っているのに、それはない。

この cc.LabelTTF._renderCmd._measure(str) は、とても有用なので、ちゃんと公開メソッドにして欲しいもんです。誰かよさげな命名のメソッドでラップしてプルリクしてあげて。

ちなみに、LabelBMFontなら、自前で明示的にカーニング情報をセットするから好きなように扱えるけど、日本語で好き放題メッセージを出したいので、LabelBMFontを使おうとすると、なんか大掛かりなスプライトパッケージングツールを書かなきゃいけない羽目になる確信。それもない。

これでうまくいく

というわけで、修正したコードが下記になる。試すときには、公式サンプルに埋め込んでね。

        /////////////////////////////
        // 3. add your codes below...
        // add a label shows "Hello World"
        // create and initialize a label
        var helloLabel;
        var text = "bunbuku chagama この道はいつか来た道…… Hello World";
        helloLabel = new cc.LabelTTF(text, "Arial", 38);
        helloLabel.x = size.width / 2;
        helloLabel.y = size.height / 2 + 200;
        var fullsize = helloLabel.getContentSize().width;
        this.addChild(helloLabel, 5);
        cc.log("fullsize: "+fullsize);

        var sumsize = 0;
        for(var i in text){
            helloLabel = new cc.LabelTTF(text[i], "Arial", 38);
            var chsize = helloLabel.getContentSize().width;
            helloLabel.x = size.width / 2 - fullsize / 2 + sumsize + chsize / 2;
            helloLabel.y = size.height / 2 + 280;
            sumsize += helloLabel._renderCmd._measure(text[i]);
            this.addChild(helloLabel, 5);
        }
        cc.log("sumsize: "+sumsize);

以上。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?