2013年1月19日土曜日

JavaFX入門

Pythonをやろうと思っていたはずが,JavaFXの勉強を始めていました.
今年も興味がうつろいやすそうです.「うつろわざるもの」になりたい.

JavaFXは,AWTやSwingのようなJavaのGUIフレームワークです.
ちょっとマルチプラットフォームでGUIのあるツールを作りたくなったため,触ってみました.

もっともシンプルなコード(Simple.java)はこんな感じ.
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Simple extends Application {
    public static void main(String [] args){
        launch(args);
    }

    public void start(Stage primaryStage) throws Exception {
        primaryStage.setScene(new Scene(new Group()));
        // Macでは幅と高さを指定しておかないとウィンドウが見えない
        // primaryStage.setWidth(100);
        // primaryStage.setHeight(100);
        primaryStage.show();
    }
}

で,これをコンパイルするためにはJavaFXのjarをクラスパスに追加する必要があります.
JavaFXはJava SE 7からは付いてきているようなので,最新版のJava SEを入れれば入っています.

Windows
Javaのインストールフォルダ\jre\lib\jfxrt.jar

Mac
`/usr/libexec/java_home`/jre/lib/jfxrt.jar

このパスをクラスパスに追加してJavaを実行すれば,ウィンドウが表示されます.

JavaFXでは,WPFのXAMLのようにFXMLというXMLでGUIを記述できます.
さらに,GUIをWYSIWYGエディタで作成できるJavaFX Scene Builderも提供されています.
上の例をFXML(Simple.fxml)で書くとこんな感じ.

<?xml version = "1.0"?>
<?import javafx.scene.Scene?>
<?import javafx.scene.Group?>
<Scene width = "100" height = "100">
  <Group />
</Scene>

上のコードと比較して何となく気付くかもしれませんが,オブジェクト間の関係と
XMLの入れ子関係が関連しているようです.
import文はXMLのProcessing Instructionとして指定するようです.

このFXMLのファイルを先ほどのクラスと同じ階層に置いて,
このファイルを使ってウィンドウを表示するコードは次のような感じに.

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Simple extends Application {
    public static void main(String [] args){
        launch(args);
    }

    public void start(Stage primaryStage) throws Exception {
        primaryStage.setScene(
            (Scene)FXMLoader.load(
                getClass().getResource("Simple.fxml")));
        // Macでは幅と高さを指定しておかないとウィンドウが見えない
        // primaryStage.setWidth(100);
        // primaryStage.setHeight(100);
        primaryStage.show();
    }
}

FXMLLoaderというのが提供されているわけです.
getClass().getResource("Simple.fxml")はこのクラスのある場所から指定した
リソース(この場合ファイル)のパスを取得してくれるメソッドのようです.

他にもCSSで見た目を変えられる機能もあるようなので,つい色々試したくなってきます.
目的のツールを作ることを忘れてしまいそう.

2013年1月12日土曜日

プログラミングとデザイン(設計ではない)

 UIデザイナーの方におすすめされて,ノンデザイナーズデザインブック,という
 本を買って読みました. 


 この本は,デザインの素人でもいくつかの原則を意識すればデザインは良くなる
 んですよ,ということを解説しています.その原則は,素人の自分でも確かに意
 識すれば分かる,という内容でした.その原則は次の4つです.

  • 近接
    • 関連のあるものは近くにまとめる
  • 整列
    • 右揃えや左揃えなど全体で揃える
  • コントラスト
    • 違いをはっきりとさせる
  • 反復
    • 全体で同じことを繰り返すことで,類似の情報を見つけやすくする

 相当ざっくりとまとめました.で,これを読んでいてふと思ったことがあり
 ます.読みやすいコードって,この原則が結構当てはまるのではないかと.

  • 近接
    • 関連のあるコードは近くにあると見つけやすい
  • 整列
    • インデントがある,揃っているコードは読みやすい
  • コントラスト
    • ちょっと思いつきません
  • 反復
    • コメントのスタイルが全体で同じ形を繰り返している

 こちらも結構ざくっ,としてますが,何が言いたいかと言うと,プログラマが
 何かしらのソースコードが美しいと言ってもプログラマ以外には理解されない,
 と良く言われますが,実は理解されるんじゃなかろうか,と思ったわけです.
 アーティストから見たデザイン的に良い文章(つまりコード)は,プログラマに
 とっても読みやすいコードで,プログラマにとって読みやすいコードとはアー
 ティスト的にデザインの良いコードなのでは無いか,と.

 後は,何かを以てコントラストが表せれば良いのですが.

