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);
以上。