株式会社八角研究所 > Androidリバーシ

エンジニア募集中!

独立心旺盛で、新しい技術で新しいWebサービスを作りたいと思っているけれど、ひとりでやることに限界を感じているフリーのエンジニアの方。あなたの期待にこたえられる仲間と環境を、八角研究所なら提供できると思います。社員としてではない関わり方も、あるかもしれません。

2009年06月25日 10:27

Androidリバーシ * * * *

by tunakan

Tags: Androidアプリ作りたい Java Android

ソースをダウンロード:Reversiソース 今日、社内の有志が集まり、Androidの発表会をしました。といっても、まだAndroidを始めたばかりなので、それぞれ思い思いのプログラムを作って発表するというものでした。私は描画部分に興味があったのでリバーシを作ることにしました。

つくりかた

普通に作ってもつまらないので、なるべく移植性を高くするような作りにしようと思いました。そこでボード状態の管理や、AI等のゲームのコアとなる部分と描画処理やキー操作などの環境依存の部分を分けて設計しました。 コアとなるクラスは、以下のクラスです(クリックで拡大)。ソースコードは簡単なので略。

 

reversi.cld

 

リバーシは、静的なゲームなのでアクションゲームのように毎フレーム更新するような仕組みは不要です。ゲームに何らかの変化があったときだけ画面を更新すればよいのです。この部分は、Javaではおなじみのリスナを使用しました。ゲームスレッドで何らかの状態が変化した時、描画スレッドにイベントが通知されます。本来であれば、イベントクラスも作成して、もう少し詳しい情報(現在のプレイヤーや裏返った石の場所等)も渡してあげるべきなのですが、今回は、手を抜きました。 このゲームクラスを使用したAndroidのソースは下記のようになります。

package net.hakkaku.android.reversi;

import net.hakkaku.reversi.Board;
import net.hakkaku.reversi.BoardPoint;
import net.hakkaku.reversi.Game;
import net.hakkaku.reversi.SimpleAI;
import net.hakkaku.reversi.Stone;
import net.hakkaku.reversi.Game.OnGameStateChangeListener;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;

public class Reversi extends Activity {

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		final Game game = new Game();

		ReversiView reversiView = new ReversiView(this, game.getBoard());
		setContentView(reversiView);

		TouchPlayer touchPlayer = new TouchPlayer();
		reversiView.setOnTouchListener(touchPlayer);

		//プレイヤを設定
		game.setPlayer(Stone.Black, touchPlayer);
		//game.setPlayer(Stone.White, touchPlayer);
//		game.setPlayer(Stone.Black, new SimpleAI());
		game.setPlayer(Stone.White, new SimpleAI());

		game.setOnGameStateChangeListener(reversiView);

		//ゲームスレッド開始
		new Thread(game).start();

	}

	class ReversiView extends View implements OnGameStateChangeListener {

		private Board board;

		public ReversiView(Context context, final Board board) {
			super(context);
			this.board = board;
			setBackgroundColor(Color.GREEN);
			this.invalidate();
		}

		private float getCellSize() {
			int width = getWidth();
			int height = getHeight();

			return width < height ? width / 8 : height / 8;
		}

		/**
		 * 画面上の座標からボード上の座標に変換する。
		 * @return
		 */
		public BoardPoint getScreenToPoint(final float screenX, final float screenY) {

			float cellSize = getCellSize();
			int x =  (int)(screenX / cellSize);
			int y =  (int)(screenY / cellSize);

			return  (0 <= x && x < 8 && 0 <= y && y < 8)?new BoardPoint(x,y):null;
		}

		@Override
		public void onDraw(Canvas canvas) {
			super.onDraw(canvas);

			Paint pBlack = new Paint(Paint.ANTI_ALIAS_FLAG);
			pBlack.setColor(Color.rgb(0, 0, 0));
			Paint pWhite = new Paint(Paint.ANTI_ALIAS_FLAG);
			pWhite.setColor(Color.rgb(255, 255, 255));

			float cellSize = getCellSize();
			// draw lines
			for (int i = 0; i < 9; i++) {
				canvas.drawLine(i * cellSize, 0, i * cellSize, 8 * cellSize,
						pBlack);
				canvas.drawLine(0, i * cellSize, 8 * cellSize, i * cellSize,
						pBlack);
			}

			// draw stones
			for (int y = 0; y < 8; y++) {
				for (int x = 0; x < 8; x++) {
					final Stone stone = this.board.stoneAt(x, y);
					if (stone == Stone.White) {
						canvas.drawCircle((x + 0.5f) * cellSize, (y + 0.5f)
								* cellSize, cellSize * 0.40f, pBlack);
						canvas.drawCircle((x + 0.5f) * cellSize, (y + 0.5f)
								* cellSize, cellSize * 0.36f, pWhite);
					} else if (stone == Stone.Black) {

						canvas.drawCircle((x + 0.5f) * cellSize, (y + 0.5f)
								* cellSize, cellSize * 0.40f, pBlack);
					}
				}
			}
		}

		private Handler handler = new Handler();

		public void onGameStateChanged() {
			handler.post(new Runnable() {
				public void run() {
					invalidate();
				}
			});
		}
	}

}

android

 

ちなみにSwing版

swing

つくってみて

実は、Android版をほとんど作り終えてから、Swing版に移植したのですが移植にかかった時間は20分ほどでした。AndoridのCanvasクラスとSwingのGraphics(Graphics2D)クラスのAPIがかなり似ていたので、コピペ&微修正であっさりと動作しました。 Androidは、Swing(AWT)のコード資産の流用も比較的容易な、良いプラットフォームだと思いました。

この記事の執筆者

九州男児 tunakan 28歳 入社2年目

内臓が全般的に弱いです。データベースは苦手なのに変なデーターベースに当たることが多い気がします。

この人の会社をみる この人関連のイベントをさがす この人と一緒にはたらく

この日記にコメントする

(メールアドレスは公開されません。メールで返答が欲しい場合などに入力してください)

このエントリへのトラックバックURL

コメント

コメントはありません

トラックバック

トラックバックはありません

メンバー紹介

sugimaru

sugimaru

すぎまるです。22時のシンデレラです。

boy

boy

少年です。 18歳以下(嘘)でも立派に社員です。 よろしくおねがいします。

tunakan

tunakan

内臓が全般的に弱いです。データベースは苦手なのに変なデーターベースに当たることが多い気がします。