2013年1月7日月曜日

2013年の抱負

新年明けましておめでとうございます.

基本的に熱しやすく冷めやすい性格なので,ブログも継続しない.というわけで,今年の目標は「継続」にしようと思います.

あと,巳年なのでPythonをやってみようかと.
単に言語としてのPythonを習得するだけでも良いのだけれど,ゲームプログラマとしては,Blenderとかのプラグインとか何か作れるようになると良いなぁ,と.

というわけで,Pythonの学習ネタでしばらくブログを書けたらな,と思う年明けでした.

部屋の片付けも継続しないとな・・・

2012年10月4日木曜日

「ゲームを動かす技術と発想」感想

堂前 嘉樹 著「ゲームを動かす技術と発想」を読みました.

読み終えて,自分がゲームプログラマになる前にこの本が出ていれば良かったのにな,と思いました.

自分のように大学出身のプログラマだと,専門学校生のようにゲームプログラミングについての知識が豊富なわけでも無いので,専門分野から少しでも外れると用語が分からなかったりします.

この本は,ゲームプログラマとしてやっていく上で必要な基礎を一通り解説していて,しかも,何故そうなっているのか,など理由をしっかりと説明してくれているため,手っ取り早く基礎を押さえるのに良いと思います.また,そういったことを教える際の参考にもなると思います.

ゲームプログラマにとってプログラムを書くのも重要ですが,デザイナに技術上の制限を理解してもらった上で色々と工夫をしてもらえるように,ちゃんと理解してもらえる説明をすることも重要だと思っています.

先日,デザイナの方からモーションを付けたらモデルの表示がおかしくなった,と相談を受けました.どうも頂点カラーが出ていないとのこと.しかし,自分は頂点カラーとモーションの関係が分からなかったため,先輩に聞きに行きました.
答えとしては,モーションが入っているとマテリアルが変わるから,頂点カラーが使えない,ということでした.
おそらく先輩にとっては常識だったのでしょうが,自分もデザイナの方もそんなことは知りません.何故モーションが入っているとマテリアルが変わるのか,聞いてみても違うからなぁ,というくらいしか答えは返ってこず,結局デザイナの方にはそのまま伝えることに.デザイナの方は,使えないなら仕方無いけどね,と渋々他の方法で表現してくれることに.

で,ちょうどこの本を読んでいたら,モーションが入ると頂点カラーが使えない,というよりも使わない理由が書いていました.おそらく,この本に書いてあるような説明ができていれば,デザイナの方も納得した上で仕事をしてもらえていたと思います.

他にも,自分の知識不足から不要な手間を取らせてしまうことが多々ありました.分かってはいるけど,デザイナの方に分かってもらうための言葉を知らなかったりもありました.

この本の前書きには,ゲームプログラマを目指す人,ゲームプログラマと接する機会の多い人向けの本です,ゲームプログラマとのコミュニケーションを円滑にするアイテムになって欲しい,と書かれています.
自分としては,特にゲームプログラマとのコミュニケーションを円滑にするアイテムとして,この本は素晴らしいと思います.

とりあえず,困ったときのために,会社の机に置いておこうと思います.

------------------------------------------------------------------------------------------------------------
著者の堂前さんが,少々はネタバレもOKということだったので,その辺も考慮して,この本の良い点を挙げておきます.

第1章は,本当に基本の基本.コンピュータがどうやって動いているのか,という内容で,さすがにプログラマならこのくらいは知っておきましょう,というレベルです.
でも,最近はメモリを意識しなくてもやっていけるので,メモリにプログラムを読み込む,というのを理解せずにプログラマになる人もいるのかも.

