7080 + 1

ゲームプログラミングの記事を書いてます。

【Unity】ビットマップフォントをUnityで扱う その2【ShoeBox】

前回の続きです。ブログの更新頻度が爆上がりしてます(前年比)
7081.hatenablog.com

ここからはUnity上での作業...といいたいんですが、実は吐き出したxmlファイルをそのまま使おうとするとエラーが出ます。
ので、先にxmlファイルを編集します。

<font>
	<info face="D:\Desktop
umberfont-export" size="35" />
	<common lineHeight="35" scaleW="137" scaleH="141" pages="1" />
	<pages>
		<page id="0" file="D:\Desktop
umberfont-export.png" />
	</pages>
	<chars count="12">
		<char id="53" x="105" y="53" width="29" height="50" xoffset="0" yoffset="-10" xadvance="33" /><!-- 5 -->
		<char id="54" x="37" y="46" width="34" height="50" xoffset="0" yoffset="-15" xadvance="38" /><!-- 6 -->
		<char id="55" x="72" y="91" width="31" height="44" xoffset="0" yoffset="-10" xadvance="35" /><!-- 7 -->
		<char id="56" x="72" y="45" width="32" height="45" xoffset="0" yoffset="-10" xadvance="36" /><!-- 8 -->
		<char id="57" x="0" y="46" width="36" height="49" xoffset="0" yoffset="-10" xadvance="40" /><!-- 9 -->
		<char id="48" x="0" y="0" width="45" height="45" xoffset="0" yoffset="-9" xadvance="49" /><!-- 0 -->
		<char id="49" x="80" y="0" width="17" height="44" xoffset="0" yoffset="-9" xadvance="21" /><!-- 1 -->
		<char id="50" x="46" y="0" width="33" height="44" xoffset="0" yoffset="-9" xadvance="37" /><!-- 2 -->
		<char id="51" x="105" y="0" width="31" height="52" xoffset="0" yoffset="-9" xadvance="35" /><!-- 3 -->
		<char id="52" x="0" y="96" width="36" height="44" xoffset="0" yoffset="-9" xadvance="40" /><!-- 4 -->
		<char id="32" x="0" y="0" width="0" height="0" xoffset="0" yoffset="0" xadvance="22" /><!--   -->
		<char id="9" x="0" y="0" width="0" height="0" xoffset="0" yoffset="0" xadvance="176" /><!-- 	 -->
	</chars>
	<kernings count="0">
	</kernings>
</font>

xmlファイルの中身です。参照するpngファイルのパスが明らかにおかしいですね。2箇所おかしいです。

D:\Desktop
umberfont-export

謎の場所に改行が入っています。(今回の画像はデスクトップに保存していました)
ShoeBoxで出力する際、ファイル名は設定をいじっていなければ「numberfont-export」になります。で、一番最後の\が何故かメタ文字扱いになってしまい、\nになって改行コードになってしまうみたいです。この辺ぶっちゃけよくわかりません。
とりあえず2箇所おかしくなっているので、正しいファイルパスに書き換えてください。

ここからはUnityでの作業です。ShoeBox Tools for Unityをインポートしてからの作業になります。

Asset->ShowBox Tools->Import Bitmap Fontを選択、xmlを選んでください。
エラーとかが出なければ、Asset直下にfontsettingsとマテリアルが出来ます。

あとはuGUIのTextのFontのところに出来たfontsettingsを突っ込めばOKです。
こんな感じになるはずです。
f:id:atori708:20171203021940g:plain
GIFのレコーダーのせいか画像汚いですが、Unity上ではきれいに出てます。

補足

このままだと改行がうまく効かないと思います。fontsettingsのLineSpacingをいい感じの数値にしてください。今回の画像の場合は50くらいがいいかと思います。
あと一行目からなんか文字が出る高さがおかしくなることがあります。これはfontsettingsのCharacterRecsts配列のVertのyで変わってきます。ここはShoeBoxのTxt Line Heightが影響してくるようです。ShowBoxで出力する際の文字出力イメージを見ながらいい感じに調整してください。今回の画像の場合、Txt Line Heightを35くらいにしました。
fontsettingsの値の詳細は面倒くさいのでに他に譲ります。

今回はこれで以上です。不明点や指摘などありましたらコメントでお願いします。

