2014年10月21日火曜日

Android ADT 22.6.0以降はEclipse Heliosでは動かない

いやいやいや、いまだにHeliosて!Heliosて!
と思われるでしょうが
6年物のCore2DuoのPCでがんばってる身としては、なるべく軽くて、枯れた環境でやっていたかったのです・・・

ADT 22.6.0(March 2014) Dependencies:
  • Java 1.6 or higher is required.
  • Eclipse Indigo (Version 3.7.2) or higher is required.
http://developer.android.com/tools/sdk/eclipse-adt.html 

今日からEclipse Keplerでがんばりたいと思います

2014年10月10日金曜日

AdMobメディエーションで日本だけNendを導入してみた結果

間取りー図に表示しているAdMobのクリック率、eCPMがいまいちだなぁと思って、6月末からAdMobのメディエーション機能を使って、日本だけNendを表示するようにしました
導入から3ヶ月たったので、成果をまとめてみます

7月、8月はNendのCTRがよく、もくろみ通りAdMobよりも高いeCPMを出していました
しかし9月に入りeCPMが激減、AdMobと逆転してしまいました

この3ヶ月の結果としては結局時期によって高かったり低かったりするという
ちっとも面白くない結果でした

しかしこれはメディエーションの良さを全く生かせてない
設定だったのです

今回やった設定は広告ネットワークの追加でNendを日本にだけeCPM $0.01で追加
としただけの物でした
結果上記の表のようにAdMobとNendのインプレッションはほぼ同数の表示となりました

しかしメディエーションの効果を上げるには


この設定が必要なのです
これによりAdMobのリアルタイムeCPM値と追加広告の設定eCPMを比較して
eCPMが高いほうの広告が表示されるのです

さらネットワークの最適化に対応している広告会社であれば、それぞれのリアルタイムeCPMを比較してより正確にeCPMが高いほうを表示してくれるのです

Google: 広告ネットワークの最適化と Live CPM について

現在(※2014/10/10)LiveCPMに対応している広告は
AdMob、Domob、InMobi、JumpTap、MobFox、MdotM、Nend

もっと早くこれをやっとけばよかった・・・

2014年10月9日木曜日

EasyBasketballの反省と新作アプリ企画

実に4ヶ月も間が空いてしまった・・・
本業が忙しかったり、色々技術的な模索をしてみたり、ネタを探してみたりと色々言い訳はあるが月1本リリースを目標としていただけに情けないことです
何とかここから巻き返したいところ

とりあえず色々思い出すために前作EasyBasketballの反省から


5ヶ月弱で1200ダウンロード、レビュー掲載 1本(※Androider)
というまあ惨敗でした

敗因はというとダウンロードにいたらない、レビューもされない
つまりはアプリからの請求力不足でしょう
まあユーザーに「これやりたい!」と思われないというところかなと思います

中身はいろいろとがんばったつもりでしたが、そもそもゲーム性のところで
作った本人も疑問を感じる出来だったというところで当然の結果だったのかもしれません

EasyBasketballでは自社広告の効果、海外レビュー依頼先など色々学んだ点もあったので
ブログでまとめたり、今後に生かしたいと思いマス

という流れで新作アプリの企画
その名も 『 Easy Putting 』
画面イメージ

まるで成長していない・・・・・・
ホントにEasyBasketballの惨敗を反省してるのか?

とりあえずリハビリがてらこいつを作っていきたいと思います

2014年6月6日金曜日

間取りー図をアップデート サイズの編集をロックする機能を追加

間取りー図をアップデートしました
主な変更点は以下
・サイズの編集をロックする機能を追加
 ・オブジェクトの編集ボタンを隠す機能を追加
 
・How toを追加
 
以上です
サイズの編集をロックする機能はよくユーザーからの要望で上がってましたので、ようやくつけれてよかったです
"How to"については今までなかったのがおかしいのですが、間取りー図はかなり有効インスト率が低いなと感じるアプリで、それというのも信じられないことですが、操作の説明が一切ないというのも大きな一因と思ってました
今回のHow toの追加でこの辺に効果があったかどうか、一か月後くらいに報告したいと思います

2014年6月4日水曜日

AndroidでTwitter公式の投稿Activityを取得(新旧バージョン対応)

