Visual Studio Code & C++ on OSX(clang)開発環境でC++11対応する

OSX上のVSCodeでC++を書く際にC++11シンタックスでコードを書くと、VSCodeの構文チェックで怒られます。
f:id:giraffyk1:20161004090645p:plain

C+11の型推論autoくらいなら警告で済みますが、初期化子リストだとエラーとして表示されます。どうしてもこれを解決しなければならなかったので調べました。

結論としては、VScodeのユーザー設定に以下を加えます。

	"clang.cxxflags": ["-std=c++11"]

配列でcxxflagsを渡せるため、includeパスや他のwarningに関する設定も渡せるようです。警告全部出しの-Weverythingを試しに設定すると

	"clang.cxxflags": ["-std=c++11", "-Weverything"]

f:id:giraffyk1:20161004091841p:plain

ご覧の通りバッチリ出力してくれました。

設定は以下の通り、基本設定→ユーザー設定から、settings.jsonを開いて追記します。

f:id:giraffyk1:20161004092004p:plain
f:id:giraffyk1:20161004092217p:plain


以下のページを参照すると、さらにclangの実行バイナリの位置指定をしたり++じゃないほうのcflagsを設定したり出来るようです。
GitHub - mitaki28/vscode-clang: Completion and Diagnostic for C/C++/Objective-C using Clang


Diagnostic(構文チェック)はc++関連のプラグインがしているものと当初思っていましたが、VSCode本体側でコントロールしているようで、この設定にたどり着くまでにかなり時間がかかってしまいました。

C++でゲームを開発することに関する愚痴

※ただの愚痴なので何も得られません

 日記を書けない日が続いています。毎日ゲーム制作には取り組んでおり、プログラムを毎日書いたり書き方を調べたりしています。具体的には、初期に書いたソースコードを全て捨てて、長期的な開発に耐えうるゲームエンジンだとか基礎みたいな部分を手がけています。

 C++はとても難しい言語です。僕が過去に触ったモダンなスクリプト言語たちより手強い事はもちろん予想していました。ただ僕は、Cを多少書いた経験があったので、なんとかなるだろうとタカをくくっていたのも確かです。それにしても、C++は予想を軽々と越えて扱い辛い言語でした。ネット上で「ゲームの開発言語といえば?」という質問に真っ先に名があがるC++言語。ですが、実のところC++を用いてフルスクラッチでゲームを作ろうとするアマチュアを殆ど見つける事が出来ません。その因果を今僕はひしひしと感じています。

 そんなわけでこの苦難を文字に起こすことにより自分のもやもやにケリを付け、引き続き取り組みを邁進したいと考え、ここに書きなぐっておくことにしました。

 書いてる僕自身も知識不足だからこういう状況になっているのは理解しているのですが、ゲームを作ってみようと軽い気持ちでこの巨象に触れてしまった無知なプログラマの素直な心情をここに吐露しておこうと思います。

Syntaxがひどい

 これは誰しもが認めるところである。もうひどいなんてもんじゃない。*とか&ならまだしもだったり&&だったり::*とか->*とか(*)とかもうわけわからない。可読性が高いコードなんて書けっこない。これに加えてオリジナルのクラス名がいたるところで型としてソースコードに埋め込まれていくので、もう左手でコード書きながら右手でハンギングロープを撚っている気持ちになる。