【Unity】ビットマップフォントをUnityで扱う その1【ShoeBox】

今回は長くなったので2回に分けます。
UnityでUIのテキストを表示するときは、uGUIのTextを使うと思います。
(TextMeshProのTextもありますが、オリジナルのビットマップフォントを扱う方法が見つからなかったので割愛)

しかしフォントを使って文字を描画するよりも、自分で作った画像をテキストで表示したいときがあると思います。
特にダメージとかの数字は自分で作った数字画像、つまりビットマップフォントが扱えるとうれしいですね。
Unityではビットマップフォントをサポートしていますが、設定を手動でやる場合、0~9の数字を用意するだけでも結構面倒くさいです。

少しでも楽するためのツールとして、ShoeBoxというものがあったので使い方を紹介します。

・用意するもの
自作の文字画像を1枚にまとめたもの(今回は0~9の数字)
ShoeBox http://renderhjs.net/shoebox/
ShoeBox Tools for Unity https://www.assetstore.unity3d.com/jp/#!/content/35760
※ShoeBoxはAdobeAirで動作しているので、AdobeAirを先にインストールしておく必要があります。

今回はこちらの画像を使います。拾い物。
f:id:atori708:20171202151509p:plain

手順

ShoeBoxを起動すると、タブがSpritesを選んだ状態になってると思います。GUIタブを選んで、BitmapFontのところに画像をD&Dしてください。
新しく開いたウィンドウのSettingsを選ぶと、また新しいウィンドウが開きます。それのAdvancedタブを選択。するとこんな画面になると思います。
f:id:atori708:20171202152442p:plain
設定を以下のように変えてください。

・TemplateをFNT-xml Starlingに(FNT Unityってあるけど無視!!)
・下の方のTxt Charsを「5678901234」に(あとで解説)

一応これで最低限の設定はできてます。
他の項目に関してはこの記事の最後に補足程度に説明しておきます。

Txt Charsをこのように設定したのは、今回扱う画像の並びが「5687901234」になっているからです。
ShoeBoxは文字の形を認識してどの文字を使うか決定しているわけではなく、左上から画像の区切りを1つずつ認識しているだけです。
それぞれにどの文字を当てはめるかを決めるのがTxt Charsです。

Applyを押すと、以下のようになると思います。
f:id:atori708:20171202155659p:plain
上の画像が元画像、左下が完成画像、右下が文字を並べたらどうなるかを見れるところです。
が、なんだか正しく認識できてないっぽいですね。この場合、元画像の数字の間隔をいじってください。ShowBoxを開いたまま画像をいじって、SettingsウィンドウのApplyを押せば読み込み直してくれます。
今回は5~9を少し上にするだけで済みました。

きれいに出来るとこうなります。
f:id:atori708:20171202154828p:plain

思った通りになっていればSave Fontを押してください。元画像があった場所にpngxmlファイルが作られます。
できたファイルをUnityに入れるのが次のステップですが、長くなったので記事を2つに分けます。次回更新までお待ち下さい。

何か不明点、間違っている点があればご指摘ください。

補足

ShoeBoxの設定で、大体いじるであろう項目の解説をしておきます。
・Kerning~~ ...カーニングに関する設定です。今回は数字だけなのでカーニングはしません。ていうか設定の仕方わかりません。
・Message ...完成画像の横に表示する文字です。どんな感じでフォントが並ぶか見れます。
Tex Power Of Two ...完成画像の幅、高さを2の乗数にするかです。ゲームに使うならTrueのほうがいいかも。
・Txt Line Height ...行の高さです。
・Txt Monospace ...文字同士の間隔を詰めるかです。
・Txt Space Width ...スペース文字の間隔の広さです。
・Txt Tab Size Spaces ...タブ文字の大きさをスペースいくつ分にするかの設定です。2,4,8が主流ですね。

【Unity】ポリゴンの裏表で描画を変える

タイトルの通り、シェーダでポリゴンの裏表を判定する方法を紹介します。
ポリゴンがカメラからみて裏か表かで描画の仕方を変えたいとき、2つの方法があります。
他にも方法があれば教えていただければと思います。

・カリングの設定を変えた2つのパスで描画する
・VFACEセマンティクスでif判定して描画を分ける

今回は裏面と表面で色を変えるだけの超シンプルなシェーダにしました。
どちらも得られる結果は同じです。
f:id:atori708:20171112173019g:plain