前回Androidアプリからツイートする4つの方法を紹介しましたが、その中でPackageManagerを利用してピンポイントで公式クライアントアプリを呼び出す方法を紹介しました
しかし、この方法は呼出し時に投稿に使われるActivityまで指定しなければならないため、公式クライアントの更新により変更されてしまった場合使えなくなります
実際過去2回ほどありました
ここではその2回の変更に対応してユーザーの公式クライアントが古いバージョンの場合にも対応できる方法を紹介します

  public static String getTwitterClass(Context context) {
    String twitterClass = null;
    PackageManager pm = context.getPackageManager();
    String packagename = "com.twitter.android";
    String class1 = "com.twitter.android.PostActivity";
    String class2 = "com.twitter.applib.composer.TextFirstComposerActivity";
    String class3 = "com.twitter.android.composer.TextFirstComposerActivity";
    try {
      ActivityInfo[] activities = pm.getPackageInfo(packagename, PackageManager.GET_ACTIVITIES).activities;
      for(int i = 0; i < activities.length; i++) {
        if (activities[i].name.equals(class1)) {
          twitterClass = class1;
          break;
        } else if (activities[i].name.equals(class2)) {
          twitterClass = class2;
          break;
        } else if (activities[i].name.equals(class3)) {
          twitterClass = class3;
          break;
        }
      }
    } catch (PackageManager.NameNotFoundException e) {
      //Twitter is not install
    }
    return twitterClass ;
  }
※Twitter バージョン5.8.0対応

内容はいたって簡単で、パッケージ名は不変なので"com.twitter.android"でGET_ACTIVITIESによりActivityの一覧を取得して、既知の3つのActivity名と照合します
あとはこれで取得したActivity名を
intent.setClassName("com.twitter.android", 取得Activity名);
とセットして明示的インテントで呼べばオッケーです

2014年6月2日月曜日

AndroidアプリからTwitter公式クライアントでツイートする4つの方法