無防備すぎる

 これはC++が何でも出来る、速度が速いというコンセプトを持っている事に起因しているのだろうけども、温室育ちの僕にはC++の世界は世紀末そのもの。メモリに直接触れるとかそういう話ではない。例えば、=やら()のオペランドに変数を突っ込むと参照じゃなくコピーで渡されるなど、他の言語からしたらどうかしているヤバいルールが採用されている点を差している。もちろん回避方法があって、それを自分でコードに起こしていくわけだけど、ガードを固めれば固めるほど出来る事は減っていくし、型が合わなかったりしてそれを上手く動かすのに多大な労力がかかってくる。スマポとか&とかrvalueがどうだとかmoveとかconstとかコピーオペランドの禁止とかもうイロイロ手段も有りすぎるし、ネットでは「こうしないやつはC++使いとは認めたくないね」みたいな事を色んな書き方でみんな言ってるし、影響されやすい僕としては彼らに怒られないよう出来るだけカッコイイコードにしたいんだけれども、StrictなC++コードを書く、そしてSyntaxぴったりに一発で書く、そして設計としてもイケてるものを生み出す、という三拍子を実現するには僕のようなC++初心者にはむちゃくちゃツラい。

 他のLLな言語はこういうところに触る手段自体を用意していない事の方が多い。最速であり続けるというのは苦痛を伴うというのがよく分かる。

1つの機能に複数の方法がある

 マクロとかtypedefとかusingとかもう1つでいいじゃん。みたいな似たような機能が大量にある。最速を維持し続け、可能性を排除しない信条が生み出す痛みは、僕みたいな後から来たプログラマが一身に背負うのがC++界隈のエコシステムにきっとなっているんだろう。10年以上CやC++を追っかけていればこういった手段を上手く使い分ける事が出来るんだろうけど、僕のような新参者には拷問でしかない。新しいイケてる機能が追加されると「新機能○○は夢がひろがりんぐ! ××機能を使い続けるやつは糞プログラマ認定」みたいに書いてあったりして、でも機能が新しいからネット上で見つかるサンプルコードも少なくて。そんな毎日です。

型を合わせるのがダルすぎる

 これも速さゆえのルールなんだろうけど、とにかくダルい。ヘッダと実装を分けると、メンバ関数や変数の呼び出し元の戻り値部分と合わせて3つがピッタリ型があってないとコンパイルエラー。auto付けても2つ。型をあわせるために四苦八苦してると、ガンダムのドッキングシーンBGMが僕の頭でリフレインし続けるわけです。constやらスマポやら*&やら。こういった方々が輪をかけて事をややこしくする。初期化はともかく、戻り値とか…上手くしといてよホント。コンパイラも何か薄々感付いたようなメッセージ吐くし。分かってんならホント上手くしといて!

 最近、コード書いている時間の半分くらい型合わせに使ってる気がします。

メタプログラミング…弱くない?

 テンプレートとconstexprもあるしラムダ式もあるし関数ポインタもクラス変数(静的メンバ)もあるんだけど…。使いたかったけど調べても見つからなかった機能としては、メンバ関数や変数の一覧を取得する手段。おなじくメンバ関数の名前。コンパイルする、実体は自分で作らないとまったく存在しない仕組という手前、そういうのが無いのは理解できるんだけど、書き方に制限が出て、もやっとします。他の言語ではインタプリタが関数名や変数名を保管したりしてるのかな。

ビルドが大変

 クラスをディレクトリで階層化しててmakefileからコンパイルを通したら通らない。案の定サブディレクトリが上手く解決されてない。手がパタパタとよく動いてたタイミングで、急ブレーキ。ここでMakeの独自言語を深掘りしないといけないのがとても苦痛だった。cmakeというモダン? なビルドツールもあるらしいがどちらも独自言語で心が折れそうになる。Unityとか使った事ないけど[ ビ ル ド]みたいなボタン押せばきっと完成なんだろうなあいいなあ。

ネット上の情報が少ない

 Webで使われる言語と比較してC++の情報は圧倒的に少ない。日本語でも英語でも。あとコンパイラが複数あるのでエラーメッセージもコンパイラ毎に異なる。これはエラーメッセージを検索キーワードにネットを探すのがかなり難しくなる。OSXなのでclangなんだけどあんまり情報がヒットしない。VC++のコンパイルエラーだともっと引っかかる気がする。


 さーて、引き続きがんばって書くぞ!

SFMLのライセンス体系について

本開発に入る前にライセンス体系が気になったので、調べてみる。SFML以外で使っているC++ライブラリはstd::ほにゃららとboostくらいであとは自前で書いてるのでSFMLだけ調査。

