2014年6月26日木曜日

iTunes ConnectでAgreement Updateと出た場合の対処法

ある日、iTunes Connectにログインすると『Agreement Update』という画面が出るようになりました。
iOS Developer Programの期限があと二ヶ月ほどで切れるので出ているのだろうなあと思って気にしないでいました。
しかし、このままだとアプリを申請できないことが分かったので対処しました。
その方法を備忘録を兼ねて記載しておきます。


Agreement Updateで『Member Center』をクリック


Developerの画面で『Review Agreement』をクリック

iOS Developer Program License Agreementを読んで、チェックして『I Agree』をクリック

Agreement Updateで今度は『Contracts, Tax Banking』をクリック

Contracts, Tax, and Bankingで『Request』をクリック

Review Agreementを読んで、チェックして『Submit』をクリック


以上で『Agreement Update』は出なくなりました。
なお、これは『iOS Developer Program』を更新したわけではないのであしからず。


せり上がってくる数字と演算子で計算式を作り消して行く
5つ正解でクリアー、全30ステージの知育系パズルゲーム


2014年6月18日水曜日

計算パズル『パズオペ』ステージ12の攻略法とその面白さ

数字と演算子で計算式を作る、知育系パズル『パズオペ』。
なかなか好評のようで、たくさんの方に遊んでいただいております。

ただ、ステージ12で苦戦される方が多いようなので、その解き方をご紹介します。
また、プレイしたことのない方もこの記事を読めば『パズオペ』の面白さが分かりますよ。


ご覧の通り、ステージ12は偶数だけしか出現しません。
偶数は以下のような性質があります。

  • 偶数 + 偶数 = 偶数
  • 偶数 - 偶数 = 偶数
  • 偶数 × 偶数 = 偶数


ところが、回答欄の7桁目に『1,3,5,7,9』の奇数が固定されています。
つまり、足したり、引いたり、掛けたりするだけでは駄目ということです。


偶数だけを使って奇数を作る方法としては『割り算』があります。

  • 6 ÷ 2 = 3
  • 4 ÷ 4 = 1  など


これを利用すると『6÷2+6=9』等の計算式を作れます。


また、奇数に偶数を『掛け算』して偶数にしてしまう方法もあります。

たとえば、『6+4=2×5』といった感じで。


このように偶数と奇数の性質を考えると色々な計算式が考えられます。

落ち着いて考えれば、簡単ですよね。




ですが、『パズオペ』は一定時間で下からパネルがせり上がってきて、
上まで積みあがるとゲームオーバーになってしまいます。



この辺りが、数字パズルとパズルゲームの好いとこ取りの『パズオペ』の楽しさでもあり、
難しさでもあります。



まだ、プレイしたことの無い方はぜひ一度ステージ12をチャレンジしてみてください。


【攻略動画】




2014年6月12日木曜日

iOSアプリでSQLiteを簡単に使えるFMDB

iOSアプリでデータベースを使いたくなることがあります。
でも、Core Dataはなんだか取っ付きにくいですよね。
そこで、SQLiteを使ってみてはいかがでしょうか?
FMDBというライブラリを使えばiOSアプリでも簡単に使えます。


準備



1.ライブラリをダウンロード


https://github.com/ccgus/fmdb



2.ライブラリを追加


ライブラリの『fmdb』以下にあるファイルを全部Xcodeに追加する。



3.フレームワークの追加


『libsqlite3.0.dylib』を追加する。



使い方



初期処理


#import "FMDatabase.h"


//FMDB
FMDatabase *db;

//DBファイル名
NSString *DB_FILE = @"test_db.sqlite3";

//DBファイルのパスを取得
NSString *dbPath = nil;
NSArray *documentsPath = NSSearchPathForDirectoriesInDomains
(NSDocumentDirectory, NSUserDomainMask, YES);