今回EasyBowlingとBowlingScoreBookにSNS投稿機能をつけましたが、BowlingScoreBookでは特に「Twitterで投稿」ボタンを付けました
その時に調べたTwitterの公式クライアントを呼びだしてツイートする4つの方法です
  1. 暗黙的Intentで投稿
  2. Intent.ACTION_SENDで暗黙的Intent呼び出しによる投稿です
    ACTION_SENDと"text/plain"に反応するアプリがすべて出るので公式以外のクライアントアプリ、Twitterに関係のないアプリも出てきます
      public static void tweetFile1(Context context, String message) {
        Intent intent = new Intent(Intent.ACTION_SEND);
        intent.setType("text/plain");
        intent.putExtra(Intent.EXTRA_TEXT, message);
        ((Activity)context).startActivity(intent);
      }
    
  3. 公式アプリのPackage、Classを指定して投稿
  4. PackageManagerで公式クライアントをピンポイントで呼び出します
    公式以外のクライアントアプリ以外は反応しません
    公式の投稿用Activityが変わった場合には修正が必要となります(過去2回程変更されている)
      public static void tweetFile2(Context context, String message) {
        String twitterClass = "com.twitter.android.composer.TextFirstComposerActivity";
        try {
          Intent intent = new Intent();
          intent.setAction(Intent.ACTION_SEND);
          intent.setType("text/plain");
          intent.putExtra(Intent.EXTRA_TEXT, message);
          intent.setClassName("com.twitter.android", twitterClass);
          ((Activity)context).startActivity(intent);
        } catch (PackageManager.NameNotFoundException e) {
          //Toast("Not found com.twitter.android")
        }
      }
    
  5. URIスキームを指定して投稿
  6. WEBページからアプリを呼び出すのに使用するURIスキームを利用して呼び出します
    公式以外でも"twitter://"のスキームに対応しているアプリが呼び出されます
      public static void tweetFile3(Context context, String message) {
        String url = "twitter://post?message=" + message;
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setType("text/plain");
        intent.setData(Uri.parse(url));
        ((Activity)context).startActivity(intent);
      }
    
  7. URL(http://twitter.com/)を利用して投稿
  8. 公式クライアントかWEBブラウザが呼び出されます ブラウザの場合、"http://twitter.com/"の投稿画面が呼び出されます
      public static void tweetFile4(Context context, String message) {
        String url = "http://twitter.com/share?text=" + message;
        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
        intent.setType("text/plain");
        intent.setData(Uri.parse(url));
        ((Activity)context).startActivity(intent);
      }
    
このように色々と投稿方法がありますが、どれを採用すべきかは状況によるかと思います
以下に各手法の特徴をまとめてみました
投稿方法互換
クライ
アント
画像
投稿
備 考
1.暗黙的Intent○○Twitter関連アプリ以外もでる
2.Package指定×○公式Twitterクライアントのみでる
3.URIスキーム指定△×互換クライアントはスキーム対応アプリのみ
4.URL(HTTP)指定××公式クライアントがなくてもブラウザで投稿できる
※2014/06/02現在

2014年5月21日水曜日

Bowling Score Bookをアップデートしましたー

Bowling Score Bookをアップデートしました


主な変更は先日のEasyBowlingと同じような感じですが、こちらのほうが高機能となってます
内容としてはスコアの画像出力と共有機能の追加ですが、出力は1ゲーム分または1日分を選択できます
共有は通常共有とtwitterへの投稿、ギャラリーでの表示を選択することが出来ます
ぜひ使ってみてください

2014年5月15日木曜日

EasyBowlingのアップデート(SNS投稿機能を付けてみた)

EasyBowlingをアップデートしました


主な変更はスコアのSNSへの投稿機能の追加です
SNSへの投稿といっても実際にはスコア画像を暗黙的IntentでACTION_SENDをしているだけですので、SNSだけではなくメールやギャラリー等にも投げれるかと思います
Twitterに投げてみるとこんな感じ

ぜひ使ってみてください

2014年5月14日水曜日

新作アプリ EasyBasketballをリリースしましたー

長々と作ってきましたが、ついに新作アプリEasyBasketballをリリースしました
EasyBasketballは同系のバスケットシュートゲームにはない操作感と、シンプルで手軽に遊べるカジュアルスポーツゲームです
またプレイデータの統計分析機能がやたらと無駄に充実しております
是非とも、たくさんプレイしてみてください

2014年4月28日月曜日

SurfaceViewで点線(破線)を描画する

新作アプリも最終調整段階に来ました
前にテコ入れ編 操作感をなんとかするという記事で操作領域を画面全体にしたことで、シュート方向がわかりにくくなってしまいました
その対策としてボールを引っ張った時のガイド線を入れてみようと思います
今回は簡単にPaint.setPathEffectの機能を使った点線を描画します
ソースはこんな感じ

Paint paint = new Paint();
paint.setStyle(Style.STROKE);
paint.setStrokeWidth(2f);
paint.setColor(Color.BLACK);
paint.setAntiAlias(true);
paint.setPathEffect(new DashPathEffect(new float[]{ 2.0f, 2.0f }, 0));
canvas.drawLine(100, 100, 100, 200, paint);

描画した感じはこれ
これの注意点としてはsetStrokeWidthもそうですが指定がピクセル値ですので、指定値が同じだと端末のdpiによって見え方が変わってしまいますので注意しましょう
と言いつつ今回は方向がわかればいいので気にしない・・・

2014年4月22日火曜日

iOS/Android両対応の開発環境のまとめ

4/22日エンバカデロ・テクノロジーズは「Delphi」「C++Builder」の流れを汲むマルチデバイス対応アプリ開発プラットフォーム「Appmethod」を提供開始したようです
http://codezine.jp/article/detail/7745

いい機会なので iOS/Android両対応の主な開発環境をまとめてみました
色々と選択肢が増えるのは開発者にとってはありがたいことですね

Appmethod
概要:「Delphi」「C++Builder」の流れを汲むマルチデバイス対応アプリ開発プラットフォーム
開発言語:C++, Object Pascal(Delphi言語)
有料/無料
http://www.appmethod.com/jp/

Xamarin
概要:C#言語によるクロスプラットフォーム(iOS/Android)なモバイルアプリケーションの開発環境
Microsoft Visual Studioを利用して開発することが出来る
開発言語:C#
無料
http://xamarin.com/

Adobe AIR
概要:アドビシステムズが開発する複数のオペレーティングシステムに対応したFlashベースのアプリケーション実行環境
開発言語:ActionScript, HTML, JavaScript
有料/無料
http://get.adobe.com/jp/air/

Unity
概要:様々なプラットフォームで動作する高度な 3D アプリケーションを制作することが出来る、統合型のゲーム開発環境
開発言語:C#, JavaScript, Boo
有料/無料
http://japan.unity3d.com/

Cocos2d-X
概要:Zhe Wang氏によって開発され、オープンソースかつ無料の2Dゲームエンジン
開発言語:C++
無料
http://www.cocos2d-x.org/

PhoneGap
概要:Adobe社により公開されているHTML5・CSS・JavaScriptで様々なプラットフォームに対応するアプリケーションを開発するフレームワーク、各デバイスのカメラやGPS,電話帳も利用できる
開発言語:HTML5, CSS, JavaScript
無料
http://phonegap.com/

Titanium Mobile
概要:HTML・JavaScriptを利用してネイティブアプリを作成するオープンソースの開発環境、ネイティブUI,デバイスのカメラやGPS,電話帳も利用できる
開発言語:HTML, CSS, JavaScript
無料
http://www.appcelerator.com/titanium/

monaca
概要:クラウドサービスを利用して、アプリ開発の一連の作業をすべてWebブラウザを通じて行うことができる開発環境
開発言語:HTML5, CSS, JavaScript
有料/無料
http://monaca.mobi/ja/

2014年4月14日月曜日

新作Androidアプリ開発 インスト・即消し対策 トレーニングモードの追加

本業が一息ついて気が抜けてしまいました
いい加減早く新作アプリをリリースしたい

さて、アプリの有効インストール率を上げるためにアプリを消されるのはいつか?ということを考えると一番多いのがインストール直後です
その削除に至る理由としては
  1.  やり方がよくわからない
  2.  どうやればうまくいくのかよくわからない
  3.  しょぼい、おもしろくない
といったところでしょうか

1.に対してはHow toやプレイ動画の提示、2.に対してはチュートリアルやTips、トレーニングモード等を用意するといいでしょう
3.についてはとにかく企画からデザインまでがんばるしかないと・・・

というわけで2.対策として、トレーニングモードを追加しました
実装はこんな感じ

2014年4月10日木曜日

マルチプラットフォームゲーム開発エンジン"Unity"が公式キャラUnityちゃんを無償公開

ユニティ・テクノロジーズ・ジャパン合同会社は開発者向けにゲーム開発などに無償利用できるキャラクター『ユニティちゃん』を発表しました

Unityは俄然勢いを増してますね、Unity5の予定もあるようです
前から手をつけたいと思ってましたが、そろそろやらないと追いつけなくなりそう・・・


利用する際は指定のロゴマークの表示や、キャラクターの価値や品位を下げるような使い方などは禁止といった制限事項があるようです
利用する方は公式でライセンスを確認してください


unity-chan公式サイト
http://unity-chan.com/

2014年3月31日月曜日

新作Androidアプリ開発 統計機能の追加 プレイデータの見える化

なかなか完成しない新作アプリですが、統計機能を追加しました
シュートデータの統計ですが位置をプロットしたり、シュート方向角別の成功率を表示しています
プレイデータの見える化、いわゆるインフォグラフィックと呼ばれるようなものですが、こういった表現の面白さがプレイ継続につながればと思いますが果たしてどうか・・・
 
 
あと、エリアごとの成功率表示も追加予定
3月中のリリースは無理だったか・・・

2014年3月25日火曜日

新作Androidアプリ開発 GUIを盛る編 ダッシュボード的なパネル

今回はStats(統計)機能の画面のGUIを盛っていきたいと思います
現状の画面だと操作と情報表示部分の区切りがはっきりせず、どこが何なのかをもう少しわかりやすくしたいので表示切替操作部をダッシュボード調にしてみます
こんな感じ、少しはわかりやすくなったかな?
こうなるとアイコンがちょっとしょぼい気がしますね、要改良です
静的なコンテンツなのであまり難しいことはしてません
layout.xmlはこんな構造です
ちょっと入れ子が多くなってしまいますね
ポイントというほどのあれはありませんが、強いて言えばダッシュボードパネル部(オレンジ)の円弧分のPaddingを取ることと、右側にドロップシャドウを落としてやることで立体感を出してます
あと緑のLinearLayoutは、3等分でアイコンを配置したいがためだけに入れています

2014年3月23日日曜日

新作Androidアプリ開発 GUIを盛る編 スタートシグナル

さて今日もGUIを盛っていきたいと思います
ゲームのスタート時いきなり始まるとユーザーがとまどうということで、3秒のカウントダウン時間を設けることにしました
ここでスタートシグナルのようなものを出したいということでとりあえず作ってみたのがこれ
んー確かにスタートシグナルなんだけど・・・
ちょっと普通っぽいし、いまいちかなぁ
一ひねりしてみようと作ったのがこれ
色調と形をもうちょっとどうにかしなきゃですが、なんとなく・・・こんな感じでいい?かな?
実装は横着して簡単にベースの黒いところと左赤、右赤、真ん中青を順番に重ねて描画するだけです

デザインは正解がないのでセンスがないと試行錯誤が増えてしまいますね・・・

2014年3月21日金曜日

新作Androidアプリ開発 GUIを盛る編 ゲージのような表示

さて新作アプリの開発ですが、 4回にわたるテコ入れ編でクリティカルな問題に対しての対策が出来ました
あとは完成に向けてひた走るだけ!?
というわけで今回から見た目部分の改良でGUIを盛る編といきたいと思います

まずは右上に表示していた残り時間の表示がスコアの表示と同じじゃわかりにくいし、なんかしょぼいのでもう少し視覚的に残り時間がわかりやすいようにしたいと思います

完成イメージはこう
これをどうやって描画したらいいかなぁと考えました
やり方はいろいろでしょうが今回は丸いゲージの部分の画像をフルで用意して、それを扇形のclipPathでマスクして必要部分だけを描く方法を取りました
パーツを一個用意して回転させながら60個描く方法もありますが、clipPathの方法なら切れ目がないようなアナログ的なゲージにも対応できる思います
コード的には以下のような感じ
    int time; //残り時間
    int rect; //ゲージの大きさのRect
    Bitmap gauge; //フルゲージ画像
    Path clip = new Path();
    clip.moveTo(rect.centerX(), rect.centerY());
    clip.addArc(rect, 267 + ((60 - time) * 6), 360 - ((60 - time) * 6));
    clip.lineTo(rect.centerX(), rect.centerY());
    canvas.save();
    canvas.clipPath(clip);
    gauge.draw(canvas);
    canvas.restore();
このブログで以前、SurfaceViewで描画範囲を限定するでやった方法と同じですね
clipPathは描画したい部分の指定になるので、addArc()の開始角と終了角をずらしながらセットしてやります

わりといい感じにできました

2014年3月18日火曜日

Google Play Services 4.3発表 クロスプラットフォームなネットゲームの時代が到来か?

Google Play Services 4.3発表 - iOSとのマルチプレイヤーゲームに対応
http://iwire.jp/news/2014/03/18/003/index.html

主な変更点
・Google AnalyticsとGoogle Tag Managerがファーストクラスオブジェクトとして利用可能になる
・Google+を利用してゲーム内アイテムや通貨のやり取りを行う"Game Gifts"機能の追加
・Drive API、Address APIの強化
・ゲームのカテゴリを追加、現行の17から20カテゴリへ
(追加されたのはおそらく"ウィジェット","ライブ壁紙","教育"、また"トリビア"が"雑学"に変更)

新カテゴリ一覧(2014/03/19)
カテゴリ名備考カテゴリ名備考
アクション
パズル
アドベンチャー
ファミリー
アーケード
ボード
ウィジェット新カテゴリ ライブ壁紙新カテゴリ
カジノ
レース
カジュアル
ロールプレイング
カード
教育新カテゴリ
シミュレーション
言葉
ストラテジー
雑学旧トリビア
スポーツ
音楽

マルチプレイ機能がさらに強化され、iOSとも繋がることが出来るようになるみたいです
Androidでネットゲームをいつか作りたいなぁとは思っていましたが、もっといろいろ勉強しなきゃですね・・・

2014年3月17日月曜日

新作Androidアプリ開発 テコ入れ編 何度もやりたくなる工夫

さてテストプレイ編であがった課題の解決も最後となりました

4.何度もやりたくなる気がおきない

さらっとヒドイ事いいますね、一生懸命作ってるのに・・・
しかしまあこれがユーザーの厳しい意見だということで、厳粛に受け止めて改良をしましょう

これについては今までのテコ入れでゲーム性、操作性等の改良により幾分良くなっていると思います
あとは得意の?プレイデータを蓄積して統計分析できる機能をつけます
これで何度もやる気がおきるのではないか!?という目論見
こんな感じに統計値やグラフで、過去の記録を見れるようにしていこうと思います

2014年3月14日金曜日

新作Androidアプリ開発 テコ入れ編 ゲーム性をなんとかする

気がついたらもう3月になっていた・・・早いところ新作アプリを完成させたい
テストプレイ編であがった課題の3つ目の対策です

3.60秒で何ゴールできるかというルールではスコアの頭打ちが早いのではないか

ゲームの根本的なところに課題が出てしまいました
まず直接的な対策として現在ボールのセットはシュートした後に高さがピークを越えた瞬間に次のボールをセットしていました
これをもっと早くの上昇中の一定高度を超えたところでセットするように変更
この変更で単純にシュートの回転率を上げることが出来るため、シュート数の増加になりスコアの上限があがることになります
まあ、あくまで理論的にではありますが・・・

そしてもうひとつのテコ入れとして1分間で何ゴールかというルールと別に、何秒で10ゴールを達成するかというタイムトライアルモードを作ることにしました
これで二通りの遊び方が出来るようになります
しかしアプリ名の1Min Basketball(仮)は変えないとならんかなぁ

2014年3月9日日曜日

新作Androidアプリ開発 テコ入れ編 見た目をなんとかする

さてテストプレイ編であがった課題の対策を続けたいと思います
今回はこれについて

2.ボールの動きがわかりにくい、特に高低差、ゴールしたのかどうか、たまに変な挙動

主に見た目の部分に手を入れていきましょう
まずはボールの高低差表現のためボールの高さによってボールの大きさを変えます
ボールの大きさは視点とボールの距離に比例するので式はこんな感じ


zoom : ボール描画ズーム率
z0 : 基底ボール高さ
z1 : ボール高さ
eye : 視点高さ

とりあえず視点高さを15mとして描画してみるとこんな感じ
 
まあ実際はこんなもんでしょうが、ゲームなので多少大げさに表現したほうがいい場合もあります
視点高さを9mにしてみます
 
ぐっと近づく感が出たでしょうか

次に背景に画像を入れていきます 1枚絵だと簡単ですが4:3比率の画面、ワイドな画面などに対応するため今回はタイル表示にします
こんな画像を用意して縦幅いっぱいで横に向かってタイル描画するだけ
タイル描画は以前ブログで紹介しました
SurfaceViewでの画像のタイル描画(繰り返し) 
こんな感じになります

次にさらに高低差感を出すのにボールに影をつけてあげます
影の位置はこのようにボールの位置とライト位置から上と下の三角形の比率で求めます

4つほどライトをつけてみた結果がこれ


ちょっと影が薄いかなー、改良の余地はまだありますがだいぶゲームらしくなってきました

2014年3月6日木曜日

新作Androidアプリ開発 テコ入れ編 操作感をなんとかする

さてテストプレイ編で課題がいくつかあがったので、それらの対策をしていきたいと思います

まずはじめにあがった

1.一番大事な操作感、すべてが小さくて、ちまちましてイライラする

というところ、 ゲームにとって操作は生命線です
操作するだけで楽しい、うまくいくと気持ちがいいという感覚
そういった操作感がゲームの面白さに直結するため非常に重要なところ
今回原因はすべてが小さいところに起因するわけなんで、単純に大きくしてやろうと考えました
グリップを表示して引っ張って放してシュートという方式は直感的でいいのですが、グリップの分どうしても引きしろ範囲を大きくとらねばなりません
なので思い切ってグリップを廃止、画面全体を操作対象にしました

全体的にかなり大きくなったので、操作感は大分良くなりました
ただグリップ式よりも方向が決めにくくなった感があるのでガイドなど表示する必要があるかも

2014年3月3日月曜日

新作Androidアプリ開発 テストプレイ編 作りたいから作った結果がこれ・・・

さて一通りの動きは実装したのでここらでざっくりとテストプレイをしてみたいと思います
本当は誰かほかの人に頼んで意見や感想をもらったりしたほうがいいのでしょうが、なかなか難しいので自分で心を鬼にして厳しいユーザー視点に立ってプレイします
ここでアプリのコンセプト、方向性、課題を厳しくチェックします


んークソゲーか? 
見た感じのしょぼさはまだ仮画像なんでおいといて・・・
ゲームとしてどうなのこれ、成り立ってるのか!?
誰だよこの企画を作ったやつは?オレカ・・・しかもこんなことまで言っている

http://anadreline.blogspot.com/2014/02/blog-post.html

>もしこれが企業での企画なら絶対通らないでしょう
>今更バスケットのシュートゲームかよと一蹴されて終わる
>しかしここが個人開発者の最高なところ
>作りたいから作るのです

作りたいから作った結果がこれか・・・
いやしかしそうだ、作りたいんだった、脳内企画ではもっと面白かったはず
まだどうにかする余地はきっとあると思う
とりあえず現状の問題点を挙げよう
  1. 一番大事な操作感、すべてが小さくて、ちまちましてイライラする
  2. ボールの動きがわかりにくい、特に高低差、ゴールしたのかどうか、たまに変な挙動
  3. 60秒で何ゴールできるかというルールではスコアの頭打ちが早いのではないか
  4. 何度もやりたくなる気がおきない
いろいろあるがクリティカルなところはこんなところか
残念ながらこのままリリースへ向かえるような状態ではない
とりあえずこれらに対して何かしらの解決策を見出して、根本的にてこ入れを行う必要がある

はあ・・・ゲーム作りって難しいですね

2014年2月28日金曜日

消えそうなアプリがアプリ名変更で大復活! EasyBowlingが5万ダウンロード突破!

2012年に公開したEasyBowlingですが、2013年の3月頃をピークに有効インストールは下がり続けてあとはただ消えゆくのみという状態でした
ある時ふと、GooglePlayの検索時「Bowling 」での検索順位がちょっと低いなぁと感じ、2013年の末にアプリ名を"EasyBowling"から"Easy Bowling"と間にスペースを入れたものに変更してみることにしました

するとびっくり!今まで「Bowling 」での検索100位にも入っていなかったEasyBowlingがいっきに25位になりました
その後インストールが一気に伸びて50000ダウンロードを達成
やはりアプリ名は非常に大事というお話ですね

アプリ名変更前は1日のダウンロード数は50以下程度でしたが、変更後はだいたい200くらいに上昇しました
EasyBowlingの無料スポーツゲームカテゴリでのランクは現在350位くらいなのでランキングからの流入はほとんど見込めません
それでも200ダウンロード/日の自然流入があるというのは、検索からの流入が効いているということかと思います

2014年2月26日水曜日

新作Androidアプリ開発 ボールをランダムに配置しよう編

ボールを操作で投げれるようになったので、今回はボールを任意のエリアにランダムに配置してみましょう
配置したいエリアはというと、距離的にフリースローからスリーポイントまでの間にあたる扇状の青の部分です
操作の都合上、リングの左右側の鋭角を10°程削っています
これをどう計算してランダムな座標を生成するか
もし対象とするエリアが長方形だったりすると話は簡単です
XとY軸の対象範囲をRandom.nextInt(value)するだけ
Rect area = new Rect(100, 100, 400, 300);
Random random =new Random();
int x = area.left + random.nextInt(area.width());
int y = area.top + random.nextInt(area.height());
試しに1000個ほど生成して描画してみましょう

Rect area = new Rect(100, 100, 400, 300);
canvas.drawRect(area, paint);
Random random =new Random();
for (int i = 0; i < 1000; i++) {
    int x = area.left + random.nextInt(area.width());
    int y = area.top + random.nextInt(area.height());
    canvas.drawCircle(x, y, 3f, paint);
}
なんか気持ち悪いですね
今回は変形扇形のエリアではいろいろと方法はあると思いますが、このような考え方で生成しました
赤枠部分フリースローラインからスリーポイントラインまでの範囲でランダムにセットした座標を、対象範囲角をランダムにセットして回転する

ソースとしてはこのような感じ
Random random =new Random();
Plot ring = new Plot(7500, 1882);
for (int i = 0; i < 1000; i++) {
    //リングX座標+フリースローラインまでの距離(4.118m)+フリースローラインからスリーポイントラインの間(2.52m)の間のランダム値
    Plot base = new Plot(ring.x + 4118 + ((2520 * random.nextInt(100)) / 100), ring.y);
    //削った10度+配置部分160°のランダム値
    int angle = 10 + random.nextInt(160);
    //回転処理
    Plot pos = Utl.rotate(angle, ring, base);
    //描画座標変換
    pos = Court.getDPlot(pos);
    canvas.drawCircle(pos.x, pos.y, 3f, paint);
}
試しに1000個ほど生成して描画
よさそうです

2014年2月18日火曜日

新作Androidアプリ開発 ボールを操作で投げる編

投げたボールの処理が代替できたので、次にユーザーの操作でボールを投げるところを作ります
操作手法はこんな感じ
いわゆるAngryBird投射法です
処理の考え方としては引っ張り長さに制限をつけて、引っ張っていない時を0、最大まで引っ張った時を100として初速度を計算します


v0:初速度
d:引っ張り長さ
dm:最大引っ張り長さ
min:引っ張り0の時の速度
max:引っ張り100の時の速度

式は簡単ですが、minとmaxの値は初速度を決めるパラメータ、つまりはゲームバランスに繋がるのでテストと調整が非常に重要になります

あとは引っ張ったところからボール初期位置への角度を水平方向の投射角として

新作アプリ開発 ボールを投げてみる編で作ったshot関数

public void shot(double speed, double vangle, double hangle)

に投げてやれば完成

2014年2月15日土曜日

新作Androidアプリ開発 ボールの跳ね返り リング編

前回ボールの跳ね返りをやりました
残るはリングとの衝突と跳ね返り処理です
これはかなり悩みました、3日ほど悩んでむりくりひねり出した結論ですが

※以下の考え方は物理的に正しいかどうかは不明です※

まず例としてこんなボールとリングの衝突と跳ね返りがあるとします
ごく当たり前の跳ね返りですが、これをどうプログラムで計算するのか?
とりあえず衝突点を求めます
そしてリングの断面の中心とボールの中心点を結んで衝突面の法線ベクトルを求めます

その衝突法線ベクトルが作る面に対しての3次元速度ベクトルの反射処理と考えました

この考え方を元にまずボールの移動前、移動後の位置を与えてリング当たっていれば衝突位置を返すメソッドを作成します
//リングとの衝突判定関数
public static Plot hitRing(Plot prev, Plot move) {
    Plot ret = null;
    //大雑把な判定条件として落下方向への移動、移動のZ座標がリング高さをまたがっている
    if (move.z < prev.z && move.z - Ball.R <= RING_H && prev.z - (Ball.R / 2) > RING_H) {
        int r = (int)((((prev.z - Ball.R) - RING_H) * 100) / (prev.z - move.z));
        //ボール下面がリング高さに来る位置取得
        Plot pos = Utl.getPlotInLine(r, prev, move);
        //リング中央との距離取得
        int d = Utl.getDistancePtoP(RING_CENTER, new Plot(pos.x, pos.y));
        //リングに当たりそうな距離にあればさらに詳しく判定
        if (d > (RING_R - Ball.R) && d <= RING_R + Ball.R) {
            float dagl = Utl.getRadians(Court.RING_CENTER, pos);
            int dx = (int)(Court.RING_CENTER.x + Court.RING_R * (Math.cos(dagl)));
            int dy = (int)(Court.RING_CENTER.y + Court.RING_R * (Math.sin(dagl)));
            int bw = Utl.getDistancePtoP(new Plot(dx, dy), new Plot(pos.x, pos.y));
            int bz = (int)(Ball.R * Math.sin(Math.acos((double)(Ball.R - bw) / (double)Ball.R)));
            r = (int)(((prev.z - (pos.z - bz)) * 100) / (prev.z - move.z));
            //実際にリングに当たる位置取得
            pos = Utl.getPlotInLine(r, prev, move);
            //リング中央との距離取得
            d = Utl.getDistancePtoP(Court.RING_CENTER, new Plot(pos.x, pos.y));
            //取得した距離からリングに当たるかどうか判定
            if (d > (Court.RING_R - Ball.R) && d <= Court.RING_R + Ball.R) {
                ret = new Plot(pos);
            }
        }
    }
    return ret;
}
こんな感じ
このメソッドをボールの移動処理にはさみます
Plot hr = hitRing(prev, move);
if (hr != null) {
    //法線ベクトル取得
    float angle = Utl.getRadians(Court.RING_CENTER, hr);
    int dx = (int)(Court.RING_CENTER.x + Court.RING_R * (Math.cos(angle)));
    int dy = (int)(Court.RING_CENTER.y + Court.RING_R * (Math.sin(angle)));
    //衝突時の速度ベクトルと法線ベクトルの内積を計算
    float ip = Utl.getInnerProduct(new Plot(xSpeed, ySpeed, zSpeed), new Plot(hr.x - dx, hr.y - dy, hr.z - Court.RING_H));
    //内積が+のときは裏からの当たりなので処理しない
    if (ip < 0) {
        //速度ベクトルの跳ね返り後の速度を取得
        Plot dv = getReflect(new Plot(xSpeed, ySpeed, zSpeed), new Plot(hr.x - dx, hr.y - dy, hr.z - Court.RING_H));
        float dk = 0.6f;
        //反発係数dkを速度にかける
        xSpeed = (int)(dv.x * dk);
        ySpeed = (int)(dv.y * dk);
        zSpeed = (int)(dv.z * dk);
        //衝突後の経過時間を計算
        int citv = (int)((interval * Utl.getDistancePtoP(hr, move)) / Utl.getDistancePtoP(prev, move));
        //移動後の位置を変更速度から再計算
        move.x = (int)(hr.x + ((xSpeed * citv) / 1000));
        move.y = (int)(hr.y + ((ySpeed * citv) / 1000));
        move.z = (int)(hr.z + ((zSpeed * citv) / 1000));
        prev = new Plot(hr);
    }
}
こんな感じ、いろいろと処理がひどいですが見ないでやってください(良い子はまねしちゃダメ)
試したところやや動きが怪しいところがありますが、基本方針としてはよさそう