qiita.com

License (SFML / Learn)

によるとSFMLは zlib/pngライセンスです。

In short, SFML is free for any use (commercial or personal, proprietary or open-source). You can use SFML in your project without any restriction. You can even omit to mention that you use SFML -- although it would be appreciated.
(ざっくりいうとSFMLは商用非商用など形態を問わず無料で利用できます。あなたのプロジェクトでのSFML利用には一切制限がありません。もちろんSFMLの使用を表明してくれたらとても嬉しいです)


というわけなんだけども、SFMLに含まれる他のライブラリのいくつかが別のライセンス形態を採用している。で以下が各ライセンスにおける、ゲームをバイナリで配布する際の制作者の義務。

BSD 3 license - 著作権と免責の記載
LGPL license - ライブラリ動的リンクの場合制限なし
GPL license - 著作権・免責の記載、再配布制限の禁止(コピー自由)、GPLライセンスを引き継ぐ義務

でfreetypeがFTL or GPLとなっているわけだけども、これはマルチライセンスやデュアルライセンスと呼ばれるもので、どちらかを適用せよという事らしい。FTLにすれば、GPLのコピー自由、自分自身もGPLで配布というヤバイ状況は回避できる。GPLはオープンソースコミュニティ用で、ソースコードを配布する前提がある。これがやっかいなので商用プロジェクトではオープンソースのライブラリを採用するのに二の足を踏むことが多い。

デュアルライセンス - Wikipedia

でfreetype project独自のライセンス形式FTLは

商標、著作権、ライセンスに関する情報

上記で和訳を読むことができた。義務部分を抜き出すと

2.再頒布
-----------------

本ライセンスは、FreeType Project (ソースコード形式およびオブジェクトコード形式の両方において)
およびその派生著作物をいかなる目的であれ使用、実行、実施、コンパイル、
表示、複製、その派生著作物の作成、頒布およびサブライセンスする権利および使用許諾、
および本書において付与された権利の一部または全部を
実行する権限を他者に与える全世界を対象としたロイヤルティ無償の
永続的かつ取消不能の権利および使用許諾を
以下の条件に従うことを条件として付与します。

o ソースコードの再頒布には、このライセンスファイル
(「FTL.TXT」) を改変せずに含めなければなりません。
元のファイルへの追加、元のファイルからの削除または変更はすべて
ドキュメンテーションに明記し添付しなければなりません。改変されていない元のファイルの著作権表示を
ソースファイルのすべてのコピーに
残しておかなければなりません。o バイナリ形式での再頒布には、本ソフトウェアの一部が
FreeType Team の著作物に基づいていることを
頒布ドキュメンテーションにおいて明記しなければなりません。さらに当方は、
あなたのドキュメンテーションに FreeType Web ページへの URLを
記載することを奨励しますが、これは必須ではありません。これらの条件は、 改変されていないファイルだけではなく、
FreeType Project から導出されたかまたはFreeType Project に基づくすべてのソフトウェアに適用されます。もし、あなたが当方の著作物を使用する場合、
あなたは当方を承認しなければなりません。しかし、当方に対して
手数料等を支払う必要はありません。
3.広告
--------------

FreeType の作成者および寄与者またはあなたのいずれも、
作成者、寄与者またはあなたの名前を、書面による事前の許可なしに
商用、広告または販売促進目的で使用しないものとします。当方は、あなたのドキュメンテーションまたは広告用マテリアルにおいて
本ソフトウェアについて記述する際に、「FreeType Project」、「FreeType Engine」、
「FreeType ライブラリ」 または「FreeType Distribution」のいずれかの文節を使用することを
提案します (ただし、要求はしません)。あなたは本ライセンスに署名していないため、
本ライセンスを受け入れる必要はありません。ただし、FreeType Project は著作権で保護されたマテリアル
であるため、本ソフトウェアを使用、頒布および改変する権利を
あなたに付与するのは、本ライセンスまたは作成者と契約した別のライセンス以外にありません。したがって、FreeType Project を使用するか、頒布するか、または改変することによって、
あなたは本ライセンスのすべての条件を
理解し受け入れたとみなされます。