//取得データ数を確認
if ([documentsPath count] >= 1) {
    
    //固定で0番目を取得
    dbPath = [documentsPath objectAtIndex:0];
    
    //パスの最後にファイル名を追加
    dbPath = [dbPath stringByAppendingPathComponent:DB_FILE];
} else {
    
    //エラー
    NSLog(@"database file not found.");
}

//DBファイルがDocument配下に存在するか判定
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:dbPath]) {
    
    //存在しない場合、DBファイルをコピー(初回起動時のみ)
    NSBundle *bundle = [NSBundle mainBundle];
    NSString *orgPath = [bundle bundlePath];
    orgPath = [orgPath stringByAppendingPathComponent:DB_FILE];
    
    //DBファイルをDocument配下へコピー
    NSError *error = nil;
    if (![fileManager copyItemAtPath:orgPath toPath:dbPath error:&error]) {
        
        //エラー
        NSLog(@"db file copy error. : %@ to %@.", orgPath, dbPath);
    }
}

//パスを設定して、データベースオープン
db = [FMDatabase databaseWithPath:dbPath];
[db open];



//処理が終わったら、データベースクローズ
[db close];




SELECT


//クエリ実行
NSString *query = @"SELECT item_id, word, date FROM items WHERE word = ? ";
FMResultSet *rs = [db executeQuery:query, @"test1"];

if ([db hadError]) {
    //エラー
    NSLog(@"db execute error");
}

//結果の取得(カラム名指定)
while ([rs next]) {
    
    //数値の取得
    int itemID = [rs intForColumn:@"item_id"];
    
    //文字列の取得
    NSString *word = [rs stringForColumn:@"word"];
    
    //日付の取得
    NSDate *date = [rs dateForColumn:@"date"];
}

//ResultSetのクローズ
[rs close];




INSERT


NSString *word = @"test1";
NSString *mean = @"テスト1";

//INSERT実行
NSString *sql = @"INSERT INTO items (word, mean) VALUES (?, ?) ";
[db executeUpdate:sql, word, mean];

if ([db hadError]) {
    //エラー
    NSLog(@"db insert error");
}



UPDATE


NSNumber *itemID = [NSNumber numberWithInt:12345];
NSDate *timeStamp = [NSDate date];

//UPDATE実行
NSString *sql = @"UPDATE items SET date = ? WHERE item_id = ? ";
[db executeUpdate:sql, timeStamp, itemID];

if ([db hadError]) {
    //エラー
    NSLog(@"db update error");
}



DELETE


NSNumber *itemID = [NSNumber numberWithInt:12345];

//DELETE実行
NSString *sql = @"DELETE FROM items WHERE item_id = ? ";
[db executeUpdate:sql, itemID];

if ([db hadError]) {
    //エラー
    NSLog(@"db delete error");
}



まとめ


RDBを使ったことがある人は簡単ですよね。
Core DataでDBを使うことを断念した人も、FMDBでSQLiteを検討してみてはいかがでしょうか。


せり上がってくる数字と演算子で計算式を作り消して行く
5つ正解でクリアー、全30ステージの知育系パズルゲーム


2014年6月11日水曜日

App Storeランキングが150位までしか表示されなくなった

iOSアプリをリリースするとApp Storeランキング、気になりますよね。
私も新作アプリの順位をチェックしていたら、何だか違和感が…
App Storeランキングが『150位』までしか表示されなくなっていました。


これでは、個人開発者はますますランク入りが難しくなります。
実際、上位は宣伝費をバンバン使える企業がほとんどです。
そこで、ランキングの仕組みを思い出して対策を考えて見ましょう。


App Storeランキングのロジック


App Storeランキングは以下の要素で決まると推測されています。
  • ダウンロード数
  • ユーザーの継続率
  • レビューの評価
また、上から順に優先度が高いと考えられています。
つまり、『ダウンロード数 > 継続率 > レビュー』となります。
やはり、ある程度のダウンロード数は必要不可欠です。


App Storeランキング入りの効果


