2013年3月31日日曜日

ゲームプログラマとしての二年目のまとめ

去年も書いたので今年もまとめておこうと思います.

今年度の仕事
今年度は去年から引き続き同じチームで開発をしていました.

キャラクターのモーションの制御システムや,サウンドシステムをチーム向けにカスタマイズしたりしてました.
規模が小さめなのもあって一人で全キャラクターのリソース管理もしていて,なかなかに大変でした.
サウンドシステムは用語も分からなかったりで色々と大変でした.周りにサウンドシステムを担当した人もいなかったので,自分で調べるしかなかったのですが,それはそれで良い勉強になりました.

今年度多用した言葉
今年度多用した言葉から,今年度を振り返ってみます.

「具体的に何がしたいんですか?」
「こういうことができないか?」と言った質問が来ることがあります.可能かどうかだけ答えても良いのですが,この一言を言っておくだけで色々と違ってきます.聞いてみたら,既にある機能を組み合わせれば出来ることだったり,逆にやらせないためにわざと出来ないようにしていることを迂回するための方法として質問してきていたりします.具体的な話が分かると,取れる対処法も違ってくるので,この言葉は今後も言い続けることになりそうです.

「いつまでに必要ですか?」
余裕のあるときは「あっ,やっておきますよ」で済むんですが,余裕が無くなってくるとそうも言ってられません.早めに必要なのか,そうでも無いのか,スケジュールを告げない人はベテランであってもいます.仕事の優先順位を決める上でも重要な情報なので,今後も使う機会は増えていくと思います.

「もっとシンプルに」
短い期間でしたが,後輩の面倒を見ることになりました.その際,プログラムを見て気付くと何度も言っていたのがこの言葉です.どうも最初からアレやコレやと色々な条件を考えすぎていたので,まずはシンプルな条件で動くコードを書いてみるように言っていました.経験が少ない状態で色々考えても抜けや漏れが出るものです.まずは分かる範囲でシンプルなものを作ってみる.作る過程で色々問題があれば,それを検討して設計に手を加える,ということが大事だと思います.時間が無いならともかく,十分な時間があるのであれば,まずは作ってみるのも重要だと思います.

あと,個人的にシンプルなAPIを上手く組み合わせて何かを実現する方が好きなので,APIはシンプルな方が好きです.

直接話すことは大事
今年度も感じたのは,直接話すことが大事ということです.直接話してみたらすんなり解決した,なんてことは良くあることです.あと,話をしていると色々な用語が出てきて,知らなければそれを調べて,で勉強にもなります.この作業が面倒だ,という雑談から,じゃあそれを楽にできるようにしましょうか,と需要を見つけることもあります.

普段から話していると,色々と相談もしてもらいやすくなるので,そこから自分の知識や経験につながったり,仕事につながったりします.雑談も重要なのです.
特にプログラマ以外との会話が大事です。プログラマにとっては当たり前のことも,プログラマ以外にとっては違ったり,逆もあり得ますから。

相手の分かる言葉で説明する
プログラマ以外の人から良く言われるのが,プログラマの説明は分かりにくい,ということです.難しい言葉や意味の分からない横文字を使おうとするからのようです.
ベテランの人たちが言うのだから,社内でもデザイナが分かるように説明してくれるプログラマは少ないのでしょう.ちゃんと相手の分かる言葉で説明しようとしていると,相手も聞きやすくなって,色々と質問してくれるようになります.質問が来るようになると,それを解決するために色々と知識や技術が身に付いていきます.

ベテランが正しいと思うな
十年以上のベテランでも間違えることはあります.こちらからアプローチしないと動かない人もいます.伝えるべき情報が分かっていない人だっています.ダメな人には言わないと分からないんです.こちらで何とかしてしまうのではなく,ちゃんと言ってあげるのも相手のためだ,と思いました.特にここ最近.

Vim
今年度もVimは大活躍してくれました.Vimが無ければ作業効率は10分の1にまで落ち込んでいたことでしょう.需要があると色々と覚えるもので,今年度はテキストオブジェクトとVimFilerを特に活用しました.

Shougoさんのプラグインはもちろん活躍しています.

Jenkins
CIのツールというよりも,自動ビルドシステムにWebインターフェースを付けるのによさそうだったので使ってみたのですが,他にも色々とできそうです.気付くと社内の他の場所でも使うようになっていて,何故か関連ミーティングに出席することになったり,と付き合いは長くなりそうです.

今年度気に入った本
ノンデザイナーズデザインブック
UIデザイナの方に紹介してもらった本です.情報を上手く伝えるために,文章をどう配置したりするか,といった部分がプログラムを如何に読みやすく書くかに通じる部分がある気がします.また,上手く情報を伝えるための資料を書く際にも役立つ気がします.
ノンデザイナーズデザインブックを読み解く
というスライドも参考になります.

ゲームを動かす技術と発想
この本はゲームを作る上で必要な基本的な説明が載っています.この本が他と違うなと思ったのが,プログラマ向けの本ではないということです.実際,うちでもデザイナーがこの本を読んでたりします.プログラマはつい専門的な用語で説明してしまいがちですが,非プログラマでも分かる言葉で説明する努力は大事だと思います.