第2章は,メモリ管理周りの話です.据え置き機と携帯機ではメモリ容量の単位が違って驚いた話や,過去と現在を比較してのコラムが面白いです.昔はこんな努力までしていた,とか.実際に仕事でやってきた経験に基づいた内容,という感じでCD-ROMなどのディスク上でのデータの配置にまで気をつかう,などは読んでいて面白かったです.

第3章は,CPUとGPUについて.この章も,本当に仕事中にこういうのが必要だったんだろうな,というのが伝わってくる内容です.こうするとメモリは節約できるけど,デバッグは面倒になったよ,とか,こういう手順だと描画処理が間に合わないから1フレームずらして,とか.この章に限らず,全体的に図が多く,分かりやすいです.

第4章は,コンピュータ上での数値の表現方法と演算方法について.これは,プログラマであれば聞いたことがある内容ばかりでしょうが,それをプログラマ以外に説明する場合に,参考になると思います.図の書き方を参考にしたいです.

第5章は,3Dを扱う上では必須の行列やクォータニオンといった数学について.5.4までは他にも色々と詳しい本があるので,そちらを読んだ方が良いでしょう.で,5.5からが個人的には良いな,と思っているところで,数式上こうなるよ,とかこうすると解けるよ,という解説は色々ありますが,何故こうする必要があるのか,これだけ容量を食うんだよ,と言った現実の問題も絡めた上での説明はあまり見たことが無い気がします.
あと,最後のまとめの,数学に対する姿勢も個人的に好きです.

第6章は,アニメーションとかモーションについて.普通に考えるとパラパラアニメの各コマ毎に全てのデータを持っていれば良いけど,それだと必要なデータのサイズがこんなことに.でも工夫すると,徐々に減っていってこれだけで実現できるよ,という説明の仕方は,何故そんなことをするの,と言う部分が分かってとても良いです.
あと,IK(Inverse Kinematics)の説明や,骨格データなども知らなかったので参考になりました.

今日はこの辺で.

全体的に,技術書にありがちな文章とコードが多くて図があまり無い,とかではなく,色々と分かりやすい図が多くて読みやすい気がします.

2012年6月28日木曜日

LINQ to XMLと属性とnullと

最近,LINQ to XMLを使う機会が多い.で,こんな感じのコードを書く.

XDocument document = XDocument.load("foo.xml");
var elements = from e in document.Descendants("bar")
                        where e.Attribute("hoge").Value == "foobar"
                        select e;

すると,適当な属性が無い場合null参照で怒られる.で、こう書き換えていた.


XDocument document = XDocument.load("foo.xml");
var elements = from e in document.Descendants("bar")
                        where e.Attribute("hoge") != null && e.Attribute("hoge").Value == "foobar"
                        select e;

でもこれ冗長だなぁ、と思っていたわけで.調べてみると、文字列へのキャストをした方が良い感じ.

XDocument document = XDocument.load("foo.xml");
var elements = from e in document.Descendants("bar")
                        let hoge = (string)e.Attribute("hoge")
                        where hoge != null && hoge == "foobar"
                        select e;

で、ふと思ったのが、文字列型の変数がnullの場合,比較したら落ちるのかな,と.

string a = null;
string b = "hello";
if(a != b){
    Console.WriteLine("not same");
}

ちゃんと比較できるっぽいので,こうすればいちいちnullチェックいらないんじゃね,ということで

XDocument document = XDocument.load("foo.xml");
var elements = from e in document.Descendants("bar")
                        let hoge = (string)e.Attribute("hoge")
                        where hoge == "foobar"
                        select e;

と,ここにたどり着いた.

2012年6月21日木曜日

OpenGL事始め3

背景を塗りつぶしたら,次は点でも表示してみよう.

// main.cpp
#include <GLUT/glut.h>

void display();

int main(int argc, char * argv[])
{
    glutInit(&argc, argv);
    glutCreateWindow("");
    glutDisplayFunc(display);
    glClearColor(0.f, 0.f, 1.f, 1.f);
    glutMainLoop();

    return 0;
}

