Javaビーム工房で学んだチーム開発の難しさ

by orekyuu 0 Comments

同じ学校のメンバーに声をかけて一緒に作っていたTwitterクライアントのα版がようやく出せた。
10月1日から始めたので大体3ヶ月くらい。まぁバグとか結構あったり未実装の部分もあるけどまぁ満足の行くところまでできたと思う。
チーム開発の経験はあまりないけど、3ヶ月ほどやってみて課題とかをまとめてみたいと思う。

今回のプロジェクトはgitとgradleを使った。
プロジェクト構成としては、JavaBeamStudioにJavaBeamStudioAPIとJavaBeamStudioAppの二つのサブプロジェクトがあるだけ。

プロジェクト開始時にgradleラッパーをプロジェクトに入れておくと、チームメンバーの環境が整えやすくて非常に良かった。
各自作業がしやすいようにEclipseかIntelliJの好きな方を使ってくれというスタンスだったが、今になってすごく後悔している。
というのも、コードのフォーマットがばらばらでタブでインデントする人が居たりしてひどいことになった。
最終的にαビルド前に全体にフォーマットかけることにしたが、rebaseするときに「あっ・・・(察し」となるのは目に見えている。

やっぱりIDEは統一させておいたほうがいいのかもしれない。
フォーマットの問題が解決すれば各自使いやすいものでいいと思うけど・・・(各自のモチベーションも上がるだろうし。

開発の流れは、週1回のスカイプ会議で各メンバーにタスクを割り振り、release-1.0.0から新規ブランチを作って完成すればプルリクエストを作成してマージする方法をとっているが、あまり効果が実感できていない。実際バグが大量に出ている。
もう少し厳しいチェックを通す方法を考えたいと思う。

JavaFX Advent Calendar25日目 ~ JavaFXで夢のCanvasライフ

by orekyuu 0 Comments

この記事はJavaFX Advent Calendar25日目の記事です。
前回はs_kozakeさんのAndroidでJavaFXを動かしてみたよ!でした。

みなさんCanvas使ってますか?
使ってない人は今日から夢のCanvasライフを始めませんか?

ところで今日はクリスマスですね!

クリスマスらしく、クリスマスツリーでも見ましょう!
クリスマスツリー

というわけで今回はCanvasを使ってクリスマスツリーを作った話です。

完成品をおいておくのでぜひ触ってください。クリックした所に赤いライト置けます。

Canvasの使い方ですが、かなり簡単です。

Canvas canvas = new Canvas(CanvasWidth, CanvasHeight)
GraphicsContext g = canvas.getGraphicsContext2D();

g.fillOval(x, y, width, height);//○書くよ

のようにGraphicsContextを使って描画していくだけです。

Appletとかに似てるなーと思っていたんですが、Java2D作ってた人がCanvas作っていたみたいですね。
そりゃ似ているわけだ。

ライトや雪が落ちたりするアニメーションはAnimationTimerを使います。

AnimationTimer animationTimer = new AnimationTimer() {

    @Override
    public void handle(long now) {
        GraphicsContext g = canvas.getGraphicsContext2D();
        g.clearRect(0, 0, CanvasWidth, CanvasHeight);
        //背景
        drawSky(g);
        //星を描く
        drawStar(g, now);
        //木を描く
        drawTree(g);
        //ライトを描く
        drawLight(g, now);
        //雪を描く
        drawSnow(g, now);
    }
};
animationTimer.start();

あとは説明するものも特に無いので、コードをgistにおいておきます。
https://gist.github.com/orekyuu/afb416d5c722edeeb79e

最終日はskrbさんです!よろしくお願いします!

ついに僕のコンパイラにデレ期が来た

by orekyuu 0 Comments

Javaビーム工房でJAXB使ってたら可愛いエラーメッセージに出くわした。

無題

確実にこれはデレ期でしょ!「1つで十分です。」って付け加える所が非常に可愛い。
コンパイラ「別に一つでいいんだよ///」的なものを感じてテンションあがった。

疲れてるのかな・・・おやすみなさい。

APTでModdingわいわい

by orekyuu 0 Comments

1.8のもぢんぐでは、アイテムの追加でjson書かないといけないみたい。
描画の設定を記述するんだけど、使い回しが聞かないのが辛い。
実際書いたjsonだけど、基本的にlayer0の値しか変わらない。
これだけのためにコピペしたりするの面倒じゃない?

{
  "parent": "builtin/generated",
  "textures": {
    "layer0": "sweetmod:items/green_candy_cane" ここしか変更しないのに!
  },
  "display": {
    "thirdperson": {
      "rotation": [0, 90, -35],
      "translation": [0, 1.25, -3.5],
      "scale": [0.85, 0.85, 0.85]
    },
    "firstperson": {
      "rotation": [0, -135, 25],
      "translation": [0, 4, 2],
      "scale": [1.7, 1.7, 1.7]
    }
  }
}

というわけでAnnotationProcessorを作ってみた。

方法については以下を参考にするとわかりやすいと思います。
「Java SE 6完全攻略」第94回 アノテーションを処理する その1
「Java SE 6完全攻略」第95回 アノテーションを処理する その2
「Java SE 6完全攻略」第96回 アノテーションを処理する その3
「Java SE 6完全攻略」第97回 アノテーションを処理する その4
「Java SE 6完全攻略」第98回 アノテーションを処理する その5
「Java SE 6完全攻略」第99回 アノテーションを処理する その6
「Java SE 6完全攻略」第100回 アノテーションを処理する その7

結果
アイテム生成はこんな感じになりました

@Languages({
    @Language(langType = LangType.EN_US, key = "item.RedCandyCane.name", name = "RedCandyCane"),
    @Language(langType = LangType.JA_JP, key = "item.RedCandyCane.name", name = "赤いキャンディーケイン")
})
@ItemModel(itemName = "RedCandyCane", textures = "sweetmod:items/red_candy_cane")
public static ItemCandyCane redCandyCane;

langファイルについても面倒なので一緒にAPTで処理できるようにしてみました。

コンパイルした時のファイルの出力先が/build/classes/main/の中になっていたので、コンパイルタスクが終わったら、ファイルを/out/production/{プロジェクト名}/にコピーするタスクをbuild.gradleに書いておしまい。

使ってみた感じかなり便利。AnnotationProcessorが入ったjarはMODのリポジトリのlibsフォルダに入っているので良かったら使ってみてください。

リポジトリ

おまけ
無題

JavaFX Advent Calendar9日目 StringConverterとBinding

by orekyuu 0 Comments

JavaFX Advent Calendar9日目の記事です。
8日目はHASUNUMA KenjiさんのJavaFX 8u40 のダイアログを探るでした。

  • StringConverterとは

Objectから文字列へ、文字列からObjectへ変換するためのものです。
javafx.util.converterパッケージにStringConverterのサブクラスが用意されています。

  • StringConverterって何に使うの

例えばスライダーの値をLabelのtextPropertyとバインドしたいとき、スライダーの値(double)からLabelのテキスト(String)に変換したい。
そんな時にStringConverterを使うと便利なんです!

  • 使ってみる

StringConverterを使ってバインドするためにはBindings#bindBidirectionalを使用します。
まずは基本的な使用方法として、第一引数にtextProperty、第二引数にバインドしたいProperty、第三引数に第二引数の型と同じStringConverterを使ってバインドしてみます。

//NumberStringConverterを使ってStringにConvertしてバインド
Bindings.bindBidirectional(sliderLabel.textProperty(), slider.valueProperty(), new NumberStringConverter());
//BooleanStringConverterで真偽値をStringにConvertしてバインド
Bindings.bindBidirectional(toggleButtonLabel.textProperty(), toggleButton.selectedProperty(), new BooleanStringConverter());

DatePickerのように、valueがLocalDateのようなjavafx.util.converterに用意されていない場合もあります。
一部のコントロールにはgetConverterメソッドでConverterを返してくれる場合があります。

//DatePickerが返すConverterを使ってバインド
Bindings.bindBidirectional(datePickerLabel.textProperty(), datePicker.valueProperty(), datePicker.getConverter());

上記2つに当てはまらない場合はStringConverterを自分で作成します。
textPropertyとColorPickerのvaluePropertyをバインドさせてみます。
StringConveerterの仮引数にはbindBidirectionalのvalueの型を指定します。
toString(T)ではTをどのような文字列で表示するかを処理します。
fromString(String)では文字列からTに変換する処理をします。

//独自にStringConverterを作る
        Bindings.bindBidirectional(colorPickerLabel.textProperty(), colorPicker.valueProperty(), new StringConverter<Color>() {
            //文字列への変換
            @Override
            public String toString(Color object) {
                double[] rgba = new double[]{object.getRed(), object.getGreen(), object.getBlue(), object.getOpacity()};
                return Arrays.stream(rgba)
                        .mapToObj(String::valueOf)
                        .collect(Collectors.joining(", "));
            }

            //Colorへの変換
            @Override
            public Color fromString(String string) {
                double[] color = Arrays.stream(string.split(", "))
                        .mapToDouble(Integer::parseInt)
                        .toArray();
                return new Color(color[0], color[1], color[2], color[3]);
            }
        });

無題

明日はtoruwestさんが面白い記事書いてくれると思います。