Android SDK で,ゲームを作る (1) [プログラム三昧]
Android SDK を使って,ゲームを作ってみました.その昔,アプレットで作成した「数字探しゲーム」の焼き直しです.ボタンの並べ方がわからないので, GridView に TextView を並べてみました.不完全ながらも,ゲームとして機能しそうなことがわかってきたので,ここに足跡を残します.
main.xml の記述
このアプリケーションは,4個の部品を縦に配置して作られています.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center" > <TextView android:id="@+id/title" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/app_name" android:gravity="center" android:layout_margin="10dp" /> <GridView android:id="@+id/content" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" android:columnWidth="60dp" android:numColumns="auto_fit" android:verticalSpacing="10dp" android:horizontalSpacing="10dp" android:stretchMode="columnWidth" android:gravity="center" android:background="#333333" /> <TextView android:id="@+id/status" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="" android:gravity="center" android:layout_margin="10dp" /> <Button android:id="@+id/start" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:layout_margin="10dp" android:text="START" /> </LinearLayout>
タイトル行は,ただの TextView です. content と名付けられた GridView には,制御コードでボタンを配置します. status は,現在の状態を示す TextView です.最後の start ボタンをクリックするとゲームが開始されます.
strings.xml の記述
アプリケーションで使用するリソースを strings.xml というファイルに入れて置きます.まだ,有効活用されていないもので.
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Seek Number Game</string> </resources>
これだけです.
SeekNumberActivity.java の記述
ゲームのすべてをひとつのクラスにまとめてみました.コメントも無いし,モデルとビューがゴチャゴチャになったプログラムですが,ご了承ください.
package org.noritan.seeknumber; import java.util.ArrayList; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.view.View.OnClickListener; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.GridView; import android.widget.TextView; import android.widget.AdapterView.OnItemClickListener; public class SeekNumberActivity extends Activity { private int columnCount = 4; private int rowCount = 4; private GridView content; private TextView statusBar; private Button startButton; private ButtonAdapter buttonAdapter; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // Create a model object. buttonAdapter = new ButtonAdapter(this, columnCount, rowCount); content = (GridView) findViewById(R.id.content); content.setOnItemClickListener(buttonAdapter); content.setNumColumns(columnCount); content.setAdapter(buttonAdapter); statusBar = (TextView) findViewById(R.id.status); startButton = (Button) findViewById(R.id.start); startButton.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { buttonAdapter.reorder(); } }); } private class ButtonAdapter extends BaseAdapter implements OnItemClickListener { private int buttonCount; private ArrayList<TextView> buttonList; private ArrayList<TextView> buttonOrdered; private int expected = Integer.MAX_VALUE; public ButtonAdapter( Context context, int columnCount, int rowCount ) { // Save button count for future use. this.buttonCount = columnCount * rowCount; buttonList = new ArrayList<TextView>(); // create and put buttons. for (int i = 0; i < buttonCount; i++) { TextView button = new TextView(context); button.setText(String.valueOf(i+1)); button.setGravity(Gravity.CENTER); button.setPadding(5, 5, 5, 5); buttonList.add(button); } // Initialize ordered button list. buttonOrdered = new ArrayList<TextView>(buttonList); notifyDataSetInvalidated(); } public void reorder() { ArrayList<TextView> buttonLeft = new ArrayList<TextView>(buttonList); buttonOrdered.clear(); for (int i = buttonList.size(); i > 0; i--) { int k = (int)(Math.random() * i); TextView button = buttonLeft.get(k); button.setVisibility(TextView.VISIBLE); buttonOrdered.add(button); buttonLeft.remove(k); } notifyDataSetInvalidated(); expected = 0; statusBar.setText("GO!!"); } @Override public int getCount() { return buttonCount; } @Override public Object getItem(int position) { return null; } @Override public long getItemId(int position) { return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { return buttonOrdered.get(position); } @Override public void onItemClick ( AdapterView<?> parent, View view, int position, long id ) { if (expected >= buttonCount) { // Nothing is expected. return; } // Select a button expected as next choice. TextView buttonExpected = buttonList.get(expected); if (view == buttonExpected) { // Right selection. // Make the right button invisible. buttonExpected.setVisibility(View.INVISIBLE); notifyDataSetInvalidated(); // point next button to be expected. expected++; if (expected >= buttonCount) { // All buttons are clicked. statusBar.setText("Finished !!"); } } } } }
START ボタンをクリックすると, TextView がランダムに配置されます.ユーザが 1 から順に TextView を押して消していって,最後まで消せたら,完了です.完了までの時間を競わせたいのだけど,タイマ機能は,まだはいっていません.
GridView に並べた部品をクリックすると「選択」してしまうので,このゲームの用途に使用するべきではないことがわかってきました.次は,他の Layout を試してみます.
参考サイト
- Hello, Android
- Android 版, "Hello World" は,各種 Layout オブジェクトの使い方実例まで付いています.こいつらを,片っ端から試してみりゃいいわけだ.
R.id.content
R.id.status
R.id.start
以上三つに
id cannot be resolved or is not a field
というエラーが出ます。
どうか御教授ください・・・。
by moni (2010-10-29 15:28)
moniさん,いらっしゃいませ.
クラス R は, Android の開発環境が main.xml の記述をもとに自動的に作成してくれます.作成された Java のコードは,通常のソースファイルが入っている src フォルダではなく, gen[Generated Java Files] フォルダに配置されます.
ファイルの作成は, aapt によって自動的に作成されると R.java ファイルに書いてあり,コンパイルの前提条件として aapt が実行されているものと思われます.プロジェクトを作成する時に "New → Android → Android Project" を選ぶと,このあたりの設定も自動的に提供されます.どこで, aapt の実行を制御しているのかは,今日は探し出せませんでした.
by noritan (2010-10-30 02:07)