Gistを初めて使いました。いいですねこれ。

前者は単純にパスを2つ作り、CullのFrontとBackに変えただけのものになります。
後者はパスは一つで、ピクセルシェーダでVFACEを受け取ってif文で色を変えてます。
VFACEは表なら正数,裏なら負数がかえってくるみたいです。

どちらもシェーダの事が分かれば以外と簡単です。(自分はVFACEの存在を知りませんでした。)

問題は重さなのですが、
前者の方法は2回描画するので普通に描画するより重いですし、
後者はif文使っちゃってるので重いと思います。

どちらがいいかは自分にはわかりません。多分毎回if判定走る後者よりも前者のほうが軽い気がします。
この2つの切り替えはそんなに手間ではないのでどちらも試して軽い方採用するのがいいと思います。

【Unity】イントロ+ループ再生を実装する

またUnityの記事です。今回は難易度低め。

BGMを流すとき、イントロ+ループというのを前提にしたBGMって結構あると思います。
Unityではそれを再生する機能が標準でない(Why?)ので、簡単に出来るのを実装してみました。

必要なものは
・イントロとループで分けたAudioClip

だけです。わざわざ分けるのめんどいですが実装が簡単な分こっちに手間がかかるということで...

ソースは以下です。改良なり再配布なりご自由にどうぞ。
(再生、停止の最低限の機能しかないです)

public class BGMPlayer : MonoBehaviour {

    [SerializeField] AudioClip bgmIntroAudioClip;
    [SerializeField] AudioClip bgmLoopAudioClip;

    AudioSource introAudioSource;
    AudioSource loopAudioSource;

    void Start()
    {
        introAudioSource = gameObject.AddComponent <AudioSource>();
        loopAudioSource = gameObject.AddComponent <AudioSource>();

        introAudioSource.clip = bgmIntroAudioClip;
        introAudioSource.loop = false;
        introAudioSource.playOnAwake = false;

        loopAudioSource.clip = bgmLoopAudioClip;
        loopAudioSource.loop = true;
        loopAudioSource.playOnAwake = false;
    }

    public void PlayBGM()
    {
        if (introAudioSource == null || loopAudioSource == null) {
            return;
        }

        introAudioSource.Play ();
        loopAudioSource.PlayScheduled (AudioSettings.dspTime + bgmIntroAudioClip.length);
    }

    public void StopBGM()
    {
        if (introAudioSource == null || loopAudioSource == null) {
            return;
        }

        if (introAudioSource.isPlaying) {
            introAudioSource.Stop ();
        } else if (loopAudioSource.isPlaying) {
            loopAudioSource.Stop ();
        }
    }
}
解説

インスペクタにイントロとループのAudioClipをそれぞれ設定すれば再生出来ます。
今回のやりかたは、AudioSourceをイントロとループでそれぞれ用意して、イントロの再生が終わった瞬間からループを再生する。
という仕組みになっています。

PlayScheduled()を使うことで、再生を遅延させることができます。AudioSetttings.dspTimeはTime.timeとは別に、オーディオを再生するための正しい時間みたいなものです。
時間指定で音を再生する場合はこれ使ったほうがいいと思います。

別の方法

他の方法として、AudioSourceは1つで、イントロの再生が終わると同時にClipを入れ替えるという方法もありますが、切り替えの瞬間にどうしてもノイズが走ってしまいます。
フレーム単位でしか切り替えられないので当然っちゃ当然なんですが、解決方法イマイチわからず...

一番はAudioSourceもAudioClipも1つだけで、ループを開始してほしい時間を指定すれば動いてくれるスクリプトなんですが、色々試した結果上記の方法が一番実装は楽そうでした。
多分サンプルレートとかも考慮して組まないと駄目な気がします。

蛇足

今回の調べて思ったんですが、Unityのマニュアルとリファレンスの音周りがほとんど翻訳されてないのが軽く衝撃でした。

【Unity】スプレッドシートのデータをスクリプトから取得する【OAuth】

久しぶりの更新です。
仕事柄、最近はUnityばかり触ってます。のでUnityの記事です。

ゲームで使う値をエクセルじゃなくてスプレッドシートで管理したかったので、色々調べました。
全体の流れをメモ代わりに書きますが、詳しく触れていないところはわからないところです。