となっている。ようするに

  • あなたのソフトウェアの一部が FreeType Team の著作物に基づいていることを表記しなさい
  • ブログやらでFreeTypeの話題について扱う際は「FreeType Project」と記載しなさい

3.広告という部分が最初まったく意味がわからなかったが、ようするに「freetypeを使うやつは我々の名称を正しく呼称しなさい」という事らしい。「あのくそフォントシステム」とか「Microsoft FreeFont」などという他の勝手ないい方で我々のライブラリを呼ばわってはいけないよ、という文面らしい(提案します云々はただの嫌らしい言い回し)。

というわけでSFMLのライセンスに関する僕の義務は、ゲームのダウンロードページなんかの最後の著作権やライセンス表記部分に

  • 本ソフトウェアの一部は、○○ライセンスの免責を含む ○○○○○○ の著作物に基づいています。

というやつをいくつか書き連ねるだけで良いということが分かった。

プロトタイプ4

 ドット絵をちょっと豪華にみせる作戦として、見下ろし視点にちょっと奥行きが出るようパースをかけて表現したい。

f:id:giraffyk1:20160927085446p:plain

ポケモンプラチナ? イメージとしてはこんな、画面上部の消失点に向けてオブジェクトが内側に向いてる状態。これを実現する作戦として、2Dの画面を単純に台形に変形してから描写する事を考えた。

実装方法としてはSFMLが持っている機能で頂点リストで四角形が書けるものがあったので、これを使おうと思った。その機能で画面大の台形板を作って、その上にテクスチャとして画面バッファを貼り付ければ奥行き出るのではないだろうか。

と思ったけど、失敗。テクスチャを貼り付けると形がゆがむしちらつく。これはSFMLが悪いのか僕が悪いのかわかららず。

プランB。SFMLはOpenGLが操作できるようなので、そこから画面大の四角いポリゴン板を生み出してそこに画面バッファを貼り付ける。んで奥行きが出るように軽くポリゴンを回転させてやればいいんじゃないかと思ったが…こちらも失敗。SFMLの画面描写機能とOpenGLが同時に使えなかった。OpenGLでポリゴンを出した後、他のインターフェイスやたデバッグ情報など上からdraw命令で描画するとOpenGL経由で出力したポリゴンが消えてしまう。

解決方法がありそうなんだけど・・・そんな事より上のポケモンの画面をじっくり見てて気づいたのが、キャラクタはドット絵なんだけど、それ以外は3Dで描写されているのでは無いかという疑念。

www.youtube.com


で、動画を実際見てみるとやっぱりそのようだ。建物やオブジェだけ3D?ともかくプレイヤーの位置によって横壁面や上面の見え方が違うのは2Dじゃ実現出来ない。僕がもしこのままOpenGLの探求を続けて、2Dにパースをかけれるようになっても、ただ歪んだ画面になるだけで立体感残したままパースがかかった画面にはならないのでしょうね。

…というわけで、今回の開発で初めて予定していた機能というかエフェクトの実装を取りやめました。

代わりにちょっとしたものを。

カメラエフェクト - YouTube

カメラが主人公が追尾する速度に少し遅延を入れました。一行で書けないかなと頭をひねったが結局三行必要だった。数学をもっと勉強しておけばなあ…。


というわけで、技術検証を終了して、本組みに入っていく。まだまだ知識が半端だけども完成するくらいまでは破たんせずに続けられる程度にはC++やらSFMLやらが理解できて全体の設計、エンジン的なもののイメージが出来た。


ただそういう地盤作りをしている間。たぶん1〜2ヶ月は目に見える変化が無いので、この開発日記はまた技術的なものに絡む独り言が増えていくだろうなあ。

