イントロダクション
Robocodeを使用して、Javaプログラミングを始めるきっかけとしてほしい、もしくはJavaという言語で遊べるということを紹介しようと考えました。
以前、Robocodeを紹介する記事を書きました。のでよかったらご覧ください。
そして、実際にワークショップを開きたいと考えております。そのために必要なことをまとめました。
ワークショップを開くための実行準備メモといったところです。
アジェンダ
そもそも「アジェンダ」って何よ?と思い、調べました。
会議で論ずる事項(議題)の表。比喩的に、課題項目。
つまり、「やることリスト」という理解です。
Robocodeアジェンダ
Robocodeのワークショップとして実行しようと考えているのは以下のものです。
- PCにRobocodeをインストールする
- サンプルバトルの起動、およびゲームの内容確認
- 自分のRoboの作成(コードは自動生成される)
4.自分のRoboをバトルに参加させてみる - Roboの動きとコードの内容を見比べて内容を大まかに理解する
- Javaコードを書いて、動きを変えてみる
- 動きを定義するメソッド「run」「onScannedRobot」「onHitByBullet」「onHitWall」の改造をしてみる
- 起動確認と実装アイディアの話し合い
- みんなで作成したRoboで対決する
- ワークショップの感想と今後の目標や、やりたいことの発表
この様なワークフローでワークショップを開こうと考えておりますが、必要になるものや、前もって調べておく(理解しておく)必要があるものがあるので、それを以下に記載いたします。
1.Robocodeをインストール
RobocodeのダウンロードはSourceForgeからできます。
そして、細かい情報はWikiがあります。
プログラミングに詳しくなくても、まったく問題ありません。このレベルのプログラミングは「アイディア」が最も重要です。
プログラムの細かい部分に関しては調べて理解すればよいし、もっと本格的な改造などを使用と考えなければJavaプログラミングをイチから学習する必要はありません。
もし、イチから学習したいと思ったらぜひやってください。
自分のお勧めする学習手順は以下のリンクにあります。よかったらどうぞ。
2.サンプルバトルの起動、およびゲームの内容確認
実際にサンプルバトルを起動したときの画像が下のものになります。
早い話が、最後まで生き残ることがこのゲームの勝利条件です。
そのために、以下のメソッドに定義する処理(動き)を工夫して、他のプレーヤーに負けないようにすることが主な目的になります。
3.自分のRoboの作成(コードは自動生成される)
やり方に関しては、こちらの記事の「Roboを作る」に記載していますが、この部分は、チュートリアル的に作業を行う感じになります。
4.自分のRoboをバトルに参加させる
これは画面操作のみです。
-
新しバトルを開く
-
自作のRoboをバトルに追加する
5.Roboの動きとコードの内容を見比べて内容を大まかに理解する
Roboを動かす処理は大きく4つあります。
- 通常(デフォルト)の動き(run)
- 敵Roboをスキャンしたときの処理(onScannedRobot)
- 弾に当たったときの処理(onHitByBullet)
- 壁にぶつかったときの処理(onHitWall)
それぞれの動きを定義しているのが、上の強調表示している名前がそうです。この名前は、メソッドというものの名前になります。
Javaプログラミングのルール
Javaはプログラムをすべて「クラス」で表現します。そして、クラスの中には「フィールド変数(属性というときもあります)」と「メソッド(振る舞いを示す)」を定義することができ、「{}」で囲った部分がクラスとメソッドの範囲を示します。
クラスの書き方
/**
* 「/**」出始めるコメント部分をJavaDocコメントといいます。
*/
public class クラス名 {
/** JavaDocコメント */
int 変数名;
/**
* JavaDocコメント、メソッドの説明
*/
public 返り値 メソッド名(引数) {
// 通常のコメント部分
/*
* 「/*」で始まるコメント部分は通常のコメントとして扱います。
*/
// メソッドの処理を書きます。
}
}
これはJavaプログラミングのルールなので、どんなクラスでも「フィールド変数」と「メソッド」の2つの要素が存在します。※必ずでこの2つがある必要はありません。
具体的には、下のようなコードです。※抜粋しています。
クラスの定義:作成したRoboの名前は「FirstRobot」
/**
* FirstRobot - a robot by (your name here)
*/
public class FirstRobot extends Robot
{
// 4つの動きを定義しているメソッドの定義があります。
}
そして、4つの動きにに対応する処理(メソッド)は以下のようになっています。
メソッドの定義:各アクションの定義
-
通常(デフォルト)の動き(run): ゲーム開始時のデフォルトの動きを定義します。
/** * run: FirstRobot's default behavior */ public void run() { aliveTime = 0; // Initialization of the robot should be put here showStatus(); // After trying out your robot, try uncommenting the import at the top, // and the next line: // setColors(Color.red,Color.blue,Color.green); // body,gun,radar aliveTime = 0; // Robot main loop while(true) { // Replace the next 4 lines with any behavior you would like ahead(10); turnGunRight(360); } }
-
敵Roboをスキャンしたときの処理(onScannedRobot)
/** * onScannedRobot: What to do when you see another robot */ public void onScannedRobot(ScannedRobotEvent e) { // Replace the next line with any behavior you would like fireBullet(120); }
-
弾に当たったときの処理(onHitByBullet)
/** * onHitByBullet: What to do when you're hit by a bullet */ public void onHitByBullet(HitByBulletEvent e) { // Replace the next line with any behavior you would like
}
4. 壁にぶつかったときの処理(onHitWall)
```java
/**
* onHitWall: What to do when you hit a wall
*/
public void onHitWall(HitWallEvent e) {
// Replace the next line with any behavior you would like
turnRight(90);
}
ちなみに、「弾に当たったとき」「壁にぶつかったとき」「スキャンしたとき」のように「~のとき」処理が動くような仕組みのことを「イベントハンドラ」と呼び、よく「~のイベントを受け取ったとき。。。」などのように話をします。
6.Javaコードを書いて、動きを変えてみる
上に示した、各イベントに対応するメソッド=「run」「onScannedRobot」「onHitByBullet」「onHitWall」に定義してある処理を変更してみます。
実際に使用できるコードはある程度決まっていて詳細に関しては、こちらのJavaDocというドキュメントに記述があります。
JavaDocとは
JavaDocはプログラムを書くときにクラスやメソッドの説明を書くときに使用するコメント文です。
そして、Roboを動かすために使用できるメソッドはこのリンク先に記載があります。
表にまとめると以下のようになります。
<表A>
返り値 | メソッド名 | 振る舞い(処理の内容) |
---|---|---|
void | ahead(double distance) | ロボットを前方に移動させます。 |
void | back(double distance) | ロボットを後方に移動させます。 |
void | doNothing() | このロボットの今回の順番では、何も動作を行いません。 |
void | finalize() | システムによって呼び出され、ロボットのクリーンアップ (終結処理) を行います。 |
void | fire(double power) | 弾丸を発射します。 |
Bullet | fireBullet(double power) | 弾丸を発射します。 |
double | getBattleFieldHeight() | 現在のバトルフィールドの高さを取得します。 |
double | getBattleFieldWidth() | 現在のバトルフィールドの幅を取得します。 |
double | getEnergy() | ロボットの現在のエネルギーを戻します。 |
double | getGunCoolingRate() | 大砲の冷却速度を戻します。 |
double | getGunHeading() | 大砲の向きを 360 度形式で戻します。 |
double | getGunHeat() | 大砲の現在の熱さを戻します。 |
double | getHeading() | ロボットの現在の向きを 360 度形式で戻します。 |
double | getHeight() | ロボットの高さを戻します。 |
String | getName() | ロボットの名前を戻します。 |
int | getNumRounds() | 現在のバトルのラウンド数を戻します。 |
int | getOthers() | 敵ロボットの残り台数を戻します。 |
double | getRadarHeading() | レーダーの向きを 360 度形式で戻します。 |
int | getRoundNum() | 現在のラウンドが、 バトルの第何ラウンドかを戻します (1~getNumRounds() の範囲) |
long | getTime() | 現在のゲーム時刻を戻します。 |
double | getVelocity() | このロボットの移動速度を戻します。 |
double | getWidth() | ロボットの幅を戻します。 |
double | getX() | ロボットの X 座標の位置を戻します。 |
double | getY() | ロボットの Y 座標の位置を戻します。 |
void | onBulletHit(BulletHitEvent event) | このロボットが発射したいずれかの弾丸が他のロボットに当たったとき、 このメソッドが呼び出されます。 |
void | onBulletHitBullet(BulletHitBulletEvent event) | このロボットが発射したいずれかの弾丸が他の弾丸に当たったとき、 このメソッドが呼び出されます。 |
void | onBulletMissed(BulletMissedEvent event) | このロボットが発射したいずれかの弾丸がはずれたとき (壁に当たったとき)、 このメソッドが呼び出されます。 |
void | onDeath(DeathEvent event) | このメソッドは、ロボットが死んだときに呼び出されます。 このイベントが通知されるようにするには、 ロボットのコードでこのメソッドをオーバーライドする必要があります。 |
void | onHitByBullet(HitByBulletEvent event) | このロボットに弾丸が命中したとき、このメソッドが呼び出されます。 |
void | onHitRobot(HitRobotEvent event) | このロボットが他のいずれかのロボットと衝突したとき、 このメソッドが呼び出されます。 |
void | onHitWall(HitWallEvent event) | このロボットが壁に衝突したとき、このメソッドが呼び出されます。 |
void | onRobotDeath(RobotDeathEvent event) | このメソッドは、 他のいずれかのロボットが死んだときに呼び出されます。 このイベントが通知されるようにするには、 ロボットのコードでこのメソッドをオーバーライドする必要があります。 |
void | onScannedRobot(ScannedRobotEvent event) | このロボットが他のロボットを発見したとき、 このメソッドが呼び出されます。 |
void | onWin(WinEvent event) | このロボットがバトルに勝ったとき、このメソッドが呼び出されます。 |
void | resume() | stop() による停止中の動作があれば、その動作を再開します。 |
void | run() | 各ロボットのメイン・メソッド。 |
void | scan() | 他のロボットを探します。 |
void | setAdjustGunForRobotTurn(boolean newAdjustGunForRobotTurn) | ロボットが回転するときに、 大砲が自動的に逆方向に回転するように設定します。 |
void | setAdjustRadarForGunTurn(boolean newAdjustRadarForGunTurn) | 大砲が回転するときに、 レーダーが自動的に逆方向に回転するように設定します。 |
void | setAdjustRadarForRobotTurn(boolean newAdjustRadarForRobotTurn) | ロボットが回転するときに、 レーダーが自動的に逆方向に回転するように設定します。 |
void | setColors(Color robotColor, Color gunColor, Color radarColor) | このメソッドは、ロボットの色を設定するために呼び出します。 |
void | stop() | 動作をすべて停止し、 後で resume() 呼び出しを使って再開できるよう、保存します。 |
void | stop(boolean overwrite) | 動作をすべて停止し、 後で resume() 呼び出しを使って再開できるよう、保存します。 |
void | turnGunLeft(double degrees) | ロボットの大砲を回転させます。 |
void | turnGunRight(double degrees) | ロボットの大砲を回転させます。 |
void | turnLeft(double degrees) | ロボットを回転させます。 |
void | turnRadarLeft(double degrees) | ロボットのレーダーを回転させます。 |
void | turnRadarRight(double degrees) | ロボットのレーダーを回転させます。 |
void | turnRight(double degrees) | ロボットを回転させます。 |
JavaDocには詳細な情報が記述されているので、このドキュメントを読んで理解できるとかなり強いプログラマーとして君臨できます(笑)
とりあえずは、JavaDocにあるメソッドを実装して動かしてみるのが、一番です。
7. 動きを定義するメソッド「run」「onScannedRobot」「onHitByBullet」「onHitWall」の改造をしてみる
具体的に実装を行います。JavaDocを参考に、各メソッドにそれぞれのメソッドを実装し、プログラムを実行して動きを確認してみます。
以前作成した動画で丁度良いのがあったのでそれを載せます。
具体的には、デフォルトの動き「run()」メソッドの定義と動きを確認してモノです。
ポイントとしては以下の通りです。上に記載した表Aから抜粋しました。 | 返り値 | メソッド名 | 振る舞い(処理の内容) |
---|---|---|---|
void | ahead(double distance) | ロボットを前方に移動させます。 | |
void | back(double distance) | ロボットを後方に移動させます。 |
コードとしては、次のようなものです。
while(true) {
ahead(100);
turnGunRight(360);
back(100);
turnGunRight(360);
}
下の「while(true)」と書いてある部分は次に書いてある「{」から「}」までの間を無限ループする処理を書いています。デフォルトの動きなので、無限ループしている処理なのでしょう。
8. 起動確認と実装アイディアの話し合い
上の表Aから各メソッドの中に、それぞれのコードを書いたり消したりしながら、Roboを最強な動きにできるように、アイディアを出し合ったり、プログラムの内容を理解したり、みんなでワイワイやると面白いだろうな、というのが自分の思惑ですが、果たしてどうなるでしょうか?
9. みんなで作成したRoboで対決する
この部分に関しては、Robocodeのウェブサーバーがあるのでそれをダウンロード、起動といった準備が必要になります。
この部分に関しては、後日追記します。
でわでわ。。。