ActionBar の表示
requestWindowFeature(Window.FEATURE_NO_TITLE);
requestWindowFeature(Window.FEATURE_ACTION_BAR);
ActionBar が表示されるようになりました。しかし ActionBar の高さの分だけゲーム画面が下にずれてしまっているため、ボールがゲーム画面外へと消えてしまいました。
画面サイズは FrameLayout から取得するように変更しました。このとき取得するタイミングに注意が必要で onCreate() で取得すると値が 0 になってしまうため、onWindowFocusChanged() で取得するようにします。Ball と Hole の生成も同じメソッド内で実施しています。
@Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); width = framelayout.getWidth(); height = framelayout.getHeight(); ball = new Ball(this); ball.x = width / 2; ball.y = height / 2; hole = new Hole(this); Random rnd = new Random(); hole.x = rnd.nextInt( width-(2*(hole.r+ball.radius)))+hole.r+ball.radius; hole.y = rnd.nextInt( height-(2*(hole.r+ball.radius)))+hole.r+ball.radius; framelayout.addView(hole); framelayout.addView(ball); }
ボールが上手くゲーム画面内に収まるようになりました。
"menu_main.xml" の編集
最初にプロジェクトを作成した際に、一緒に作成されるメニュー項目の設定ファイルを編集します。[res/menu/menu_main.xml] を開き以下のように修正します。"Settings" は最初から定義されているので、リトライ処理用のメニュー項目を追加しています。
<menu xmlns:android= "http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity"> <item android:id="@+id/action_settings" android:title="@string/action_settings" android:orderInCategory="100" android:showAsAction="never" /> <item android:id="@+id/action_retry" android:title="Retry" /> </menu>
ActionBar にメニュー項目が表示されるようにするため MainActivity に以下のコードを追加します。
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_main, menu);
return super.onCreateOptionsMenu(menu);
}
"Retry" と "Settings" のメニュー項目が表示されました。
リトライ処理の追加
メニュー項目の "Retry" を押したときの処理を MainActivity に追加します。先ほどの状態だとメニュー項目の表示と非表示を繰り返すたびに addView() が実行され、表示がおかしくなっていたためフラグを使って最初と "Retry" を押したときだけ addView() が実行されるように修正しました。
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.action_retry) {
framelayout.removeAllViews();
handler.removeCallbacks(this);
init_flag = false;
}
return super.onOptionsItemSelected(item);
}
Boolean init_flag; @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (!init_flag) { width = framelayout.getWidth(); height = framelayout.getHeight(); ball = new Ball(this); ball.x = width / 2; ball.y = height / 2; hole = new Hole(this); Random rnd = new Random(); hole.x = rnd.nextInt( width - (2 * (hole.r + ball.radius))) + hole.r + ball.radius; hole.y = rnd.nextInt( height - (2 * (hole.r + ball.radius))) + hole.r + ball.radius; framelayout.addView(hole); framelayout.addView(ball); init_flag = true; handler.postDelayed(this, 3000); } }
以上で、正常にリトライ処理ができるようになりました。"MainActivity.java" のソースコードは以下のようになっています。
public class MainActivity extends Activity implements Runnable, SensorEventListener {
SensorManager manager;
Ball ball;
Hole hole;
Handler handler;
int width, height, time;
float gx, gy, dpi;
FrameLayout framelayout;
Boolean init_flag;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_ACTION_BAR);
framelayout = new FrameLayout(this);
framelayout.setBackgroundColor(Color.GREEN);
setContentView(framelayout);
time = 10;
handler = new Handler();
init_flag = false;
dpi = getResources().getDisplayMetrics().densityDpi;
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (!init_flag) {
width = framelayout.getWidth();
height = framelayout.getHeight();
ball = new Ball(this);
ball.x = width / 2;
ball.y = height / 2;
hole = new Hole(this);
Random rnd = new Random();
hole.x = rnd.nextInt(width - (2 * (hole.r + ball.radius))) + hole.r + ball.radius;
hole.y = rnd.nextInt(height - (2 * (hole.r + ball.radius))) + hole.r + ball.radius;
framelayout.addView(hole);
framelayout.addView(ball);
init_flag = true;
handler.postDelayed(this, 3000);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_main, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.action_retry) {
framelayout.removeAllViews();
handler.removeCallbacks(this);
init_flag = false;
}
return super.onOptionsItemSelected(item);
}
@Override
public void run() {
ball.vx += (float) (gx * time / 1000);
ball.vy += (float) (gy * time / 1000);
ball.x += dpi * ball.vx * time / 25.4;
ball.y += dpi * ball.vy * time / 25.4;
if (ball.x <= ball.radius) {
ball.x = ball.radius;
ball.vx = -ball.vx / 3;
} else if (ball.x >= width - ball.radius) {
ball.x = width - ball.radius;
ball.vx = -ball.vx / 3;
}
if (ball.y <= ball.radius) {
ball.y = ball.radius;
ball.vy = -ball.vy / 3;
} else if (ball.y >= height - ball.radius) {
ball.y = height - ball.radius;
ball.vy = -ball.vy / 3;
}
if ((hole.x - hole.r < ball.x && ball.x < hole.x + hole.r) &&
(hole.y - hole.r < ball.y && ball.y < hole.y + hole.r)) {
ball.x = hole.x;
ball.y = hole.y;
ball.vx = ball.vy = 0;
ball.invalidate();
} else {
ball.invalidate();
handler.postDelayed(this, time);
}
}
public void onDestroy() {
super.onDestroy();
handler.removeCallbacks(this);
}
@Override
protected void onResume() {
super.onResume();
manager = (SensorManager)getSystemService(
SENSOR_SERVICE);
List<Sensor> sensors =
manager.getSensorList(
Sensor.TYPE_ACCELEROMETER);
if (0 < sensors.size()) {
manager.registerListener(
this, sensors.get(0),
SensorManager.SENSOR_DELAY_NORMAL);
}
}
@Override
protected void onPause() {
super.onPause();
manager.unregisterListener(this);
}
@Override
public void onSensorChanged(SensorEvent event) {
gy = event.values[0];
gx = event.values[1];
}
@Override
public void onAccuracyChanged(
Sensor sensor, int accuracy) {
}
}
リトライ処理が実装でき、ゲームとしての体裁がさらに整ってきました。次は設定画面の作成手順を紹介します。
0 件のコメント:
コメントを投稿