2013年5月27日月曜日

自作ライブラリ-SurfaceViewで表示するボタン

SurfaceViewでボタンを使いたくなった場合、FrameLayoutあたりを使ってButtonを重ね表示して、onClickイベントで処理するということもできますが、自前でSurfaceViewに描画するButtonクラスを作っておくと、いろいろと柔軟に対応できて捗ります。
まず対応する状態に応じた画像を準備します。

Buttonクラスはこんな感じで、状態とそれに応じたImageを持っていて描画メソッドでは状態に応じて画像を描画します。
public class CvsButton {
  public Paint paint = new Paint();
  public boolean enabled = true;
  public boolean pressed = false;
  public boolean visible = true;
  public Bitmap defaultImage;
  public Bitmap pressedImage;
  public Bitmap disenableImage;
  public Rect rect;

  public CvsButton() {}

  public CvsButton(Resources resouce, int defaultId, int pressedId, int disenableId, Rect size) {
    defaultImage = BitmapFactory.decodeResource(resouce, defaultId);
    pressedImage = BitmapFactory.decodeResource(resouce, pressedId);
    disenableImage = BitmapFactory.decodeResource(resouce, disenableId);
    rect = size;
  }

  public void draw(Canvas canvas) {
    if (enabled) {
      if (pressed) {
        canvas.drawBitmap(pressedImage, rect, rect, paint);
      } else {
        canvas.drawBitmap(defaultImage, rect, rect, paint);
      }
    } else {
      canvas.drawBitmap(disenableImage, rect, rect, paint);
    }
  }
}
このクラスをSparseArrayかHashMapあたりに突っ込んで、SurfaceViewのonTouchEventで座標をisPressに流してボタンのイベント処理、描画スレッドでdrawメソッドを呼んでボタンの描画処理を行います。

  public static final int BUTTON_A = 1;
  public static final int BUTTON_B = 2;

  private SparseArray<CvsButton> items = new SparseArray<CvsButton>();

  public void init() {
    items.put(BUTTON_A, new CvsButton());
    items.put(BUTTON_B, new CvsButton());
  }

  public int isPress(int x, int y) {
    int ret = -1;
    for (int i = 0; i < items.size(); i++) {
      if (items.valueAt(i).rect.contains(x, y) && items.valueAt(i).visible && items.valueAt(i).enabled) {
        items.valueAt(i).pressed = true;
        ret = items.keyAt(i);
        break;
      }
    }
    return ret;
  }

  public void draw(Canvas canvas) {
    for (int i = 0; i < items.size(); i++) {
      if (items.valueAt(i).visible) { items.valueAt(i).draw(canvas);}
    }
  }

一度作っておけば、使いやすいよう改変したりしていろんなところで使えるので大変お勧めです。

2013年5月22日水曜日

ついにキタコレ!Unityモバイル向け機能を完全無償化

Unity, iOS と Android を含む個人・小規模開発者向けのモバイル向け機能を完全無償化
http://japan.unity3d.com/blog/press/?p=408&preview=true

Unityとはユニティ・テクノロジーズが開発している統合開発環境をもったゲームエンジンで、多様なプラットフォームに対応している。
有名どころではけり姫クエストなんかにも採用されています。

去年の4月ごろ期間限定の無料キャンペーンをやっていたUnityですが、この時ゲットし損ねたのを悔やんで悶々としておりました。

それがついに!完全無償化とはいやはや太っ腹です。これで今までやっていなかった3Dを駆使したアプリなんかにも挑戦してみたいですね。

2013年5月20日月曜日

Androidでのオンラインランキングのど本命「Google Play game services」

アプリにオンラインランキング、実績サービスを組み込むことが出来る「Google Play game services」が発表されました。
ランキングと実績に加えてユーザー同士をマッチングする、マルチプレイの機能も用意とのこと。

以前オンラインランキングを考えていて、自分でサーバーを用意するかサービスとして提供しているものを利用するか検討したことがありました。その時出てきたのは大体こんなところ。

hamon夫婦で交換日記: OpenFeintの代わりに使えそうなサービス一覧
OpenFeintというのはモバイルゲーム向けのプラットフォームでオンラインランキングやソーシャル的な要素を組み込むためのサービス。
2010年時点で1000万ユーザーを獲得していましたが、2012年末にGREEに買収されてしまいました。

http://pankia.com/
パンキアは目標を達成することでトロフィーを集める「アチーブメント」、スコアを投稿してランキングをつける「リーダーボード」等を提供しているプラットフォーム。
ネットワーク対戦を実装するための簡単なインターフェースもあります。

上記のサービス利用にはユーザーのアカウント登録が必要なのが多かったりして、結局どれもまだ利用していませんでしたが、今回Googleからこのようなサービスが出るとなれば利用しない手はないかもしれません。

