× [PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。 |
Eclipseは起動が遅い。
起動したときに必ずSDK Content Loaderが走り、それが100%になるまでビルドその他の処理は実行できない。 そしてこれが遅い。 ネットワークが遅いとさらに遅い。 ネットワークが繋がっていても、 SDK Content Loaderが0%のまままったく進まないときがある。 そのときは、以下を参考。 参考 要するに workspace/.metadata/.plugins/org.eclipse.core.resources/.projects をまるごと消してしまう。 乱暴だ…。 削除してからEclipseを起動すると、プロジェクトの中身がなくなっている。 (プロジェクト名だけ残して、中身のファイルはなくなる) Refreshコマンドを実行しても戻らない。 一度消して、再度プロジェクトの追加を行うことになる。 (File->New->Other->Android Project from Existing Code) ライブラリプロジェクトも漏れなく消えるので、追加してBuild Projectをお忘れなく。 workspaceディレクトリ以下にあるプロジェクトは自動で復活するらしい。 あとは、adbプロセスを削除するという手もあるようだ。 PR |
インテントを使ってYouTubeアプリを起動するだけ。
youtubeIdは動画ID。URLに含まれているもの。 インテントが無いときは、PlayストアのYouTubeアプリのページに飛ばしたりするとよいかと思われる |
testflightが使えなくなり、iTunesConnectから使用するように変わった。
使い方のイメージとしては、「サブミット前の確認」。 まず、iTunesConnectに行き、最新のAppleの条件をAgreeする必要がある。 これをしなくても先のページに進めるが、アプリを登録するボタン(ヘッダの「+」ボタン)を押しても何も出ない、という妙なところで止められてしまう(不具合に見える。こんなところでも分からないと詰まってしまうようなところ) Agreeしたら、iTunesConnectにアプリを登録する。 DeveloperCenterでDistribution用のProvisioning Profileを作っておく。 このとき、AdHoc用ではなく、Distribution用を作ることに注意。 AdHoc用でもこの先の手順でサブミットできるし、testflightで配布もできるのだが、testflightからインストールできるのが、Provisioning Profileに登録されているデバイスだけに限定されてしまうので不便なだけ。 で、Distribution用のProvisioning ProfileでアプリをXcodeでアーカイブする。 できたらSubmit。 少し待つと、iTunesConnectにアプリが載る。 ここで「プレリリース」をクリック。 内部テスターの欄に、testflightで配布したいメンバーのappleIDを登録する。 (開発メンバーは基本的に内部テスター。外部テスターというのもあるが、これは実際の顧客など外部の人に使ってもらうことを想定しており、外部テスターに配布するためにはAppleの審査を通した後配布するという手順を踏むことになるようだ) で、「TestFlightベータ版テスト」のスイッチをONにし、 招待メールを送信。 これで、内部テスターのappleIDのアドレスにメールが届く。 iPhone、iPadなどでそのメールのリンクを踏むと、testflightのアプリに飛び、件のアプリがインストールできるページになる。 晴れてインストールできるというわけ。 たまにメールが飛ばないことがあるので、「TestFlightベータ版テスト」をOFF→ONにしたらメールが行ったということがあった。 また、上げ直す際は必ずビルド番号を上げておくこと。 あくまでサブミットへの手順の一部なので、ビルド番号をあげておかないと、XcodeからiTunesConnectへのアップロードができない。 再度アーカイブし直しという面倒なことになるので注意。 バージョンはあげなくていい。 というか、上げるとストアの情報など再設定が必要になったりtestflight的にも新しいもの扱いに鳴って再度招待メールを飛ばす必要があったりと面倒。 本当にアプリとしてバージョンをあげるときだけにとどめよう。 |
cocos2d-xでスクリーンショットを撮影する方法。
ios標準の機能だと、こんな感じになる。
参考 しかし、この方法だとcocos2d-xで描画している画面は映らない。(上記コードで言うと、[aWindow.layer renderInContext:context]; の部分) cocos2d-xの3.2以降だと、便利な機能がついている。 cocos2d::utils::captureScreen() がそれで、 以下コード例。
captureScreenの第1引数が完了時に実行するラムダ式。第2引数がファイル名。 キャプチャーが取れるとラムダ式の中が呼び出される。 ラムダ式の第2引数のfilePathは、保存したファイルの完全な絶対パスが入っている。 このパスを使って、スプライトをゲーム中に表示したり、Twitterにシェアしたりすることができる。 スプライトの場合は、通常通り Sprite::create(filePath); とすればよい。 ただし、そのままだと2回目以降、スクリーンショット画像が変化しない(1回目のスクリーンショットが表示されてしまう) これは、Sprite::create()の中で自動的にテクスチャがキャッシュされているからだ。
そこで、毎回テクスチャキャッシュを削除すればよい。
上記コードをSprite::create()の前に実行すればOK。 TwitterやFacebookにシェアする場合、UIImageインスタンスを作成する。
アセットではなくファイルパスなので、以下の書き方ではUIImageを作成できないので注意。 UIImage* image = [UIImage imageNamed:[NSString stringWithUTF8String:filePath]]; 総合すると、スクリーンショットを撮ってTwitterに投稿するのは以下のようなコードになる。
|
Androidはiosと比べてスレッドに気をつけて実装する必要がある。
描画処理をメインスレッドで実行するとすぐ落ちる。 runOnUiThread()とは仲良くなっておこう。
cocos2d-xを使っている場合 cocos2d-xの処理は、できるだけメインループである
から呼び出される中で実行した方が良い。 といっても、普通に実装していれば大抵はこの中から呼び出される。 JavaからnativeのCメソッドを呼び出すような場合は、この限りでない。 例えば、Twitterでシェアしたのを確認した後、ゲーム内でインセンティブを与えたいといったようなとき、Java側からnativeメソッドを呼び出すようなことになるが、 このときはメインループから呼び出されない。 こういう場合、cocos2d-x内で画像読み込みや音声再生など、リソースにアクセスするような処理を行うと、 セグメンテーションエラーが起きたり、(Fatal signal 11 (SIGSEGV) at 0x00000000) 処理が止まったりする(タッチが反応せず、他のスレッドで描画や音声はそのまま再生できてたりする)。 そういうときは、Javaから呼び出すnativeメソッドではフラグを立てるだけにしておいて、 メインループからフラグをチェックしてインセンティブの処理を行う、のようにすれば回避できる。 |
Androidで、ビューの位置をpx単位で正確に指定したい時の方法。
ゲームアプリの広告表示の場合、 ゲーム部分はフレームワークが自動で拡大縮小してスクリーンサイズに合わせているため、 Androidのxmlでレイアウト指定するものと併せられない。 そこでpxを計算して表示することになる。 方針としては、marginでpx指定することになる。
ポイントとしては、 「pxでの指定」になること(dpではない) 途中計算で使っているdisp.getHeight()はpxの値が返ってくる。 また、MarginLayoutParams.bottomMarginもpx指定となっている。(top,left,rightも同様) |
iOSでYouTubeの動画を再生するときの方法。
画面でボタンをクリック→全画面で動画再生→完了ボタンを押したら元の画面に戻る という流れにしたい。 WebViewを使うのが早い、という記事が多いが、WebViewだと完了ボタンを押したときに画面を閉じるということができない。 WebViewはhtmlを表示しているだけなので、動画コンテンツを再生しているかどうかは感知できない。だから完了ボタンを押したときに、明示的にWebViewを閉じる命令を出す必要があるが、そもそも完了ボタンを押したことを知ることができない。 そこで、MPMoviePlayerViewControllerを使う。 モーダルビューコントローラを表示し、そこで動画(URLで指定)を再生できる。完了したらモーダルは閉じる。これだ! ただし注意。YouTubeのURLそのままだとiOSで再生できない。 再生可能な形式のURLを取得してくる非公式ライブラリがあるのでそれを使う HCYoutubeParser 以下のようになる。
その他、WebViewでいい場合は 参考 |
applicationDidEnterBackgroundの中とかでローカル通知のスケジューリングを行う。
アプリを起動したときにスケジュール済みの通知を全削除したりするが、そのタイミングは applicationWillEnterForeground ではいけない。 必ず通るとは限らないからである。 起動 →バックグラウンドへ(ここで通知スケジューリング) →他のアプリを起動するなどしているうちに、アプリが自然にシャットダウンする →アプリを起動 →バックグラウンドへ(ここで通知が2重にスケジューリングされる!) というわけで、通知を全削除する( [[UIApplication sharedApplication] cancelAllLocalNotifications]; )箇所は、 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions; - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation; - (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url; - (void)applicationWillEnterForeground:(UIApplication *)application; の4つ…とかはめんどいので、 applicationDidEnterBackground でスケジューリング登録する直前に全削除、が一番楽であろう。 |
RPGとかノベルゲームでよくある、1文字ずつ表示する仕組み。
◯cocos2d-xの内部 文字を表示するのはLabelクラス。 これはSpriteBatchNodeの一種で、1文字を1つのSpriteで保持している。 文字数分だけ、子ノードにSpriteを持っているという構造になっている。 で、◯文字めのSpriteを返す getLetter() というメソッドがある。これを使う。
という感じ。 ◯注意点 labelは使い回しできない。 一度runActionして1文字ずつ表示した後、 label->setString("another string"); して、再度runActionすると、文字の表示位置がずれまくり、そして落ちるという謎現象が起きた。 その場合、label->removeFromParent(); してから再度 Label::create() すれば正しく動いた。 ◯注意点その2 int textLength = label->getStringLength(); の文字数が合っていない。textLengthの文字数だけでwhileをまわすと、たまに末尾の1〜2文字が表示されないことがあった。 どうやらcocos2d-x内部での文字の数え方に差異があるようだ。 面倒なので、textLength + 2 でループをまわしたりした。 ちゃんと調べたい |
白くフェードアウトする場合、スプライトに
と記述してある可能性がある。 SpriteBatchNodeを使用しているかどうかでも変わる(使用していると白くはならない)
|