2016年2月18日木曜日

チヌかかり釣りMEGAの開発でやらなければよかった4つのこと

チヌかかり釣りMEGA(以下MEGA)を公開、運営しはじめてから来月で丸5年になる。また、公開時からホストサーバとして使用してきていたExpressWebがサービスを今年で終了するということで色々とこのプロジェクトの開発を振り返った際に「あぁこうすりゃよかったなぁ」と後悔したことをまとめておきたい。


1、Microsoftの技術は使うべきではなかった
誤解してもらいたくないのでひとまず断わっておくと私は.NET1.0からの.NET開発者である。仕事ではASP.NET, ASP.NET MVC, Windows Forms, Silverlight, WPF, SQL Server等々とどっぷりとMSの開発環境で経験を積んできている。その流れでMEGAの開発の話がビジネスパートナーとの間であがったときに自然とASP.NET MVCとSQL Serverを選択してしまった。しかし、この選択は今でもなんやかやと足をひっぱっている。主に費用面で。

そう、MSの製品を使うと高いのだ。

まずサーバは必然的にWindows Serverとなる。今なら.net coreとかあるのでLinuxでも動作させられるのだろうけど5年前にはそんなものは影も形もなかった。またSQL Serverは他のDBに比べて余計にお金がかかるし、仮に自前のサーバを建てたとしてもライセンス料もろもろが発生する。

私はMSの開発環境は大変好きなのだが、それが自分のビジネス(超小規模)に向いているとは言えない。MS製品は潤沢な資金を持っているお客さんを捕まえたときに使用するべきものだと思う。