プロトタイプ3

 険しい道のりを越えてようやくプレイヤーキャラクターが歩けるようになりました。


https://www.youtube.com/watch?v=eOcvCJTd8fM

 素材は素材配布サイトを運営しているねくらさんからお借りしました。

 なんとかビルダーとか、ほにゃららビルダーみたいなので制作しはじめると一瞬の道のりなんだと思いますが、スクラッチで作っていくのはとても大変でした。捨てるプログラムとはいえ、オブジェクトの管理、アニメーションやフレームの管理などの基礎というかエンジンというかそういうものを作りながらだったので、余計に骨が折れました。自由度はツール上で制作するより高くなる…はず!

 ここからは、キャラ変えようぜーとか、NPC歩かせようぜー、とか足の速さ変えようぜ―とか、アニメのコマ数いじろうぜ―なんかはそれほど苦なくできることでしょう。

 そろそろコードが1000行近くなってきたので、本格開発に移行すべくこれはスクラップにして組み直す予定。その前に1つだけ後からじゃあめんどくさそうな技術検証が必要なカメラエフェクトを実装を試みる。

 エターナる(最近知った単語)になりませんように。

プロトタイプ2

 ちょっと間が開いてしまいました。本制作用のクラス構成なんかを考えていました。(以後ですます調で)

 とはいえまずは技術検証ということでプロトタイプ制作に復帰。FPS表示+デバッグ関連情報表示とコントロール。続いてキー入力とカメラの移動。 


プロトタイプ カメラ移動・FPS表示 - YouTube


 SFML上で動いているものの、かなりの部分を自分で書かないと行けないので、すごく大変。こういう機能は必須だから既存の機能でできるんじゃない? と思って検索しても

「理論的にはこう実装してコードはこうあるべきだけど、そういうことを実現する機能は無いよ。自分で書いて」

みたいなフォーラムの回答ばかりでWeb界隈のライブラリを共有する習慣とは一線を画しているなあと感じる毎日です。一方、そういうものを自分で書くのは、今のところとても楽しくやっています。

 さて次こそキャラクターを歩かせるぞ。

プロトタイプ1

 プロトタイプ。というか、SFMLの動作テストとC++のプログラミングの実際、それからコーディングスタイルが落ち着くまで、将来コードを捨てるつもりで雑に書いていく何かを作成中。ゲームロジックなどはまだまだだいぶ先の話。

f:id:giraffyk1:20160917180959p:plain

 Hello World。文字表示するのもWebと違ってやっぱり大変。

 それ以上に、開発環境の準備、うまく動作するように調整したり、言語に慣れていないせいで調べ物をしたりにとても時間がかかっている。

 文字を書いている時間1:調査している時間20の比率くらい。これはしょうがないよね。

f:id:giraffyk1:20160917181323p:plain

 マップの描き出し。マップチップ1枚ずつ書くと処理が遅くなるらしい(SFML上で)、ということで後学の為に、遠回りして3D技術のポリゴンとかテクスチャとかで使われる「頂点配列」というのを使ってマップが表示できるようにした。平面に見えるポリゴンにマップチップをテクスチャにして貼り付けてる。見た目には変化無いがだいぶ負荷が減ったはず。

 難しい技術だけど中々面白かった。本当に難しい部分はフレームワークのSFMLやOpenGLあらかじめが実装してくれてるので、それと比べたら大したことないだろう。マップタイル画像はフリーのものをちょっと拝借した。

 同じ技術で線や図形も描けるので、デバッグ用にタイルに線を入れておいた。通し番号も表示できるようにしておきたい。

f:id:giraffyk1:20160917181949p:plain

 ここまででコード200行くらい。ここらへんまできて、ようやく調べる時間とコード書いてテストしている時間が3:1くらいになってきた。だいたいテスト…というかコンパイルが通るように書き直してる時間だけど。

 やっぱゲーム作るのって大変。

 次はFPS、処理レートの調整とキャラクターのお試し表示かな。