ページ 11

AndroidでSurfaceViewを利用したゲーム作成でのActivity

Posted: 2013年2月27日(水) 14:27
by hydrate
AndroidでSurfaceviewを利用したゲームを作っています。
少し大きなプログラムになったのですが、ホームボタンを押して中断してから再びアイコンクリックして中断地点から始めようとすると、とても起動(中断時の画面に戻るの)に時間がかかってしまいます。

調べてみたところ、Activityの動作が重要でホームボタンを押す→再び起動はOnPause()とOnResume()が関係しているとまではわかったのですが、そこからどうすればいいかがわかりません。

ホームボタンを押したらSurfaceviewを一時停止する形にすればよいのではと自分の中では思うのですが方法もわからないので、どうすればよいか教えていただけるとありがたいです。

よろしくお願いします。

Re: AndroidでSurfaceViewを利用したゲーム作成でのActivity

Posted: 2013年2月28日(木) 04:22
by ISLe
スレッドを一時停止するサンプルプログラムを書いてみましたが、これだけで重くなるのが解消するとは考えにくいです。

再始動時に呼ばれるイベントメソッド(onRestart,onStart,onResume)でリソースを読み込んでいるなら、ガベージコレクションで重くなる可能性があります。
その場合は、onPause,onStopでリソースを解放しておけばガベージコレクションが集中しなくなって軽くなるかもしれません。

コード:

package isle.example.suspend;

import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.SurfaceView;

public class MainActivity extends Activity {

	MySurfaceView mysv;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		mysv = new MySurfaceView(this);
		setContentView(mysv);
	}
	@Override
	protected void onStart()
	{
		super.onStart();
		mysv.suspend(false);
	}
	@Override
	protected void onStop()
	{
		super.onStop();
		mysv.suspend(true);
	}
	@Override
	protected void onDestroy()
	{
		super.onDestroy();
		// スレッドを安全に終了させるよう念のため
		mysv.suspend(false);
	}

	private class MySurfaceView extends SurfaceView implements Runnable
	{
		Activity activity;
		volatile boolean suspend = false;

		public MySurfaceView(Activity activity) {
			super(activity);
			this.activity = activity;
			new Thread(this).start();
		}

		public void suspend(boolean b) {
			// 待機フラグをセット
			suspend = b;
			if (!b) {
				// 待機フラグが真でないなら待機中のスレッドを起こす
				synchronized (this) {
					notifyAll();
				}
			}
		}

		@Override
		public void run() {
			int count = 0;
			Log.d("MAINLOOP", "start!!!");
			while (!activity.isFinishing()) {
				Log.d("MAINLOOP", ""+(++count));
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				
				// 待機フラグが真であれば待機する
				synchronized (this) {
					while (suspend) {
						try {
							wait();
						} catch (InterruptedException e) {
						}
					}
				}
			}
			Log.d("MAINLOOP", "finish!!!");
		}
	}
}

Re: AndroidでSurfaceViewを利用したゲーム作成でのActivity

Posted: 2013年2月28日(木) 07:53
by hydrate
スレッドの一時停止プログラムを適用してみたところ、起動が重い点は解消しました。ありがとうございました!

ただ、ホームを押す→またゲームに戻る を行うと、画面遷移の際に別の画面が一瞬ちらつくようになってしまいます。
中で複数のSurfaceviewが動いているのでしょうか。

参考になるかはわかりませんが、画面遷移はrunの中で変数により描画関数を変えている形式です。この関数が変わるような画面遷移の時に別の画面(タイトルなど)が一瞬ちらつきます。

コード:

        try{
    			
    			switch(scene){
    			//スタート画面
            	case 0:
            		Start();
            		break;
            	//ゲーム中画面
            	case 1:
            		GameEasy();
            		break;
            	//結果表示画面
            	case 2:
            		End();
            		break;
            	//ゲーム中画面ノーマル
            	case 3:
            		GameNormal();
            		break;
            	//オプション
            	case 4:
            		Option();
            		break;
            	//記録
            	case 5:
            		Record();
            		break;
            	//ゲーム中画面ハード
            	case 6:
            		GameHard();
            		break;
            	//ヘルプ画面
            	case 7:
            		Help();
            		break;
            	}
いくつも質問すいません。重ね重ねよろしくお願いします。

Re: AndroidでSurfaceViewを利用したゲーム作成でのActivity

Posted: 2013年3月01日(金) 00:22
by ISLe
ちらつくのは遷移する前や後の画面とは別の画面でしょうか。
アプリの待機中にプロセスが破棄される場合もあるのですが、そのあたりの対策は行われているのでしょうか。

いずれにしても、あちこちで参照を保持しているようなプログラムだと、いつのまにかスレッドがいくつもできているということはあります。
あと参照関係だとCanvasの使い回しとか。

ADTで開発しているなら、Eclipseのデバッグパースペクティブのスレッド一覧でスレッドが増えていくのが分かると思いますが。

Re: AndroidでSurfaceViewを利用したゲーム作成でのActivity

Posted: 2013年3月01日(金) 15:55
by hydrate
Eclipseでスレッドの挙動を見たところ複数起動していました。
プログラムのスレッドを生成する位置をいじることによりひとつしか起動しないようになりちらつきが解消しました。
色々教えて頂きありがとうございました。