スプレッドシートにアクセスにするには、2つの方法があります。
Google API Keyを使ってアクセスする
OAuth認証をしてアクセストークンをもらい、それでアクセスする

1つ目はすぐに出来ます。APIKeyさえあればアクセス出来ますが、シートの共有をオンにしておく必要があります。
共有するのが嫌な人はOAuth認証を使いましょう。APIKeyのほうは割愛します。

OAuth認証に必要なもの

OAuth認証によるアクセスでは、以下のものが必要になります。
・OAuthクライアントID
・OAuthクライアントシークレット
OAuth認証コード
・アクセストーク
・リフレッシュトーク
スプレッドシートのID

実際にアクセスするのに必要なのはアクセストークンとスプレッドシートのIDのみです。
アクセストークンを取得するのにOAuth認証コードとクライアントシークレットもしくはリフレッシュトークンが必要になり、
OAuth認証コードやリフレッシュトークンを取得するにはOAuthクライアントIDが必要になります。
結構ややこしい。

注意なのは、アクセストークンには有効期限があり、切れるとそのトークンではアクセスできなくなることです。
その時はリフレッシュトークンを使って、アクセストークンを再発行することになります。
リフレッシュトークンに有効期限はない(多分)ので、どこかに保存しておきましょう。

スプレッドシートのIDは、スプレッドシートのURLの一部になります。
https://docs.google.com/spreadsheets/d/[この部分]/edit#gid=0

手順

OAuthのクライアントIDとクライアントシークレットをAPIConsoleから作る

当たり前ですが、Googleアカウントが必要になります。
Google API Consoleとググるとトップにサイトが出てきます。
そこで認証情報→認証情報を作成→OAuthクライアントの作成を選んでください。

f:id:atori708:20170215001707p:plain

アプリケーションの種類を聞かれるので、その他を選んで、名前は適当につけてください。
これでOAuthのクライアントIDとクライアントシークレットを取得できました。

Unityが登場するのはまだ先です。

OAuthのクライアントIDとScopeから、認証コードを取得する

認証コードを取得するには、クライアントIDとScopeが必要になります。
Scopeは、特定のサービスに、どの権限でアクセスするかを教えるものです。
今回はスプレッドシートの読み書きをしたいので、
https://www.googleapis.com/auth/spreadsheets
がScopeになります。

Scopeの種類は以下に書いてあるので、スプレッドシート以外のサービスにもアクセスできます。
OAuth 2.0 Scopes for Google APIs  |  Google Identity Platform  |  Google Developers

コードを取得するには、
https://accounts.google.com/o/oauth2/v2/auth にクエリをたくさんつけてリクエストを投げます。

クエリは、

?scope=https://www.googleapis.com/auth/spreadsheets
&redirect_uri=http://localhost
&response_type=code
&client_id=OAuthクライアントID

になります。
全部ひとつなぎにしてURL欄に入力してください。

URLが正しく入力できていると以下の画面に飛ぶので、許可を選んでください。
もしGoogleのアカウントにログインする画面に飛んだら、OAuthクライアントを作ったアカウントでログインしてください。

f:id:atori708:20170215001833p:plain

許可を押すとredirect_uriで設定した先へ飛んでいきます。
localhostにしたので何もないですが、URLのcode=~以下がOAuthの認証コードになるので保存しておきましょう。

認証コードからアクセストークンとリフレッシュトークンを取得する

ここからUnityでの作業になります。
UnityのWWWを使って、OAuthからスプレッドシートのアクセストークンをもらいましょう。
https://www.googleapis.com/oauth2/v4/token にフォームデータ付きでリクエストを送信します。

WWWForm form = new WWWForm ();
form.AddField ("code", OAuthの認証コード);
form.AddField ("client_id", OAuthクライアントID);
form.AddField ("client_secret", クライアントシークレット);
form.AddField ("redirect_url", "http://localhost");
form.AddField ("grant_type", "authorization_code");
form.AddField ("access_type", "offline");
form.headers.Add ("Content-Type", "application/x-www-form-urlencoded");
Dictionary<string, string> headers = form.headers;
byte[] rawData = form.data;
WWW www = new WWW ("https://www.googleapis.com/oauth2/v4/token", rawData, headers);

レスポンスはwww.textにJSON形式で入って返ってきます。

