Siv3Dでグラデーション文字を作る
はじめに
この記事は Siv3D AdventCalendar 2017 13 日目の記事です。
前日の記事はmoonmileさんのLattePanda と Siv3D(仮)です。
みなさんはコンピューターゲームでのグラデーション文字を見たことはありますか?
影付き文字ではありません。文字そのものがグラデーションしてるものです。
RPGツクール2000や東方projectシリーズ*1などを始め様々なゲームで見ることが出来ます。
グラデーション文字は目がチカチカしない読みやすさを保ちつつ誰のセリフか視覚的に分かりやすいです。重要なセリフの色分けに使うのも効果的ですね。なにより単色のテキストよりオシャレ。
自分もグラデ文字使いたい!!でもどうやって作ればいいかわかんない!?
そんなあなたもこの記事を読んで今日から君もグラデーション文字デビューだ!!!
環境
Siv3DのバージョンはAugust 2016 v2版を使います。 Siv3Dの基本的な使い方については説明を省略しますので公式の豊富なリファレンスを読んで学んでいただけると幸いです。
目次
完成図
コード全文
# include <Siv3D.hpp> void Main() { const Font font(30); //Font作成 const String string(L"Siv3Dで\nグラデーション文字を作る\n"); //テキスト作成 Image image(font.region(string).size);//Image作成 font.overwrite(image, string, { 0,0 }, Palette::White); //ベース文字を書き込む for (int i = 0; i <= font.region(string).size.y / font.height; i++) //グラデーション書き込み { Image(Palette::Blue, L"Image/gradation.jpg") //グラデーション画像を透過画像に .scaled(font.region(string).size.x, font.height) //透過画像のサイズ調整 .write(image, Point(0, font.height*i)); //透過画像を書き込む } const Texture texture = Texture(image); //ImageからTextureを作成 while (System::Update()) { texture.draw(30, 80); //Textureを表示 } }
実行結果
Imageフォルダを作ってgradation.jpgさえ入れておけばコピペするだけで動きます。
こんな短いコードでグラデーション文字が実装出来ます。すごいですねSiv3D。
どういうコードになっているか今から一行一行解説していきます
解説
フォントと文章の用意
Font font(30); String string(L"Siv3D グラデーション文字");
好きなフォントと表示したい文章を用意します。フォントのサイズは30ぐらいにしときましょう。
Image型インスタンスの作成
Image image(font.region(string).size);
Image型でグラデーションを掛ける処理を行うので表示する文章の大きさに合わせたImageを用意します。
テキストを描く · Siv3D/Reference-JP Wiki · GitHub
font.region()はテキストが表示される領域(のサイズ)を調べる関数です詳しくは上のリンクから確認してください。
Imageに文章を書き込む
font.overwrite(image, string, { 0,0 }, Palette::White);
先程用意したImageに文章を書き込みます。overwriteではなくwriteにしてしまうと文字が見えなくなってしまうので気をつけましょう。*3
Palette::Whiteの部分が文字のベースの色になります。
文字とグラデーション用画像を合成
for (int i = 0; i <= font.region(string).size.y / font.height; i++) { Image(Palette::Blue, L"Image/gradation.jpg") .scaled(font.region(string).size.x, font.height) .write(image, Point(0, font.height*i)); }
今回の記事の肝となる部分です。
透過情報を持つ画像を作成する
Image(Palette::Blue, L"Image/gradation.jpg")
for文は飛ばしてここから。これはSiv3Dの公式サンプルにも乗ってる機能です。こちらから確認してみてください
画像編集 · Siv3D/Reference-JP Wiki · GitHub
// 第 2 引数の画像の r 成分を、新しく作る画像の a 成分とする
「rとかaとか何言ってるのか分かんねぇ…」自分も悩んだので解説します。 rとはRGBのR成分。つまり赤色成分です。256段階で大きいほど赤色が強くなります。 aとはalpha、透明度成分です。256段階の0なら完全に透明で255なら完全に不透明になります。
これをふまえるとこの関数は『第二引数の画像の赤い部分を赤い分だけ不透明にして第一引数の色で塗りつぶす』関数と説明できます。 ちなみにRGBのGとBはなにも使いません。この先では特に記載が無い場合この2つの成分は0とします。
ここの第一引数の色を自由に設定することで1つのgradation.jpgでありとあらゆる色のグラデーションが作れます。
気になるgradation.jpgはこちら。 赤い分だけ不透明な色に、黒い分だけ透明になると考えてもらって結構です。
グラデーション画像の調達
グラデーション画像を用意する方法はお絵かきソフトで作る、Siv3Dで作る等ありますが簡単に作れるサイトを1つご紹介します。 www.lancork.net 使用時のコツをいくつか
- 横サイズは1で大丈夫です。自分は管理のしやすさとサイズの差が微々たるものである点を考慮して横に長いものを使っています。
- 縦サイズは60あれば十分ですフォントサイズを100にしてもちっとも荒れません。
- この記事で使われているグラデーション画像は開始色#000000終了色#a40000です。好みに合わせて調整してみてください。
- GB成分である後ろ4桁は0000のままで構いません
グラデーション画像のサイズを文字に合わせる
.scaled(font.region(string).size.x, font.height)
グラデーション用画像の大きさを変えます。横幅はテキスト表示領域いっぱい、縦幅はフォントの高さを指定します。ちなみにフォントのサイズを30にするとフォントの高さは60になります。引き伸ばしたら汚くなると思われる方も居るかもしれませんが、グラデーション用画像がある程度大きければ縦に引き伸ばしてもきれいに写りますよ。横は言わずもがな。
文字と合成
.write(image, Point(0, font.height*i));
いよいよ合成です。文字がない部分は完全に透明なので合成した後は文字にだけ色がかかります。writeではなくoverwriteにしてしまうと一面のグラデーション画像で文字が見えなくなってしまうので気をつけましょう。上で青い透過画像にしたので文字は青のグラデーションがかかります。
for文について
for (int i = 0; i <= font.region(string).size.y / font.height; i++) { //略 .write(image, Point(0, font.height*i)); }
このfor文について解説します。これは文章が複数行になった際、一行一行にグラデーションをかけるためのfor文です。
font.region(string).size.y / font.heightは文章全体の高さ÷一行の高さになるのでこの文章が何行有るか計算できます。
Point(0, font.height*i(添字))で行数に合わせてグラデーション画像を合成する位置を調整します。
TextureにImageからコピーして表示
const Texture texture = Texture(image); while (System::Update()) { texture.draw(30, 80); }
後はテクスチャにした文章を表示するだけです。この先は関数化したりクラス化したりして自作のアプリで使いやすく改造してみてください。
さいごに
「Siv3Dでグラデーション文字を作る」いかがだったでしょうか。長い記事にお付き合いいただきありがとうございます。お疲れ様でした。
おまけ
実はSiv3Dにはグラデーション図形を描くというグラデーション文字作成にドンピシャで使えそうな機能があります。
しかし残念なことにこの機能、Textureを描くことにしか使えずImageに描きこむことができないのです。(writeやoverwriteといった関数が使えない) もし使えたら画像を用意することなくグラデーション文字が作れるんですけどねぇ。
今後実装します
— Ryo Suzuki (@Reputeless) 2017年12月3日
Twitterの話によるとバージョンアップでImageへの書き込み機能が追加されるかもしれませんね。楽しみに待っています。 ほんとに終わり。