文字の幅を自動計測

文字の幅を自動計測
ok-scratch

スクラッチに挑戦している皆さん、どうも!スクラッチコーチです。

Scratchには文字幅を取得するAPIがありません。スプライトを画面端に押し付け、1ピクセルずつ右に動かして端から離れた瞬間のX座標から幅を逆算するアルゴリズムを、カスタムブロックとリストで実装します。

さぁ、スクラッチでナニ作る!?

端タッチの消失点から文字幅を逆算する設計が光っている。文字幅を返すAPIがScratchに存在しないにもかかわらず、「端に触れた/触れていない」という二値のセンシングだけで定量的な幅の数値を得る発想が面白い。さらに計測時に2倍拡大して結果を÷2するという一工夫で、小数点以下の精度まで確保している。この仕組みをどう組み立てているのか、作り方を見ていこう。

動画で見てみよう

ok-scratch ok-scratch
チャンネル登録して応援よろしく!チャンネル登録する

チュートリアルの元になった作品

今回の目標

文字スプライトの全コスチューム(文字)の幅を「端に触れた」ブロックで自動計測し、■フォント半幅リストに格納するしくみを作ろう。

スターター作品をリミックスしよう

このチュートリアルにはスターター作品があります。使わなくても大丈夫だけど、最低限の素材などが用意されてるので便利です。
スターター作品をダウンロード

#1計測ブロックの準備

ok-scratch ok-scratch
文字スプライトで文章を組もうとすると、そのままでは文字同士が重なっちゃうし、「あ」「1」「ぁ」みたいに文字ごとに横幅もぜんぜん違う。そもそもScratchには「文字の幅を取る」APIが無いから、1文字ずつ手で測って並べるしかない――けど文字数が増えたら現実的じゃないよね。そこで「端に触れた」ブロックだけを使って、全文字の幅を自動計測するカスタムブロック「フォント幅を計測する」を自作していくよ。

準備

スプライト「テキスト」を開く

テキストテキスト
スプライトについて
文字コスチュームの幅を計測してFONT_HALVESリストに格納するスプライト。テキスト描画システムの土台となる。
どんな役割か
文字の幅を自動で計測するしくみを作るよ!各文字コスチュームを順番に表示して、何ピクセル幅かを調べてリストに記録していくよ。これがあとのテキスト描画に使われるんだ。

カスタム定義「フォント幅を計測する」を追加

ズーム倍率と補正値を受け取り、全コスチュームの幅を計測してFONT_HALVESリストに格納するプロシージャ

カスタム定義「フォント幅を計測する」を追加

リスト「■フォント半幅リスト」の追加

各文字コスチュームの計測済み幅(補正値込み)を格納するグローバルリスト。テキスト描画時の文字間隔計算に使用する。

リスト「■フォント半幅リスト」の追加

実装

step-0

まず見た目大きさを ( ) %にするでスプライトのサイズを「ズーム倍率」ぶん拡大して、「■フォント半幅リスト」をリスト( )のすべてを削除するで空にするよ。1pxきざみでしか動かせないから、元サイズのまま測ると丸め誤差が出ちゃうんだ。いったん拡大してから測って後で元に戻せば、サブピクセル単位の精度が確保できるってわけ。

そのあと見た目コスチュームを ( ) にするでコスチューム番号を「四捨五入(0)」に切り替える。Scratchではコスチューム0を指定するとなぜか最後のコスチュームにラップするという、ちょっと変な仕様があるんだ。これを逆手に取れば、次のステップで「次のコスチューム」を呼ぶだけで先頭からキレイに全コスチュームを走査できる仕掛けになる。

#2画面端にセット

ok-scratch ok-scratch
ここからがこの作品のキモ。文字の幅を、端っこへの接触だけで自動計測するアルゴリズムだよ。まず画面端にX座標をセットする。
step-1

#31pxずつ幅を測る

step-2

制御( ) 回繰り返すでコスチュームの数だけループして、毎回見た目次のコスチュームにするで次の文字に切り替えるよ。文字を切り替えたらx座標を-9999にして画面の左端に押し付けて、制御( ) まで繰り返すで「端に触れた」のではないまで1ピクセルずつ右に動かす。端から離れた瞬間のx座標に240を足せば、その文字の半分の幅がわかるんだ。

#4倍率を反映する

ok-scratch ok-scratch
計算した値を「ズーム倍率」で割って元のサイズに換算して、「補正値」を足してから「■フォント半幅リスト」に追加するよ。こうやって全文字ぶんの幅データがリストに溜まっていく。あとでテキストを並べるとき、このリストから文字ごとの間隔を取得できるわけだね。

準備

変数「文字幅」を追加

計測中の文字コスチュームの幅(ピクセル単位)

変数「文字幅」を追加

実装

step-3

ok-scratch ok-scratch
普通、各文字のピクセル幅を知りたかったら1文字ずつ手動で測ってリストに直打ちするしかないよね。でもフォントを変えるたびに全部やり直しだし、正直ガチで無理ゲー。この作品では「端に触れた」ブロックだけで全自動計測しちゃう。こういう「ないものは既存の部品で作る」発想の転換が、プログラミングの醍醐味だったりするんだ。

#5元の状態に戻す

ok-scratch ok-scratch
計測がぜんぶ終わったら、スプライトの状態を元に戻していくよ。コスチュームを1番に切り替えて、拡大していたサイズも「ズーム倍率」で割って元のスケールに戻す流れだね。
step-4

計測用に拡大していたから、終わったあとに戻さないとスプライトがデカいまま画面に居座っちゃうんだ。カスタムブロックの中で状態を変えたら、出る前に必ず戻す。これがプログラミングでいう「後片付け」ってやつだよ。

ok-scratch ok-scratch
この「使ったら元に戻す」って考え方、Scratchに限らずプログラミングのいろんな場面で登場するよ。たとえばゲームで一時的に無敵状態にしたあと、元に戻す処理を忘れたら永久に無敵のまま。ペンの色を変えて絵を描いたあと戻し忘れると、次の描画がおかしくなるのも同じパターンだね。たった2ブロックの処理だけど、この習慣があるかないかで複雑な作品を作ったときの安定感が変わってくるんだ。

#6旗クリックで実行

ok-scratch ok-scratch
カスタムブロックができたから、あとは旗クリックから呼び出すだけ。コスチュームを1番にしてサイズを150%にセットするよ。
step-5

そしてブロック定義( )で「フォント幅を計測する」を「ズーム倍率」2、「補正値」0で呼び出すんだ。拡大倍率が2だと、1pxループは整数のx座標でしか止まれなくても、元サイズに÷2で換算すれば0.5pxきざみの解像度で幅が決まる仕組みだね。旗を押すと「■フォント半幅リスト」に全文字の幅データが入るはず――確認してみよう!

確認プレビューしておこう 確認プレビューしておこう
旗を押すと全コスチュームの文字幅が自動計測されて、■フォント半幅リストに数値がずらっと入ったね。

まとめ

「端に触れた」の瞬間がそのまま文字の境界になるなんて、発想の転換だよね。APIが存在しないなら既存ブロックで代替する、このプログラマー的な問題解決が今回の醍醐味だ。次はこのデータを使って、文字をきれいに並べるテキスト描画システムを作っていこう!あ、ちなみにRPG風の会話ボックスを作るっていう連載チュートリアルがすでにあるから、気になる人は是非チェックしてくれぃ!

ブクマよろしくお願いします! ブクマよろしくお願いします!
どんどん追記・更新していくので、ブックマークやシェアよろしくお願いします!