Web Audio API
Web Audio APIの本ですが,Web Audio API自体が昔ながらのサウンドシステムのモデルに基づいているらしく,自分が今利用しているサウンドシステムを理解する上でも役立ちそうな感じです.サウンドシステムで利用される用語なども理論や定義などが解説されていて,サウンドシステムを作るのではなく利用する側になった場合に色々と役立ちます.もっと早くにこの本に出会えていたらな,と思います.サウンドデータを扱う本は多々あれど,サウンドシステムについて書かれた本は珍しい気がします.

最後に
今年度は開発の後半に突入したこともあり忙しかったですが,それでもとても楽しい日々を過ごせました.デザイナやサウンドとの関わりから色々な知識や経験を得られ,興味の幅を広げることも出来,本当に良い一年でした.
プログラマ以外と話すことは苦手でしたが,やはり話すことは大事だな,と思った一年でもあったので,今後も「話すこと」をしっかりとしていこうと思います.

来年度は社会人3年目として新人の面倒を見ることもあり,「話すこと」はますます重要になりそうです.

ゲームプログラマとしてのまとめなのに,ゲームプログラミングに関する話がほとんど無いなぁ,と思わないでもないですが,実際仕事をしていてゲームプログラミングが特殊なことをしているわけでもないので,よっぽど特殊な部分を担当しない限りは,仕事の仕方とかについて思うことの方が増えますね.

2013年3月14日木曜日

clang::Preprocessorで字句解析をするまで

clangを使ってC++のコードについてのメトリクスを取得したりするためのツールが作れないか,と思って手を出してみたものの,まず字句解析するだけでも一苦労だった.とりあえず色々調べてみた結果,まずはプリプロセッサを作るところかららしいので,clangのDoxygenのドキュメントを参考にプリプロセッサオブジェクトを作ってみた.

環境は,Mac Book AirのMountain Lionで.

// main.cpp
#include 
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Basic/DiagnosticIDs.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/FileSystemOptions.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/Token.h"

using namespace std;

int main(int argc, char * argv[])
{
    clang::DiagnosticIDs * diagnosticIds =
        new clang::DiagnosticIDs;
    clang::DiagnosticOptions * diagnosticOptions =
        new clang::DiagnosticOptions;
    clang::IgnoringDiagConsumer * diagnosticConsumer =
       new clang::IgnoringDiagConsumer;

    clang::DiagnosticsEngine diagnosticsEngine(
        diagnosticIds,
        diagnosticOptions,
        diagnosticConsumer
    );
    clang::LangOptions langOptions;
    clang::TargetOptions targetOptions;
    targetOptions.Triple = LLVM_DEFAULT_TARGET_TRIPLE;
    clang::TargetInfo * targetInfo = 
        clang::TargetInfo::CreateTargetInfo(
           diagnosticsEngine,
           &targetOptions
        );

    clang::FileSystemOptions fileSystemOptions;
    clang::FileManager fileManager(fileSystemOptions);
    clang::SourceManager sourceManager(
        diagnosticsEngine,
        fileManager
    );

    clang::HeaderSearchOptions * headerSearchOptions =
        new clang::HeaderSearchOptions;
    clang::HeaderSearch headerSearch(
        headerSearchOptions,
        fileManager,
        diagnosticsEngine,
        langOptions,
        targetInfo
    );

    clang::CompilerInstance compilerInstance;

    clang::PreprocessorOptions * preprocessorOptions =
        new clang::PreprocessorOptions;
    clang::Preprocessor preprocessor(
        preprocessorOptions,
        diagnosticsEngine,
        langOptions,
        targetInfo,
        sourceManager,
        headerSearch,
        compilerInstance
    );

    clang::FileEntry const * pFileEntry =
        fileManager.getFile("input.c");
    clang::FileID fileID = 
        sourceManager.createMainFileID(pFileEntry);
    preprocessor.EnterMainSourceFile();

    clang::Token token;
    do {
        preprocessor.Lex(token);

        if(diagnosticsEngine.hasErrorOccurred())
            break;

        preprocessor.DumpToken(token);
        std::cout << std::endl;
    } while(token.isNot(clang::tok::eof));

    return 0;
}


入力のinput.cはこんな感じ.
main()
{
}

Makefileはこんな感じ.結構色々リンクする必要がある.llvm関連については,llvm-configで簡単に設定できる.
# Makefile
main: main.cpp
 clang++ `llvm-config --cxxflags --ldflags --libs` $^ -o $@ -lclangBasic -lclangFrontend -lclangAST -lclangLex -lclangSerialization -lclangSema -lclangDriver -lclangEdit -lclangAnalysis -lclangParse

出力はこんな感じに.
identifier 'main'
l_paren '('
r_paren ')'
l_brace '{'
r_brace '}'
eof ''

コードの説明も書いておこうかと思ったけど力尽きた.
気が向いたらそのうち書こう.

2013年3月6日水曜日

コメントを自動挿入せずに改行する方法

Vimでプログラムを書いていて,単行コメントを何行か入れた後で次の行ではコメントにせずにしたい,
と思ったときにどうすれば良いのか,自動挿入をキャンセルする方法が無いのかな,と思ったけれど,
特にそれらしいオプションが見つからなかったので,適当にキーマップしてみた.

inoremap  :call append('.', repeat(' ', indent('.')))ji

Ctrlを押しながら改行すると,適当なインデント分の空白を入れて次の行から開始できる,という風にしてみた.