2、一つの技術で作るべきだった
実はMEGAは色々な技術で構成されている。
  • メインのサイト
    ASP.NET MVC(C#)、SQL Server
  • 渡船店(余談だが渡船は「とせん」と読む)独自のホームページが更新されたかをチェックするチェッカー(Cron)
    Django nonrel、Google App Engine(Python)
  • 渡船店のホームページから釣果を抜き取ってくるCron on Ubuntu
    Node.js(Javascript)、Backbone.js、Mongodb
  • 独自広告設定用のサイト on Ubuntu
    Node.js(Javascript)、Backbone.js、Mongodb
  • ちぬあたりMEGA(ゲーム)
    CreateJS(Html版)、Android(Android版)
と、まとまりの無い状況になっている。なぜこうなったのか!?

なぜこうなったのか!というと、もうね、やっぱり初手でMSの技術を選択したってのが大きいと自分的には感じているのだけど、それ以上にその時々で流行りの技術に興味のおもむくままに手を出してきたってのが一番悪かったと思う。一応その技術を選択した背景にはそれなりの技術的な理由があるのだけれども、チェッカーを作ったころの2011~2012年あたりはNoSQLが流行りだしてたころで、「おっ、GAEなら無料でサイトもホストできんじゃん」という安易な考えを助長する状況だったのも悪く働いた。この記事を書くにあたって当時書いてたコードをざっと見てみたけど、もうね、ほんときれいさっぱりPythonとか忘れてるから。数年前にコード書くのに勉強して、数ヶ月だけ使って、それ以来使ってない言語とかSyntaxレベルで忘れるからね。仮にチェッカーを手直しする必要が出てももう無理だよ。むりぽ。

さらにチェッカーの開発環境が何だったかさえ定かではない。PC買い替えに伴い、日常的に使わない開発環境を構築しなかったために大和の主砲のロストテクノロジーばりにどうやって開発してたのかさえ分からない。どうすんのこれ状態だ。


3、流行りの技術に飛びつかない
2の続きなんだけど、カッティングエッジな技術とかが話題になっていると気になるし調べちゃうとどうしても使いたくなってくる。で、それで何かしら作っちゃう。でもね、これはほんと危険。まず開発環境が違うので時がたつと確実に環境構築方法を忘れる。環境が残っていればよいけどPCの買い替えなんかがあったら大変だ。でも必要に迫られて数年前に作ったものを修正しようとするとどうやって開発してたかを覚えていない。IDEは何だったのか、どうやってコンパイルしてたのか、Webサーバはどうやって起動させてたのか、などなど思い出すのに苦労する。試行錯誤しながら環境構築するのは面倒なのでモチベーションがあがらず時間もかかる。

サンドボックス的にお試しで最新技術をちょろっと触る分には良いと思うけど、何らかのプロジェクトの一部分にプログラミング言語やらプラットフォームが異なるものを混ぜ込ませるのは本当に避けた方が良い。

たとえば全文検索機能が必要になったときにSQL Serverをすでに使っているのならばFull Text Searchを検討するべきであって、Lucene.Netなどに特段の理由もなく浮気するのは後々面倒な事態に直面することが予想されるので避けるべきだ。


4、安定した技術を使うべき
Node.jsはライブラリも豊富で開発もやりやすかったのだけれども、保守の観点から考えると最悪である。私がNode.jsで開発しはじめたときのバージョンは0.6.9だった。その後、必要な機能の実装も終わり運用を開始し、一年後ぐらいに機能追加した際にNode.jsのバージョンを0.10.1だかに更新しようとしたところ失敗してしまった。なぜかというと、使用しているライブラリの大半がそのバージョンに対応していなかったからだ。

Node.jsのバージョンアップは使用しているライブラリが増えるほどに難しくなる。バージョンアップをすんなり成功させるのはほとんど無理じゃないかな。DLLヘルならぬnpmヘルだ。最新のNode.jsの環境では何らかの解決方法があるのかもしれないけど。

で、今現在のNode.jsの最新バージョンを調べたらv5.6とかになっている。私の環境とメジャーバージョンで5も違う!2~3年でバージョンが5もあがってんのかよ。なんじゃそりゃ。バージョンアップしようにも作り直しに近い形で手を入れないといけないので、とてもじゃないけどそんなことはできない。

このように若い技術は変遷が激しい。互換性を保ったまま移り変わっていくのは難しいので大抵新しいバージョンになるとインターフェースが変わっていたりして動かなくなる。しかもその変わり方が非常に激しい。その技術をメインで扱っているのならそれでもやっていけると思うけれど、つまみ食い的に手を出して、作った後はしばらく放置するような状況の場合は本当に負担になる。


まとめ
MEGAはビジネス的には全然成功していないのでそこらへんを念頭に置いて下記のまとめを読んでもらいたい。
  • お金のかかる技術は使うべきではない(例:MSの製品全般)。ただ、お金があるならこんなことを気にする必要はなし
  • Webフレームワーク、Database、Cron、他のなんらかの便利スクリプトなど、できるだけ同一のプログラミング言語、技術、プラットフォームでまとめる。同じIDEが使えると環境構築の手間も省けて楽
  • 保守を第一に考えて、安定した、こなれた技術を使う。移り変わりの激しい技術はメインで使うのでもきついのに、それがサブだったりしたら本当に大変
ある程度の経験のある開発者ならば言語、技術の違いなどは大した問題ではないのだけれど、プロジェクトの保守、運用を考えた場合に、とくに小さなチームや独りで開発している場合などは、それらの違いが大きな負担になる。これは無用の負荷なのでできるだけ避けるべきである。ヒソカが言うところの「メモリのムダ使い」というやつだ。そんな無用なところに気を使うのではなく、製品の品質向上、機能追加にこそリソースを割くべきである。

と、後悔はつきないけど、具体的にどういうテクノロジーをMEGAのために今後取捨選択したら良いかは今のところ何も思いつかない。

2015年9月2日水曜日

d3.jsでチャートを作る パイチャート

前回に引き続き今回もd3.jsでのチャートをまとめておく。今回はパイチャートについて。

前々回はこちら
d3.jsでチャートを作る ラインチャートとバーチャートを2つのy軸上に描画する
前回はこちら
d3.jsでチャートを作る ツールチップ



SFiddleはこちら

弧上に描画するためのarc()とパイ上に配置するためのpie()を用意する。それと配色用のcolor。
 var arc = d3.svg.arc()
              .innerRadius(50)
              .outerRadius(radius);
  var pie = d3.layout.pie()
              .value(function (d) { return d.sales; })
              .sort(null) // ソートはしない
              .startAngle(-Math.PI / 3) // -60度から
              .endAngle(Math.PI / 3);   // 60度まで
  var color = d3.scale.category10();

データをpie()にかませて配置用のデータへと変換する。
var container = svg.selectAll('g')
                      .data(pie(data))
                      .enter()
                      .append('g');

弧を描画する。
// 色をつけて弧を描画する
  container.append('path')
              .style("fill", function(d, i) { return color(i); })
              .attr('d', arc);

arc.centroid()を使用すると真ん中の座標が簡単に取得できる。
// 真ん中に文字を描画する
  container.append('text')
              .attr('class', 'label value')
              .attr('transform', function(d, i) {
                  return 'translate(' + arc.centroid(d) + ')';
              })
              .attr('text-anchor', 'middle')
              .text(function (d, i) { return d.value; });

弧の外側に文字を描画するには三角関数を使用して座標を算出する。またtext-anchorを角度によって変更している。
// 外側に文字を描画する
  container.append('text')
              .attr('class', 'label name')
              .attr('transform', function(d, i) {
                  // 弧の外側を取得。パイチャートでは90度(Math.PI/2)の位置が0度計算になっているので注意。それなのでxは-する。yはSVGだと向きが逆になるので+する
                  var labelR = radius + 20
                      , x = labelR * Math.cos((d.endAngle - d.startAngle) / 2  + d.startAngle - Math.PI/2)
                      , y = -labelR * Math.sin((d.endAngle - d.startAngle) / 2 + d.startAngle + Math.PI/2);
                  return 'translate(' + x + ','+ y + ')';
              })
              .attr("text-anchor", function(d) {
                  var angle = (d.endAngle + d.startAngle) / 2;
                  return 0 < angle && angle < Math.PI ? "start" : "end";
              })
              .style("fill", function(d, i) { return color(i); })
              .text(function(d, i) { return data[i].busho; });

d3.jsでチャートを作る ツールチップ

前回に引き続き今回もd3.jsでのチャートをまとめておく。今回はおもにツールチップ的なものについて。ツールチップ的な部分以外は前回のものとあまり大差ないため省略するので詳細は前回を参照してもらいたい。

前回はこちら
d3.jsでチャートを作る ラインチャートとバーチャートを2つのy軸上に描画する
次回はこちら
d3.jsでチャートを作る パイチャート



JSFiddleはこちら

X軸。今回はtimeを使用している。またrange()の指定は少しずらすために30からとなっている。
// x軸は日付。y軸にくっつけたくなかったので30からはじめている
  var x = d3.time.scale().nice()
              .domain(d3.extent(data, function (d) { return d.date; }))
              .range([30, width]);
  var yearMonthFormat = d3.time.format("%Y/%m");
  var xAxis = d3.svg.axis().scale(x)
                  .orient('bottom')
                  .tickFormat(yearMonthFormat);
  svg.append('g')
      .attr('class', 'x axis')
      .attr('transform', 'translate(0, ' + height + ')')
      .call(xAxis);

ツールチップ。
// ツールチップ
  var focus = svg.append('g')
          .attr('class', 'focus');
  focus.append('rect')
           .attr({ x: -10, y: -25, width: 105, height: 50 });
  // circle
  focus.append('circle')
          .attr('class', 'profit')
          .attr({ r: 5, cy: -15 });
  focus.append('circle')
          .attr('class', 'sales')
          .attr({ r: 5 });
  focus.append('circle')
          .attr('class', 'expense')
          .attr({ r: 5, cy: 15 });
  // text
  focus.append('text')
          .attr('class', 'profit')
          .style('text-anchor', 'end')
          .attr({ x: 90, y: -15, dy: '.35em' });
  focus.append('text')
          .attr('class', 'sales')
          .style('text-anchor', 'end')
          .attr({ x: 90, dy: '.35em' });
  focus.append('text')
          .attr('class', 'expense')
          .style('text-anchor', 'end')
          .attr({ x: 90, y: 15, dy: '.35em' });

オーバーレイとツールチップの表示場所の指定。チャート上のどこにマウスがあっても表示したいのでオーバーレイはチャート全体を覆っている。mousemove()の冒頭でマウスの現在座標からその位置よりも左側に位置するデータをbisector()で取得している。それだけだとマウスが二つのデータ間にある場合、必ず左側のものが選ばれてしまうのでマウスとデータ間の距離を比較してツールチップを表示するべきデータを取得している。このx.invert()の使用方法はtime()でしか使用できないので注意。ordinal(), linear()の場合(linear()は違うのかも。調査していないので不明)はデータの幅とrange()、マウスの座標から当該のデータを探し出す必要がある(詳細は下記参考を参照してもらいたい)。
// オーバーレイ
  svg.append('rect')
      .attr('class', 'overlay')
      .attr({ width: width, height: height })
      .on('mouseover', function () { focus.style('display', 'block'); })
      .on('mouseout', function () { focus.style('display', 'none'); })
      .on('mousemove', mousemove);

  var bisectDate = d3.bisector(function (d) { return d.date; }).left
      , formatValue = d3.format(",.2f")
      , formatCurrency = function (d) { return formatValue(d) + '億円'; };
  function mousemove() {
      var x0 = x.invert(d3.mouse(this)[0])
          , i = bisectDate(data, x0, 1);
      if (i < data.length) {
          var d0 = data[i - 1],
              d1 = data[i],
              d = x0 - d0.date > d1.date - x0 ? d1 : d0; // 一番近いデータを取得
          focus.attr('transform', 'translate(' + (x(d.date)) + ',' + y(d.sales) + ')');
          focus.select('text.profit').text(formatCurrency(d.profit));
          focus.select('text.sales').text(formatCurrency(d.sales));
          focus.select('text.expense').text(formatCurrency(d.sales - d.profit));
      }
  }

参考
Inversion with ordinal scale

d3.jsでチャートを作る ラインチャートとバーチャートを2つのy軸上に描画する

d3.js周りを調査して、簡易なチャートをいくつか作ったので後々のためにまとめておく。今回は2つのy軸上にラインチャートとバーチャートをプロットする。

他のチャートはこちら
d3.jsでチャートを作る ツールチップ
d3.jsでチャートを作る パイチャート



JSFiddleに動作するサンプルをあげてあるので詳細はそちらを参考にしてもらいたいが、簡単に解説しておく。なおd3.jsはdata, enterの仕組みが理解できていないと一見しても意味不明なコードになるのでチュートリアル的なものをどこかで一読されることをお勧めする。

JSFiddleはこちら

データを用意する。
var data = [
      { name:'Branch A', sales: 5400, forecast: 7000 },
      { name:'Branch B', sales: 2800, forecast: 4500 },
      { name:'Branch C', sales: 3600, forecast: 3300 },
      { name:'Branch D', sales: 1700, forecast: 4700 },
      { name:'Branch E', sales: 2200, forecast: 5500 }
  ];

svg要素を用意する。
var margin = { top: 50, right: 100, bottom: 40, left: 40 }
      , width = 800 - margin.left - margin.right
      , height = 300 - margin.top - margin.bottom
      , svg = d3.select('#item-container').append('div').append('svg')
                  .attr('width', width + margin.left + margin.right)
                  .attr('height', height + margin.top + margin.bottom)
                  .append('g')
                  .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

X軸。ここでscaleにはordinal()を使用している。他に線形のlinear()と時系列用のtime()が使用できる。
// x軸は文字列なのでordinalにするのとrangeRoundPointsでちょうど良い場所を取得する
  var x = d3.scale.ordinal()
              .domain(data.map(function (d) { return d.name; }))
              .rangeRoundPoints([0, width], 0.5);
  var xAxis = d3.svg.axis().scale(x)
                  .orient('bottom');
  svg.append('g')
      .attr('class', 'x axis')
      .attr('transform', 'translate(0, ' + height + ')')
      .call(xAxis);

   // x軸のTickの文字を斜めにする
   svg.selectAll(".x text")
        .attr("transform", function (d) {
            return "translate(" + this.getBBox().height * -2 + "," + this.getBBox().height + ")rotate(-45)";
        });

一つ目のY軸。domain()に0から売り上げと予想の最大値を指定している。またnice()でよさげにtickを調整してもらう。range()がheightから0になっているのはSVGの(0, 0)は左上をさすため。
// 一つ目のy軸。売り上げと予想から最大値を取得する
  var y = d3.scale.linear().nice()
              .domain([0, d3.max(data, function (d) { return Math.max(d.sales, d.forecast); })])
              .range([height, 0]);
  var yAxis = d3.svg.axis().scale(y)
              .orient('left')
              .ticks(5);
  var gy = svg.append('g')
      .attr('class', 'y axis')
      .call(yAxis);
  // テキストを表示する
  gy.append('text')
      .attr('transform', 'rotate(-90)')
      .attr('y', 16)
      .style('text-anchor', 'end')
      .text('万円');

二つ目のY軸。右端にtransform.translateで移動する。また横線を引くためにd3が追加してくれたtickのg要素があるのでそこに横線用のline要素を追加して描画している。
// 二つ目のy軸。売り上げと予想の割合を表示する
  var y2 = d3.scale.linear().nice()
              .domain([0, 150])
              .range([height, 0]);
  var yAxis2 = d3.svg.axis().scale(y2)
              .orient('right');
  var gy2 = svg.append('g')
      .attr('transform', 'translate(' + width + ',0)')
      .attr('class', 'y2 axis')
      .call(yAxis2);
  // 横線を描画する
  gy2.selectAll('g').filter(function(d) { return d; })
      .append('line')
      .attr('x1', -width)
      .attr('x2', 0)
      .classed('minor', true);
  // テキストを表示する
  gy2.append('text')
      .attr('transform', 'rotate(-90)')
      .attr('y', -10)
      .style('text-anchor', 'end')
      .text('%');

ラインチャート。二つ目のY軸で高さを算出している。
// ラインチャート。売り上げと予想の割合を表示する
  var linePlaceHolder = svg.append('g');
  var percentLine = d3.svg.line()
              .x(function (d) { return x(d.name); })
              .y(function (d) { return y2((d.sales / d.forecast) * 100); });
  linePlaceHolder.append("path")
                  .datum(data)
                  .attr("class", "line percent")
                  .attr("d", percentLine);

バーチャート。一つ目のY軸で高さを算出している。またX軸のscaleでrangeRoundPoints()を指定しているおかげでちょうど良い感じの座標が取得できている。ここらへんは色々いじってためしてもらいたい。
// バーチャート。売り上げと予想を表示する
  // bars
  var bar = svg.selectAll('.bar')
      .data(data)
      .enter()
      .append('g')
      .attr('class', 'bar')
      .attr('transform', function(d) { return 'translate(' + (x.rangeBand() / 2 + x(d.name)) + ',0)'; });

  // 売り上げ
  bar.append('rect')
      .attr('class', 'sales')
      .attr('x', -10)
      .attr('y', function (d) { return y(d.sales); })
      .attr('height', function (d) { return height - y(d.sales); })
      .attr('width', 10);

  // 予想
  bar.append('rect')
      .attr('class', 'forecast')
      .attr('y', function (d) { return y(d.forecast); })
      .attr('height', function (d) { return height - y(d.forecast); })
      .attr('width', 10);

2015年3月12日木曜日

libgdxで2つ目のゲームを作ったので宣伝

スマホ用のゲームを作りました。

・作ったゲーム
スーパーホッケー

Get it on Google Play


・感想(ゲーム開発全般)
昨年中にこのゲームはリリースする予定だったのが、やる気の低下やらDragon Age Inquisitionやら、さらに延期したMy締め切りである一月中という目標も低下したやる気ではかなわず、結局Android版ができたのは二月末。毎月簡単なゲームをポンポンリリースしていこうかと思っていたけど、いやー、大変すわ、これは。おもにやる気の部分で。結局このゲーム用に凝ったものを作る気持ちが出てこなかったのでスーパーバレーボールから画像を流用しまくってお茶を濁すことに。なんだろ、多分これ作っても見返りほとんど無いしなぁ、って思いがゲーム作りたいって気持ちより強くなっちゃってやる気がでてこなかったんだろうな。次回はもっと新しいことにチャレンジしよう。じゃないと面白くないね。

・感想(libgdx周り)
libgdxでの開発は大分なれた。次回はfontやらsoundあたりをしっかりと組み込んでみようかな、と思案中。

2015年2月19日木曜日

.NETプログラム実行時にDLLの参照エラーになったときようのツール

実行時にDLLが見つからずにエラーになるのはままあることで原因を特定するのはさほど難しくないけれど面倒な作業である。とくにライブラリで参照しているDLLと呼び出し元のプロジェクトで参照しているDLLに差が出ることは、Nugetでパッケージを取得することが増えた昨今はよく起こる。

ということが今の職場でよく起きてそれを調べる用のツールを作ったので公開する。

Missing Reference Finder
https://github.com/yooontheearth/missing-reference-finder



使い方はいたって簡単。Pathにbin等のフォルダを指定してcheckボタンを押下するだけ。指定のフォルダかGACにないものはMISSING扱いになる。

2014年9月28日日曜日

libgdxでスマホ用のゲームを作っての感想

今年に入ってからの仕事で調べた物を社内のWikiにまとめるという作業がとても多いのでこちらのブログに書くモチベーションがまったくあがらず放置しまくっていたけれど久しぶりに仕事とは離れたネタができたので更新。

前々から何らかのゲームを作りたいなとAndroid用にAndEngineをいじくってみたりHtml5用にEaselJSで遊んでみたりしてみたけどどうにもしっくりこない。そんなこんなで月日は流れたけれど今年の夏に一念発起して二ヶ月に一本ぐらいのペースでゲームをリリースしていこうと決めた。

で、八月の頭からゲーム開発を余暇を使ってしてきたんだけど先ほどつつがなく一本目のリリース(2014/11/06につつがなくApp Storeへのリリースも完了)が終わったので宣伝やら何やらも兼ねて楽しかったり大変だったりしたことをまとめたのが以下。今回は主に開発環境周りで。

・作ったゲーム
宣伝です。

Get it on Google Play



余談:「バレーボール ゲーム」で調べたらあんまり出てこなかったので油断して「Slime Volleyball」って名前にして作ってたらまんま同名の10万回ぐらいダウンロードされてるタイトルがあって内容も似てたのでとりあえず「Super Volleyball」にしてお茶を濁す。


・フレームワーク
libgdx
AndEngineとかEaselJSをいじってみて思ったんだけど同じ製品をAndroid用、Html用、iOS用とか作り分けるのはやっぱりめんどい。他プラットフォーム用に製品を作るのはロジック部分とかほぼほぼ転用できるので開発は思いのほか楽なんだけどそれでもメンテナンスを考えるとめちゃめんどい。リソースが自分ひとりで開発からグラフィック、リリースとかまで全部やるのにこれはかなりの重労働になるのでうまいこと他プラットフォーム用のコードを生成してくれるフレームワークがないかなぁと思っていて見つけたのがこれ。

Unityも考えたけどlibgdxはフリーだし必要そうな機能も満たしてたのでこちらへ。javaで開発できるのもいいね。C#でもできるっぽいけどC++とか今更触りたくないよ。

・libgdxの感想
さくさく開発できた。libgdxはビルドをGradleに任せてるんだけどそのお陰か私のメインIDEであるIntelliJ Ideaでのセットアップもすぐに完了し即コーディングに入れたのはベリーグッド。グッジョブだ。Box2dとかも初期設定で参照するようにできるし簡単だった。ただねGradleのことが良く分かってなかった(今現在もポワポワしてる)ので何らかのサードパーティのライブラリを追加するのは結構骨が折れたしこれからも骨が折れそう。

・コーディング周りの感想
scene2dという形でScreen、Actor、Actionとか画面の要素をうまいことまとめて使えるようにしてくれてるけどまだ自分の中でしっくりきてないしまだまだこなれてない。それなので模索しながら開発しつつ今現在もまだモヤモヤしたまま。けれど可能性は十分あると感じた。やっぱController的なレイヤーをしっかりと作ってView的な要素ともっと明確にわけたほうがスコアとか画面のステートとかがごちゃごちゃせずにすっきりするだろうなという感じ。

・フォント
これは今もってどうしたほうが良いのか謎。今回みたいにほとんどテキスト表示するものが無いものはあんまりこだわる必要もなくデフォルトのを使えばよいかなぁと思った。ちょっと凝った部分は画像を文字として使うことになるし。多言語化とか考えたら文字を画像にするのとかご法度だろうけど。

・ツール類
Texture Packerの存在を途中まで認識しておらず最初のころは自前で複数の画像を一枚の画像につめてその画像内の座標を指定して表示用に抜き取ったりという狂気の沙汰を続けていたのだけれどTexture Packerさんにご足労いただいてからはその自死一歩手前から引き返すことができた。とても便利。

さらにPhysics Body Editorなるめちゃんこ優秀なツールもあるのでBox2dを使う方は目を通されるとよいかと。

あとは2D Particle Editorとかもある。未使用なのでまだいまいち把握していないけれどエフェクトを派手にするためにも次のゲームでは使ってみようと考えている。

・マネタイズ
libgdxを選んだ理由にAdMobとかとの統合のチュートリアルがちゃんとあるというのも大きなウェートを占める。少し苦労したけれど無事にAdMobを実装し広告が出せるようになった。いずれはiOS版も出そうとは考えているけれどそっちはまだあまり調べていないので少し謎だけど一応問題なくできそう。

・グラフィック
Ink Scapeを使用。グラフィックの勉強をちゃんとしたこともないしPhotoShopで適当に画像をいじったりとかしかしたことなかったけれどInk Scapeは優秀なのでネットに転がってるチュートリアルを参考にいくつかサンプルを作ったりしてたら大分慣れてきてほぼほぼ満足いくキャラとか背景とかが作れた。まだ隠された機能がたくさんあるようなので精進あるのみ。非常に使いやすいのでお勧め。フリーだし。

・サウンド
なし。スマホゲームでサウンドはいらんかなと思ったのでばっさりと。サウンドやらBGMの作り方とかまったくの門外漢なので。今後も予定無し。

・iOS
Androidアプリは今までもいくつか作ったことがあったので勝手が分かってたけどiOSのほうは全然分からないので現在勉強中。アイコンとかでさえどっから手をつければよいのかがまったく分からん。iAdを組み込むならなおさら。
下記に追記。


まとめ
専門学校以来10数年ぶりのゲーム作成で面白かった。libgdxはさくさく作れるので良い。動作テストもDesktopのプロジェクトを含めておけばPCですぐに確認できるし。これがAndroidのEmulatorだけだったら遅すぎて発狂すると思う。



追記 2014/11/07
App Reviewが昨日承認されて晴れてApp Storeにリリースできた。iOSアプリを作ったことがなかったのに加えてlibgdxでiOS版をリリースするチュートリアルがEclipseメインで書かれているものが多くIntellij ideaを使ってのリリースはかなり大変だった。またAppleのチュートリアルもXCodeを使って開発することを想定してのものなので、libgdx+intelij ideaというiOSアプリ開発環境的に邪道感満載の環境で手動設定するべき値がどれなのかを調べるのには骨が折れた。iAdのほうがマネタイズ的にAdMobよりも断然おいしいという比較記事を読んでいたのでiAdを組み込みたかったのだけれどそこにたどり着くまでにかなり試行錯誤を繰り返しすぎて発狂しそうだったのでそこはすっぱりとあきらめてrobovm-ios-bindings/admobでさくりと実装した。それとApp Reviewはなんやかんやとやっぱり時間を食う。それでもSubmitしてから一週間ということを考えれば早いほうなのかな、と。

いずれAdMobの組み込み方とか、iOS版のリリース方法とかまとめたいと考えているけれどとりあえず年内にもう一本簡単なゲームをリリースしたいのでそれが終わってから気が向いたら書くかも。