こんなJSONが返ってきたら成功です。

{
 "access_token": "アクセストークン",
 "token_type": "Bearer",
 "expires_in": 3600,
 "refresh_token": "リフレッシュトークン"
}

expires_inがアクセストークンの有効期限で、スプレッドシートは1時間のようです。
リフレッシュトークンは数に上限があるそうなので、なるべく同じのを使い続けましょう。

Unityからでなくても、curlコマンドを使うと同じことが出来ます。
その方法は他の人が書いてるので割愛。

アクセストークンからスプレッドシートにアクセスする

このシートのデータを取ってきてみましょう。
テイルズオブベルセリアのキャラです。面白かったです。

f:id:atori708:20170215001651p:plain

ここまで来ると簡単で、
https://sheets.googleapis.com/v4/spreadsheets/スプレッドシートのID/values/取得するセルの範囲?AccessToken=アクセストークン
にPOSTすると、セルの中身がJSON形式で返って来ます。

WWW www = new WWW ("https://sheets.googleapis.com/v4/spreadsheets/スプレッドシートのID/values/取得するセルの範囲?AccessToken=アクセストークン");	

今回はセルの範囲をA1:B4にしました。

{
  "range": "'シート1'!A1:B4",
  "majorDimension": "ROWS",
  "values": [
    [
      "名前",
      "性別"
    ],
    [
      "ベルベット",
      "女"
    ],
    [
      "ライフィセット",
      "男"
    ],
    [
      "ロクロウ",
      "男"
    ]
  ]
}

無事取ってこれたでしょうか。
後はJSONをMiniJSONとか使って保存すればOKですね!

リフレッシュトークンからアクセストークンを取得する

先程も書きましたが、アクセストークンには有効期限があるので、もし切れていたら、リフレッシュトークンを使って再発行する必要があります。
https://www.googleapis.com/oauth2/v4/tokenにリクエストを飛ばすと取得できます。