ランキング入りすると以下のような効果でダウンロード数が増えます。
  1. ランキングに載る
  2. ランキングを見てダウンロードする人が増える
  3. ダウンロード数が増えてランキングが上がる
  4. ランキングが上位になり見る人が増える
  5. ランキングを見る人が増えてダウンロード数が増える

つまり、最も効率のよいプロモーションになるという訳です。


ランキング入りするための対策


ランキング入りするためのダウンロード数はカテゴリ毎にことなります。
よって、『ゲーム』などのメジャーなものではなく『教育』などのマイナーなカテゴリを狙うとハードルが下がります。

今回、私の新作アプリ『パズオペ』もパズルゲームですが、あえて『教育』カテゴリにしてランキング入りさせることに成功しました。

『パズオペ』が教育・無料アプリで『22位』になりました!


まとめ


ダウンロード数を増やすにはApp Storeランキング入りするのが最も効率的です。
ランキングのロジックを把握して、上手くランク入りを目指しましょう!


せり上がってくる数字と演算子で計算式を作り消して行く
5つ正解でクリアー、全30ステージの知育系パズルゲーム


2014年6月5日木曜日

Objective-Cで0.1+0.2が0.3にならない?

新作アプリ『パズオペ』は計算式を作るパズルゲームです。


数字と演算子を組み合わせて、正しい計算式を作って行きます。

ところが、小数も計算できるようにしていたら不具合が発生しました。
具体的には『0.1+0.2=0.3』とすると、なぜか不正解と判定されてしまうからです。


=================

double num1 = 0.1;
double num2 = 0.2;
double num3 = 0.3;
double ans = num1 + num2;

//比較
if (ans == num3) {
    NSLog(@"YES");
} else {
    //こちらが表示される
    NSLog(@"NO");
}

=================


これは私もすっかり頭から抜け落ちていたのですが、小数の値が二進数では表現できないことによる誤差が原因でした。

そもそも、プログラム内部では値を二進数で計算しています。
十進数の『0.1』は二進数だと『0.0001100110011…』となり循環小数となってしまいます。
演算するときはどこかで丸められてしまうので、十進数の値とは誤差が生じてしまうというわけです。

Objective-Cではそういう場合は『NSDecimalNumber』を使って対処します。

=================

NSDecimalNumber *decimal1 = [NSDecimalNumber decimalNumberWithString:@"0.1"];
NSDecimalNumber *decimal2 = [NSDecimalNumber decimalNumberWithString:@"0.2"];
NSDecimalNumber *decimal3 = [NSDecimalNumber decimalNumberWithString:@"0.3"];
NSDecimalNumber *decimalAns = [decimal1 decimalNumberByAdding:decimal2];

//比較
if ([decimalAns isEqualToNumber:decimal3]) {
    //ちゃんとこちらが表示される
    NSLog(@"YES!!");
} else {
    NSLog(@"NO!!");
}

=================

プログラムを書いていると、内部は二進数で…ということは忘れがちです。
これはどの言語でもある現象なので、覚えておくと良いでしょう。


せり上がってくる数字と演算子で計算式を作り消して行く
5つ正解でクリアー、全30ステージの知育系パズルゲーム


2014年6月3日火曜日

アプリのレビューサイトに掲載される依頼の仕方

新作アプリ『パズオペ』がSocial Game Infoに掲載されました。
http://gamebiz.jp/?p=130913

この記事は、こちらから発信した新作リリースの情報をソースにしています。
これまでも何度か開発したアプリがレビューサイトなどに取り上げてもらいました。
そこで、どのような依頼をすると掲載してもらえるのか参考までにご紹介します。


1.アプリの概要を端的に


アプリの内容を説明するとついつい長くなりがちです。
でも、長い文章は多くの人が読む気をそがれてしまいます。

そこで、まず概要として端的にまとめて、詳細な内容と別にします。
具体的には100字程度、または3行で。

今回掲載された記事も私が書いた概要がほぼそのまま使われています。



2.スクリーンショットを提供


