cocos2d-xを利用してゲームを開発してる際に、Android端末の画面の明るさを変更する方法をメモ。
基本的には、通常のAndroid開発でActivityのonCreateで変更する方法と同じである。
cocos2d-xの場合は、srcフォルダ内の[プロジェクト名].javaファイルに記述することになる。
(1) 画面が暗くなるのを防ぐ
srcフォルダ内の[プロジェクト名].javaを開き、onCreate内に以下を記述する。
// 画面が暗くなるのを防ぐ Window window = getWindow(); window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
(2) 画面の明るさを変更する
同様に、[プロジェクト名].javaのonCreate内に以下を記述する。
明るさの指定は0から1のfloat値を設定することで変更できる。
1に近いほど明るくなる。
// 明るさを設定 WindowManager.LayoutParams lp = getWindow().getAttributes(); lp.screenBrightness = [0から1のfloat値]; getWindow().setAttributes(lp);
cocos2dなどから利用できるBox2Dという物理エンジンで物体をグラフィカルに定義できる「Physics Editor」というツールがある。
これを使えば、物理エンジンに使う物体を簡単に定義できるようになり、非常に便利である。
公式サイトはこちらから
そして、このツールの全ての機能を使うにはライセンスを購入する必要があるが、ブログをやっている方には無償でライセンスを配布してもらえる。
以下の条件があるが、当てはまる場合は申請することができる。
- ブログを持っている
- 半年以内に5つ以上の記事を投稿していて、1ページ以上の長さがある。
- ブログのテーマが「ゲーム/ソフトウェア/WEBプログラミング/アプリケーション」についてである。
Cocos2d-xに入門しようとしたところハマったのでメモ。
Cocos2dの導入方法を調べると、色々なサイトで
sudo ./install-templates-xcode.sh
を実行してXcodeへインストールするということが書いてありました。
しかし、cocos2d-x-2.2ではinstall-templates-xcode.shが存在せず、これを実行することが出来ません。
代わりに、以下の方法でプロジェクトを作り、Xcodeで開けば良いということが分かりました。
1. ターミナルでcocos2d/tools/project-creatorに移動する 2. python create_project.py -project [プロジェクト名] -package [パッケージ名] -language [言語名 (cpp |lua | javascript) ]; を実行する 3. cocos2d-xフォルダ下のprojectsフォルダにプロジェクトが作られるので、それを開く 4. プラットフォーム別にフォルダが作られるので、適したものを開く
以上です。
こちらを参考にしました。
Android向けの「インベーダーくずし」というゲームを公開しました。
————————————————————————————————
・ブロックくずしで地球をまもれ!
地球にせまり来るインベーダーから地球をまもって下さい。
ブロックくずしのようにボールをバーで跳ね返すことで敵を倒しましょう。
・敵のビームを跳ね返して反撃
インベーダーはビームを撃ってくることがあります。
地球をまもるために、そのビームを避けずに跳ね返してください。
・ボス敵との激戦を勝ち抜け
特定のステージでボス敵が登場します。様々な攻撃をしてくるボスとの激戦を勝ち抜いてください。
また、このゲームには2つのモードがあります。
1つ目の「アーケード」は、ステージを進めながらハイスコアを競うモードです。
このモードには3体のボスが登場します。
2つ目の「VSボス」は、ボス達と連続して戦うモードです。
アーケードに登場する3体のボスを倒すと、このモードにのみ出現する最後のボスが登場します。
あなたは最後のボスを倒してエンディングを見ることができるでしょうか?
————————————————————————————————
インベーダーくずしをダウンロード
Google Play Game Serviceのリーダーボードや実績にはデバッグ用の機能が用意されていない様で、ゲームサービスの公開前にデバッグ中に登録された記録をリセットする方法がありません。
しかし、リーダーボードは簡単にリセットすることが出来たのでメモします。
1 . Developer Consoleよりゲームサービス内のリーダーボードを選択する。 2 . リセットしたいリーダーボードの情報を一時的に変更して保存する。 (ハイスコアの順番付けなどを一時的に変更する) 3 . リーダーボードがリセットされたことを確認して、設定を元に戻す。
以上です。
今作っているゲームに、GooglePlayGameServicesを使おうとしたところ、色々と問題が発生したのでメモ。
今回は、特に解決に時間がかかったタイトルの問題について書きます。
BaseGameActivity.beginUserInitiatedSignIn()をしても、onSignInSucceeded()とonSignInFailed()が両方とも呼ばれずサインイン出来ない。
しかし、一度画面を消した後などに復帰すればそのタイミングでサインインがされるという事がありました。
この問題は、onActivityResult()をオーバーライドしている場合に起こります。
Activityをextendsしている場合では、super.onActivityResult()を呼ぶ必要はありませんが、
BaseGameActivityのbeginUserInitiatedSignIn()の処理を完了するためにsuper.onActivityResult()を呼ばなければいけません。
たったこれだけの原因ですが、なかなか解決が困難でした。
@Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { // これが無ければonSignInSucceeded()・onSignInFailed()が呼ばれない super.onActivityResult(requestCode, resultCode, intent); /** 処理 **/ }
こちらを参考にして解決出来ました。
Google Play Game Services: strange sign in behavior
SurfaceViewを使ってゲームを作った時に使った画面サイズに合わせて描画する方法をメモしておきます。
Androidでは様々な画面サイズの端末が存在するため、ゲームなどでの描画処理に一工夫が必要です。
まず、Canvas.scaleを使って画面サイズに合わせて全体を拡大縮小します。
これだけでは画面の左上に偏るので、画面の中心に描画されるようにcanvasを移動させます。
移動にはCanvas.translateを使います。
使用する関数 Canvas.scale(x方向の倍率, y方向の倍率) Canvas.translate(x方向の移動量, y方向の移動量);
コード例
/** 最初にゲーム内の画面サイズを決めておく **/ final float VIEW_WIDTH = 600 final float VIEW_HEIGHT = 900;
決めた画面サイズをもとに倍率を計算します。縦横比が異なる場合は小さい方に合わせます。
/** SurfaceCreatedに記述 **/ float scaleX = getWidth() / VIEW_WIDTH; float scaleY = getHeight() / VIEW_HEIGHT; scale = scaleX > scaleY ? scaleY : scaleX; // onCreate内ではgetWidth()が0を返すので上手くいかない。
この倍率から、拡大・縮小して描画します。
/** 描画部分で記述 **/ Canvas c = holder.lockCanvas(); c.translate(getWidth() - VIEW_WIDTH)/2*scale, (getHeight() - VIEW_HEIGHT)/2*scale); // 画面の中央になるように移動させる c.scale(scale, scale); // 端末の画面に合わせて拡大・縮小する // 描画処理 holder.unlockCanvasAndPost(c);
また、ゲームを作る場合は、これだけではゲームのタッチ入力を取得するときに問題が起きます。
タッチ入力の座標は拡大・縮小されないため、ここにズレが生じるからです。
そこで、タッチ入力の座標に関しても倍率を使って調整する必要があります。
/** (例) イベント部分で記述 **/ public boolean onTouch(View v, MotionEvent event) { touchedX = event.getX() / scale; touchedY = event.getY() / scale; }
MediaPlayerを使って動画プレイヤーを作っていたのですが、seekTo()が上手く動いていない様子でした。
seekTo()を使うと指定した位置からずれた位置に移動してしまいます。
まだ解決はしていませんが、原因や試したことをメモしておきます。解決策をご存知ならば是非教えて下さい。
色々と調べた結果、次のような書き込みを見つけました。
Seek to Key frame – The video when encoded will usually have something called as the I frame or the Key frame, it means that this frame has lot of information and can be used to decode a frame in its entirety. To reduce the amount of space all the frames are not encoded as key frames instead they are encoded as P (Predicted) frames or predicted frames, meaning you can decode a P frame with the help from the key frame.
(http://stackoverflow.com/questions/6845161/accuracy-of-mediaplayer-seektoint-msecsより)
MediaPlayerのseekTo()では、指定した時間の近くのキーフレームにしか移動できないようです。
0.1秒ごとにseekTo()してみると、一定の間は同じ場所に飛んで、急に少し先の場所に飛ぶ、というのが繰り返されていたのですが、このためだと思われます。
そこで、seekTo()で移動した位置から実際に指定した位置まで再生して移動させようと試したのですが、これも上手くいきませんでした。
こうしたかった
mediaPlayer.seekTo(seekPosition); int diff = seekPosition - mediaPlayer.getCurrentPosition(); mediaPlayer.start(); try { Thread.sleep(diff); } catch (InterruptedException e) { e.printStackTrace(); } mediaPlayer.pause();
しかし、getCurrentPosition()からはseekPositionが返ってきてしまって失敗。
もう少し試してみて何か分かったら追記します。