WWWForm form = new WWWForm ();
form.AddField ("refresh_token", リフレッシュトークン);
form.AddField ("client_id", OAuthクライアントID);
form.AddField ("client_secret", OAuthクライアントシークレット);
form.AddField ("grant_type, "refresh_token");
Dictionary<string, string> headers = form.headers;
byte[] rawData = form.data;
WWW www = new WWW ("https://www.googleapis.com/oauth2/v4/token", rawData);

これで成功していたら、アクセストークンがJSON形式で返ってきます。
アクセストークン期限が切れていなくても再発行可能のようです。
10個くらい連続で取得してみたのですが、全部使えました。

アクセストークンが有効かどうか調べる

有効かどうか、また有効期限も調べられます。

WWW www = new WWW("https://www.googleapis.com/oauth2/v3/tokeninfo?access_token=アクセストークン");

無効だった場合

{
 "error_description": "Invalid Value"
}

※もともと存在しない適当な文字列入れても同じエラーが返ってきます。

有効だった場合(例)

{
 "azp": "247046462806-7efg42ut1tau4n2ku081gn81nebma2ab.apps.googleusercontent.com",
 "aud": "247046462806-7efg42ut1tau4n2ku081gn81nebma2ab.apps.googleusercontent.com",
 "scope": "[]https://www.googleapis.com/auth/spreadsheets[]",
 "exp": "1485228014",
 "expires_in": "3584",
 "access_type": "offline"
}

Unityの記事と言いましたが、認証の仕方は他でも使えると思います。
間違っていたり、質問や不明点がありましたらコメントでお願いします。

WindowsなんだからWindowsAPIも知る必要がある

学生時代の自分のDirectXのプログラムを見ていると、先生からもらったサンプルをそのまま意味もわからず使っているケースがあります。 特にWindowsAPI周りが意味不明で、この関数呼んでる意味あんのか?と思ったりすることもあります。

しかし調べてみると、意味のある処理が非常に多かったので、忘れないようにメモしておこうと思います。 ちなみに、独自解釈が多々入っているので、間違っている可能性があります。その時はご指摘いただければと思います。

ValidateRect(HWND, CONST RECT*)

過去の自分のプログラムのコメントを見ると、「WM_PAINTを呼ばないようにする」と書いてありました。 WM_PAINTというのは、WindowsAPIで毎フレーム呼ばれる、描画メッセージです。つまり、DirectX使わなくても、WindowsAPIだけで画面描画することはできます。 ですがそれでテクスチャつけて3Dモデル動かして・・・なんてやってられません。描画をDirectXだけでやりたいなら、このメッセージが飛ばないようにして、処理を少しでも軽くしてやりましょう。 第一引数にウィンドウハンドル、第二引数にNULLを渡してやれば、そのウィンドウではWM_PAINTは呼ばれなくなるみたいです。(確かめてない)

GetClientRect(HWND, RECT*)

これ意外と大事です。Windowsのウィンドウには、外枠がありますよね。ウィンドウのタイトル表示してたり、閉じるボタン、最小化ボタンがあるところです。 左右と下にもわずかですが枠があります。CreateWindow()呼ぶときに幅と高さを指定しますが、これはその枠を含めたサイズでウィンドウを作ります。

ですが実際にゲームの描画が行われるのはその枠を覗いた領域のみです。これを「クライアント領域」と言います。この関数はそれを取得できます。(枠がないクライアント領域のみのウィンドウを作ることも可能です) ウィンドウのサイズそのままでDirectXの描画を行うと、きっと小さなズレが生まれるでしょう。ゲームを作る上で、クライアント領域を覚えておくのは必須といえます。

今回は2つ紹介しました。全部WindowsAPIです。使い方は全て調べていただければ普通に出てきます。 DirectXの学習も大切ですが、こういった部分は一度設定するとそのまま変えないので、忘れがちになると思います。 また何か紹介できるものがあれば書いていきたいと思います。

OSのバージョンを調べる(VerifyVersionInfo())

OSのバージョン取得方法には、GetVersionEx()と、VerifyVersionInfo()の2つがあります。 しかし両者には違いがあります。

前者は現在自分の使っているOSのバージョンを知ることが出来ます。
後者は現在自分の使っているOSと、引数で指定したバージョンを比較します。

言葉だけではわかりにくいですね。でも安心してください。前者はWindows8.1では使えません。 古い形式だとコンパイラに怒られてしまいます。
私はなんとか前者が使えないかと四苦八苦してました。

なので、Windows8.1の人は何も考えずにVarifyVersionInfo()を使いましょう。 GetVersionEx()の使い方はご自分でお調べください。

それでは、まずはVerifyVersionInfo()を使うための準備です。

    OSVERSIONINFOEX OSver;
    ULONGLONG condition = 0;
    OSver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
    OSver.dwMajorVersion = 6;
    OSver.dwMinorVersion = 2;
    VER_SET_CONDITION( condition, VER_MAJORVERSION, VER_GREATER_EQUAL);
    VER_SET_CONDITION( condition, VER_MINORVERSION, VER_GREATER_EQUAL);

OSVERSIONINFOEXに設定しているのは、この構造体のサイズと、Windowsのバージョン情報です。 このバージョンと、自分の使っているOSのバージョンを比較するわけです。サイズは必ず必要です。 dwMajorVersionに6、dwMinorVersionに2を渡しているので、Windows8.0を表しています。 Majorは6のままで、Minorを1にするとWindows7、3にするとWindows8.1を表します。

VER_SET_CONDITION()というのは、何の値をどのように比較するのか、というのをconditionに設定しています。 OSVERSIONINFOEXにはたくさんのメンバがあります。OSのバージョン以外にも、ServicePackのバージョンとか、なんか色々です。で、現在はVER_MAJORVERSIONVER_MINORVERSIONを比較します。比較の仕方がVER_GREATER_EQUAL、要は比較演算子<=で比較するわけです。

つまり、メジャーバージョン、マイナーバージョンの比較は<=で比較するように設定します。これをマイナーバージョンだけは==で比較、とか自由に設定できるわけです。

さて、それではVerifyVersionInfo()を実際に使ってみるとこうなります。

if( VerifyVersionInfo( &OSver, VER_MAJORVERSION | VER_MINORVERSION, condition))
{
    // Windows8.0以上の時の処理
}
else
{
    // それ以外の処理
}

第二引数で、何と何を比較するのかをパイプ演算子で設定します。 これを正しく設定しないと、先程用意したconditionの設定が無駄になります。 先程作ったOSVerconditionの設定だと、自分の使っているOSがWindows8.0以上なら trueを、それ以外ならfalseを返します。