アプリを記事にするときには画面のスクリーンショットが必要になります。
でも、わざわざライターが用意するのは面倒のはずです。
そこで、最初から使えそうなスクリーンショットをサイトにアップしておきます。

私は今回、以下のサイトにまとめてアップしました。
http://sites.google.com/site/kojisatoapple/home/puzzope/shot

掲載された記事では、そこから3点ほど使われていました。



3.プロモーション動画を作る


今までアプリのプロモーション動画を作ってきたのですが、はっきりいってあまり見てもらえていません。
でも、直接ユーザーに見てもらえなくても、レビュアーに対するアプリの説明用としてアピール要素になります。
記事を書く立場からすれば、アプリをダウンロードして実際に起動しなくてもどんなモノか分かるので手間が省けますよね。




私が実際にしているレビュー依頼の仕方は以上です。
このように気をつけても実際に掲載される確立はかなり低いです。
ですが、少しでもそれを上げるためにもレビューする側の立場になって考えるのが良いと思います。


せり上がってくる数字と演算子で計算式を作り消して行く
5つ正解でクリアー、全30ステージの知育系パズルゲーム


2014年6月2日月曜日

新作アプリ『パズオペ』が海外で受けた3つの要因

5/31に新作iPhoneアプリ『パズオペ』をリリースしました。
リリース直後はApp Storeの新着効果で海外からのダウンロードも多少あります。
ですが、今回の新作はやたらと海外のユーザーが多くなっています。


ダウンロードされるだけではなく、ステージ8までとか結構長く遊んでくれています。
そこで、今までのアプリと何が違うのかを上げて、海外で受けた要因を考察したいと思います。


1.スクリーンショットで遊び方の説明

まず、今までApp Storeのスクリーンショットは漠然とプレイ画面のキャプチャを乗せていました。
今回はユーザー目線で何を目的にスクリーンショットを見るのかと考え、自分だったら『どんなゲームなのか』を知るために見ると思いました。
そこで、ヘルプのキャプチャを作る感じで、『遊び方』を説明するスクリーンショットにしました。


また、説明も拙い英語でひたすら『遊び方』を書いています。

------------------------------------------

Let's make calculation formula with Numbers and Operators.
Interesting and simple puzzle game.
Adults and children to enjoy.

When the correct answer, numbers and operators will disappear.
After a period of time, to gradually rise.
When built up to the ceiling, Game Over.

If you correct answer 5, Stage Clear.
Operator is fixed, Appear only odd, Calculation of decimal, And so on.
There are various stages.

Challenge to all 30 stages!

------------------------------------------

これにより、新着でアプリを見つけた人が「なんだか、よくわからん」とダウンロードを止めるのを減らすことができたのではないかと考えられます。


2.シンプルな画面


さて、ダウンロードしてもらっても、遊んでもらえないのでは意味がありません。
そこで画面をシンプルにして、ボタンはボタンらしく大きくしました。



これで、どこをタップすればよいのかが一目瞭然で「なんだか、よくわからん」と遊ぶのを止めるのを減らすことができたのではないかと考えます。


3.分かりやすいアクション


今までは、数字を選択したら文字が変わるだけ、クリアーまでのポイントも表示してあるだけでした。



今回は、数字を選択したら、その数字が飛んで行くアクションをつけました。
また、クリアーまでのポイントも数字が変わるごとに拡大表示するアクションをつけました。


どちらでもゲーム性は変わりませんが、一目での分かり易さが違います。
ゲームのルールを言葉で説明するよりは、触れば分かるという方がとっつき易く「なんだか、よく分からん」を防げるのではないかと思います。



まとめ


今回は、いろんな意味で『分かり易く』改善したのが良かったのではないかと思います。
これは海外向けというよりは、アプリを作る上での基本ですね。
でも、案外おろそかになりがちなので一度見直してみると良いかも知れません。


せり上がってくる数字と演算子で計算式を作り消して行く
5つ正解でクリアー、全30ステージの知育系パズルゲーム