Android Surface Viewゲーム開発例

3716 ワード

複雑なゲームを開発する必要があり、プログラムの実行効率が高い場合、Viewクラスはニーズを満たすことができません.この場合、Surface Viewクラスで開発する必要があります.
例えば,速度が要求されるゲームでは,Viewクラスが需要を満たすことができなくなり,その場合にはSurfaceViewクラスを用いて開発しなければならない.例えば、スピードが要求されるゲームでは、デュアルバッファを使用して表示することができます.ゲームの背景、人物、アニメーションなどはキャンバスに描画する必要がありますが、Surface Viewはキャンバスに直接アクセスできます.Surface Viewはフォームコンポーネントではなくピクセルを直接描画する必要があるアプリケーションに提供されます.各Surfaceは、ViewおよびSurfaceでの描画操作を管理するためにCanvasオブジェクトを作成します(ただし、プロパティは常に変更されます).
具体例:
Activity
public class Activity01 extends Activity {
	
	GameSurfaceView gameView = null;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
       
        gameView = new GameSurfaceView(this);
        setContentView(gameView);
    }
}
GameSurfaceView
public class GameSurfaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable{

	private Activity01 mActivity = null;
	
	private SurfaceHolder mHolder = null;
	private Thread mThread = null;;
	private boolean mLoop = false;
	
	private Canvas mCanvas = null;
	private Paint mPaint = null;
	private long drawStartTime = 0, drawCostTime = 0, drawTotalTime = 30;
	
	private float x, y;
	private int screenWidth = 480, screenHeight = 800;
	
	public GameSurfaceView(Context context) {
		super(context);

		mActivity = (Activity01)context;
		
		mHolder = this.getHolder();
		mHolder.addCallback(this);
		setFocusable(true);
	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		mPaint = new Paint();
		mPaint.setColor(Color.CYAN);
		mLoop = true;
		
		new Thread(this).start();
	}

	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
		screenWidth = width;
		screenHeight = height;
		
		x = screenWidth / 2;
		y = screenHeight / 2;
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		mLoop = false;
	}

	@Override
	public void run() {
		while(mLoop){
			drawStartTime = SystemClock.uptimeMillis();
			
			synchronized (mHolder) {
				try {
					mCanvas = mHolder.lockCanvas();
					onDraw();		// repaint
				} catch (Exception e) {
					e.printStackTrace();
				} finally {
					if(mCanvas != null){
						mHolder.unlockCanvasAndPost(mCanvas);
					}
				}
			}
			
			drawCostTime = SystemClock.uptimeMillis() - drawStartTime;
			Log.i("drawCostTime", "drawCostTime = " + drawCostTime);
			try {
				if(drawCostTime < drawTotalTime){
					Thread.sleep(drawTotalTime - drawCostTime);		// sleep elapse time
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	private void onDraw(){
		if(mHolder == null && mPaint == null){
			return;
		}
		
		mPaint.setAntiAlias(true);
		mPaint.setAlpha(100);
		
		mPaint.setColor(Color.CYAN);	// paint background color
		mCanvas.drawRect(0, 0, screenWidth, screenHeight, mPaint);
		
		mPaint.setColor(Color.BLUE);	// paint foreground color
		mCanvas.drawCircle(x, y, 50, mPaint);
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		super.onTouchEvent(event);

		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			this.x = event.getX();
			this.y = event.getY();
			break;

		case MotionEvent.ACTION_MOVE:
			this.x = event.getX();
			this.y = event.getY();
			break;

		case MotionEvent.ACTION_UP:
			this.x = event.getX();
			this.y = event.getY();
			break;

		default:
			this.x = event.getX();
			this.y = event.getY();
			break;
		}

		return true;	// true then event can be implemented again
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event){
		super.onKeyDown(keyCode, event);
		
		if(keyCode == KeyEvent.ACTION_DOWN){
			this.mActivity.finish();
		}
		
		return true;
	}
}
実行効果:
ソースのダウンロード