void display()
{
    glClear(GL_COLOR_BUFFER_BIT);

    // 点を描画
    glBegin(GL_POINTS);
    {
        glVertex2f(0.f, 0.f);
    }
    glEnd();
    glFlush();
}

glBegin(描画方法)からglEnd()の間に点を描画したい座標をglVertex2f()で指定してやると,点が描画される.この場合,中心に白い点が描画される.ただし,凄く小さくて分かりづらい.

そこで,少しサイズを大きくしてみる.サイズの指定は,glPointSize();

// main.cpp
#include <GLUT/glut.h>

void display();

int main(int argc, char * argv[])
{
    glutInit(&argc, argv);
    glutCreateWindow("");
    glutDisplayFunc(display);
    glClearColor(0.f, 0.f, 1.f, 1.f);
    glutMainLoop();

    return 0;
}

void display()
{
    glClear(GL_COLOR_BUFFER_BIT);

    // 点のサイズを指定
    glPointSize(32.f);
    glBegin(GL_POINTS);
    {
        glVertex2f(0.f, 0.f);
    }
    glEnd();
    glFlush();
}

四角くでかい点が出る.ちなみに,このglPointSizeの位置をBeginとEndの間に持ってきても上手く動かない.更に点に丸みを付けてみる.glEnableにGL_POINT_SMOOTHという引数を渡すだけ.

// main.cpp
#include <GLUT/glut.h>

void display();

int main(int argc, char * argv[])
{
    glutInit(&argc, argv);
    glutCreateWindow("");
    glutDisplayFunc(display);
    glClearColor(0.f, 0.f, 1.f, 1.f);
    glutMainLoop();

    return 0;
}

void display()
{
    glClear(GL_COLOR_BUFFER_BIT);

    glEnable(GL_POINT_SMOOTH);
    glPointSize(32.f);
    glBegin(GL_POINTS);
    {
        glVertex2f(0.f, 0.f);
    }
    glEnd();
    glFlush();
}

OpenGL事始め2

コードは書きつつも,アウトプットが無さ過ぎなのでちょっと書いておく.

OpenGL事始め1で書いたコードに追加する感じで.

背景を塗りつぶす
だいたいの入門書で取り合えず背景を特定の色で塗りつぶす方法が最初に紹介されている気がする.OpenGLだと,glClear関数を呼び出す.描画関係の処理はglutDisplayFunc()に渡した関数の中に書く.

// main.cpp
#include <GLUT/glut.h>

void display();

int main(int argc, char * argv[])
{
    glutInit(&argc, argv);
    glutCreateWindow("");
    glutDisplayFunc(display);
    glutMainLoop();

    return 0;
}

void display()
{
    // 色バッファを指定した色で埋める
    glClear(GL_COLOR_BUFFER_BIT);

    // 描画コマンド実行指示
    glFlush();
}

glClear関数は,いくつかのビットフラグになっている定数を指定することで,その定数で指定されたバッファの内容を指定された値で埋めてくれる.今回の場合,色が保存されているバッファを指定した色で埋めている.

最後のglFlush関数は呼び出しておかないと,描画が実行されなかったり.

glClearのデフォルト値は,RGBAで(0, 0, 0, 0)になっているので,何も指定しないと画面が黒になる.
色を指定する場合は,次のようにglClearColorにRGBAを指定する.

// main.cpp
#include <GLUT/glut.h>

void display();

int main(int argc, char * argv[])
{
    glutInit(&argc, argv);
    glutCreateWindow("");
    glutDisplayFunc(display);
    // 青色で塗りつぶすようにする
    glClearColor(0.f, 0.f, 1.f, 1.f);
    glutMainLoop();

    return 0;
}

void display()
{
    // 色バッファを指定した色で埋める
    glClear(GL_COLOR_BUFFER_BIT);

    // 描画コマンド実行指示
    glFlush();
}

R(赤),G(緑),B(青),A(アルファ)を0.0fから1.0fの範囲で指定する.

ちなみに,glClearColorの位置をglutCreateWindowの前にすると落ちる.