2013年5月16日木曜日

SurfaceViewでの複数解像度に対応した画面設計

Androidでは多様な端末が存在しており、解像度も縦横比も異なるさまざまな画面に対応しなければなりません。
これに対処するには用途に応じて画面に対する比率で大きさを決める部分、縦横比を固定する部分、引き伸ばしてもいい部分というように分割して考える必要があります。
例えば拙作のFactoryではこのような分割をして画面を設計しました。



画面に対して上下を55:45に分けて液晶描画とボタン描画部にとっています。
上部分の液晶表示部は横を全体width90%としていますが、縦横比は変えたくない部分なので縦はそれに対しての77%にしています。
この設計でいくとXperia Z、LG L-06D、初代Xperia SO-01Bなどでは以下のような実寸になります。
 
改めて計算してみると数あるAndroidスマートフォンの中でも、おそらく最も縦横比の縦が短いと思われるJOJO携帯ことLG L-06Dですが、上下分割の上の部分494pxに対して液晶表示枠の縦が768×0.9.×0.77=532pxになっていてはみ出してしまっています。
今頃気づいたんですがこれは完全に設計ミスですね
LG L-06Dユーザーの方ごめんなさい。

2013年5月15日水曜日

レトロではまる新作アプリ「Factory」公開

某コンテストに出したけど特に何もなく終わったゲームなんですが、個人的にこのゲームはなかなかゲームルールとゲームバランスの調整がよくできたと思ってます。自分で言うなという感じですが…
そのままお蔵入りではもったいないので、キャラクターを変えたりして公開することにしました。
よかったら遊んでみてください。







2013年5月2日木曜日

setColorとsetAlphaで半透過描画した時の落とし穴

こんなのにはまるのは自分だけかもしれませんが、半透過の描画をしようとしてはまってしまったので書いておきます。
描画時に透過したい場合setAlphaを使ったりしますが、このときsetColorとの組み合わせに注意しなければなりません。
例えば赤い半透明の丸を書いて、その横に青い半透明の丸を書きたいなんて時

Paint paint = new Paint();
paint.setColor(linecolor);
paint.setStyle(Style.FILL);
//描画色_赤指定
paint.setColor(Color.RED);
//半透過指定
paint.setAlpha(128);
//丸描画
canvas.drawCircle(40, 40, 40f, paint);
//描画色_青指定
paint.setColor(Color.BLUE);
//丸描画
canvas.drawCircle(120, 40, 40f, paint);

と書いてしまうとこうなります。
青い丸が透過していません。なぜかというとsetColorリファレンスをよく見ると、The new color (including alpha)と書いてある通り透過パラメータを含んでます。
Color.BLUEはColor.argb(255, 0, 0, 255)と値が同じなので、Color.BLUEをセットすると透過なしになってしまいます。
なのでこの場合、setColor後に再度setAlpha(128)をするかsetColor(Color.argb(128, 0, 0, 255))にすると
このように意図したとおりになります。
リファレンスはちゃんと読もうということですよね…

2013年5月1日水曜日

PhotoRouletteアプリ公開1ヶ月 反省会

PhotoRouletteを公開してから1ヶ月あまりが経ちました。
現在までのダウンロードは以下のような感じ。
有効インストールは4/25時点で59、とこれは惨敗といっていい結果です…
レビューサイトでの掲載は恐らくミートロイド様での1件のみ。
残念でしたと言っても仕様がないので、敗因を探ってみます。
アプリの成功要因を需要・品質・インパクト・流行・プロモの5つで自己評価してみました。
 
アプリを使ってもらうためにはまず第1にGooglePlayでアプリを表示してもらうこと、次にアプリの説明、スクリーンショットを見てアプリをインストールしてもらうことの2つ関門があります。

GooglePlayで表示してもらうにはPlayのランキングか検索からのいわゆる自然流入とよばれるものと、レビューサイトの紹介、ブログ、twitter、Facebook等のメディア流入、あとは純広告、リワード広告、自社広告からの広告流入などでしょうか。
PhotoRouletteの場合この中で流入が期待できるのはレビューサイトくらいかなと思ってたので、 Androidアプリのレビューサイトの依頼先(国内) まとめで挙げたのを含め20サイトくらいにレビュー依頼をしました。しかし結果は1件で、残念ながらレビューサイトに載るには需要、インパクト、プロモーションが全然足りなかったと思われます。
もっと充実した質の高いアプリの紹介、スクリーンショットや画像、紹介動画の作成など力を入れておくべきでした。
そもそもアプリの出来が悪いのでは?という懸念もありますが、1ヶ月で総インストール160という数からして、アプリの出来以前にインストールもしてもらえてないということです。
特にプロモーション不足しているところを反省点にして次に生かしたいところです。