CodeGym の「ゲーム」セクションには、人気のあるコンピューター ゲームの作成に関わるエキサイティングなプロジェクトが見つかります。人気ゲーム 2048、マインスイーパー、スネーク、その他のゲームの独自バージョンを作成してみませんか? それは簡単です。私たちはゲーム作成を段階的なプロセスに変えました。
![CodeGym の「ゲーム」セクション: 役立つ理論 - 1]()
ゲーム開発者としての能力をテストするには、高度なプログラマーである必要はありませんが、Java の特定の知識が必要です。
ここではゲーム作成に役立つ情報を紹介します。
1. 継承
CodeGym ゲーム エンジンの操作には、継承の使用が含まれます。しかし、それが何なのかわからない場合はどうすればよいでしょうか? 一方で、このトピックを理解する必要があります。このトピックは
レベル 11で学習されます。。一方、エンジンは非常にシンプルになるように特別に設計されているため、継承に関する表面的な知識だけで済みます。では、継承とは何でしょうか?非常に簡単に言うと、継承は 2 つのクラス間の関係です。そのうちの 1 つが親になり、もう 1 つが子 (子孫) になります。さらに、親クラスは、子孫があることさえ知らない可能性があります。つまり、子孫を残すことで特に有利になるわけではありません。しかし、継承は子孫に多くの利点をもたらします。そして最も重要なことは、親クラスのすべての変数とメソッドが、親クラスのコードが子孫クラスにコピーされたかのように子孫に表示されることです。これは完全に正確な説明ではありませんが、継承を簡単に理解するには十分です。
例 1:最も単純な継承。
public class Parent {
}
|
Childクラスは、extendsキーワードを使用してParentクラスを継承します。 |
public class Child extends Parent {
}
|
例 2:親クラスの変数を使用する。
public class Parent {
public int age;
public String name;
}
|
Childクラスは、親クラスで宣言されているかのように、親クラスのage変数とname変数を使用できます。 |
public class Child extends Parent {
public void printInfo() {
System.out.println(name+" "+age);
}
}
|
例 3:親クラスのメソッドの使用。
public class Parent {
public int age;
public String name;
public getName() {
return name;
}
}
|
子クラスは、親クラスの変数とメソッドを、子クラスで宣言されているかのように使用できます。この例では、getName()メソッドを使用します。 |
public class Child extends Parent {
public void printInfo() {
System.out.println(getName()+" "+age);
}
}
|
Childクラスはコンパイラからは 次のように見えます。
public class Child extends Parent{
public int age;
public String name;
public getName() {
return name;
}
public void printInfo() {
System.out.println(getName()+" "+age);
}
}
2. メソッドのオーバーライド
場合によっては、子クラスに、そのすべての変数とメソッドとともに、非常に便利な親クラスを継承させますが、一部のメソッドが期待通りに動作しない場合があります。あるいは、私たちが望むようにはまったくなりません。この状況では何ができるでしょうか? 気に入らないメソッドをオーバーライドできます。これは非常に簡単に行うことができます。子クラスで、親クラスのメソッドと同じシグネチャを持つメソッドを宣言し、その中に独自のコードを記述するだけです。
例 1:メソッドをオーバーライドする。
public class Parent {
public String name;
public void setName(String nameNew) {
name = nameNew;
}
public getName() {
return name;
}
}
|
printInfo() メソッドは「Luke、No!!!」と表示します。 |
public class Child extends Parent{
public void setName(String nameNew) {
name = nameNew + ", No!!!";
}
public void printInfo() {
setName("Luke");
System.out.println(getName());
}
}
|
Childクラスはコンパイラからは 次のように見えます。
public Child extends Parent {
public String name;
public void setName(String nameNew)
name = nameNew + ", No!!!";
}
public getName() {
return name;
}
public void printInfo() {
setName("Luke");
System.out.println( getName());
}
}
例 2:いくつかの継承マジック (およびメソッドのオーバーライド)。
public class Parent {
public getName() {
return "Luke";
}
public void printInfo() {
System.out.println(getName());
}
}
|
public class Child extends Parent {
public getName() {
return "Luke, I am your father";
}
}
|
この例では、
printInfo
(Parent クラスの) メソッドが Child クラスでオーバーライドされていない場合、このメソッドが Child オブジェクトで呼び出されるときに、
getName()
Parent クラスのメソッドの代わりにそのメソッドが呼び出されます
getName()
。
Parent parent = new Parent ();
parent.printnInfo();
|
このコードは画面に「Luke」を表示します。 |
Child child = new Child ();
child.printnInfo();
|
このコードは、画面に「ルーク、私はあなたの父親です」と表示します。 |
Childクラスはコンパイラからは 次のように見えます。
public class Child extends Parent {
public getName() {
return "Luke, I am your father";
}
public void printInfo() {
System.out.println(getName());
}
}
3. リスト
リスト (List) をまだ知らない方のために、ここで簡単な概要を説明します。
完全な情報は、 CodeGym コースのレベル 6 ~ 7 で見つけることができます。
リストには配列と多くの共通点があります。
- 特定の種類のデータを大量に保存できます。
- インデックスによって項目を取得できます。
- 要素のインデックスは 0 から始まります。
リストの利点: 配列とは異なり、リストはサイズを動的に変更できます。リストの作成時のサイズは 0 です。リストに項目を追加すると、そのサイズは増加します。リストの作成例は次のとおりです。
ArrayList<String> myList = new ArrayList<String>();
山括弧内の値は、リストに格納できるデータ型を示します。リストを操作するためのいくつかの方法を次に示します。
コード |
コードの動作の簡単な説明 |
ArrayList<String> list = new ArrayList<String>(); |
文字列の新しいリストを作成する |
list.add("name"); |
リストの最後に要素を追加します |
list.add(0, "name"); |
リストの先頭に要素を追加します |
String name = list.get(5); |
インデックスで要素を取得する |
list.set(5, "new name"); |
インデックスによって要素を変更する |
int count = list.size(); |
リスト内の要素の数を取得します |
list.remove(4); |
リストから要素を削除する |
リストの詳細については、次の記事を参照してください。
- ArrayList クラス
- 写真のArrayList
- ArrayList からの要素の削除
4. 配列
マトリックスとは何ですか? マトリックスは、データを入力できる長方形のテーブルにすぎません。言い換えれば、それは二次元配列です。おそらくご存知のとおり、Java の配列はオブジェクトです。標準的な 1 次元
int
配列は次のようになります。
int [] array = {12, 32, 43, 54, 15, 36, 67, 28};
次のように視覚化できます。
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
32 |
43 |
54 |
15 |
36 |
67 |
28 |
一番上の行はセルのアドレスを示します。つまり、数値 67 を取得するには、インデックス 6 の配列要素にアクセスする必要があります。
int number = array[6];
すべてとてもシンプルです。2 次元配列は 1 次元配列の配列です。このことについて初めて聞いた場合は、立ち止まって頭の中で想像してください。2 次元配列は次のようになります。
0 |
1次元配列 |
1次元配列 |
1 |
1次元配列 |
2 |
1次元配列 |
3 |
1次元配列 |
4 |
1次元配列 |
5 |
1次元配列 |
6 |
1次元配列 |
7 |
1次元配列 |
コード内:
int [][] matrix = {
{65, 99, 87, 90, 156, 75, 98, 78},
{76, 15, 76, 91, 66, 90, 15, 77},
{65, 96, 17, 25, 36, 75, 54, 78},
{59, 45, 68, 14, 57, 1, 9, 63},
{81, 74, 47, 52, 42, 785, 56, 96},
{66, 74, 58, 16, 98, 140, 55, 77},
{120, 99, 13, 90, 78, 98, 14, 78},
{20, 18, 74, 91, 96, 104, 105, 77}
}
0 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
65 |
99 |
87 |
90 |
156 |
75 |
98 |
78 |
1 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
76 |
15 |
76 |
91 |
66 |
90 |
15 |
77 |
2 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
65 |
96 |
17 |
25 |
36 |
75 |
54 |
78 |
3 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
59 |
45 |
68 |
14 |
57 |
1 |
9 |
63 |
4 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
81 |
74 |
47 |
52 |
42 |
785 |
56 |
96 |
5 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
66 |
74 |
58 |
16 |
98 |
140 |
55 |
77 |
6 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
120 |
99 |
13 |
90 |
78 |
98 |
14 |
78 |
7 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
20 |
18 |
74 |
91 |
96 |
104 |
105 |
77 |
値 47 を取得するには、[4][2] の行列要素を参照する必要があります。
int number = matrix[4][2];
マトリックス座標が古典的な直交座標系 (デカルト座標系) とは異なることに気づいたかもしれません。
行列にアクセスするときは、最初に y 座標を指定し、次に x 座標を指定します。数学では、最初に x 座標、つまり (x, y) を指定するのが通例です。「行列の表現を回転してから、(x, y) を使用して通常の方法で要素にアクセスするのはどうでしょうか? これを実行しても行列の内容は変更されません。」と疑問に思われるかもしれません。はい、何も変わりません。しかし、プログラミングの世界では、「最初に y で、次に x で」行列にアクセスすることが受け入れられています。これを正しい方法として受け入れるべきです。ここで、行列をエンジンに投影する方法について話しましょう (
Game
クラス)。ご存知のとおり、エンジンには特定の座標で競技場のセルを変更するメソッドが多数あります。たとえば、
setCellValue(int x, int y, String value)
方法です。value パラメーターと等しい座標 (x, y) を持つ特定のセルを設定します。お気づきかもしれませんが、この方法では、古典的な座標系と同様に、x が最初に取られます。エンジンの他のメソッドも同様に機能します。ゲームを開発する場合、画面上でマトリクスの状態を再現することが必要になることがよくあります。どうやってそれを行うのでしょうか?まず、ループ内のすべての行列要素を反復処理する必要があります。次に、REVERSED 座標を使用して、それぞれの表示メソッドを呼び出します。例えば:
private void drawScene() {
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
setCellValue(j, i, String.valueOf(matrix[i][j]));
}
}
}
当然のことながら、反転は両方向に機能します。(i, j) を
setCellValue
メソッドに渡すと同時に、行列から要素 [j][i] を取得できます。座標を反転するのは少し難しいように思えるかもしれませんが、覚えておく必要があります。そして、何か問題が発生した場合は、必ず紙とペンを用意し、マトリックスを描き、そのマトリックスに関連するプロセスを再現する必要があります。
5. 乱数
乱数発生器をどのように操作しますか? クラスはメソッド
Game
を定義します
getRandomNumber(int)
。内部では
Random
java.util パッケージのクラスを使用しますが、乱数ジェネレーターの操作方法は変わりません。
getRandomNumber(int)
引数として整数を取ります。この数値は、ジェネレーターが返すことができるものの上限になります。下限は 0 です。
重要! ジェネレーターは決して上限数値を返しません。たとえば、 を呼び出すと
getRandomNumber(3)
、ランダムに 0、1、または 2 が返されます。ご覧のとおり、3 を返すことはできません。この方法でジェネレーターを使用するのは非常に簡単ですが、多くの場合に非常に効果的です。
ある範囲の乱数を取得する必要があるとします。 [100..999] の範囲の 3 桁の数値が必要だと想像してください。ご存知のとおり、返される最小値は 0 です。そのため、100 を追加する必要があります。ただし、この場合、上限を超えないように注意する必要があります。最大ランダム値として 999 を取得するには、
getRandomNumber(int)
このメソッドには引数 1000 が指定されています。しかし、結果に 100 を加えていることを思い出してください。これは、上限を 100 減らす必要があることを意味します。つまり、3 桁のランダムな数値を取得するコードは次のようになります。 :
int number = 100 + getRandomNumber(900);
ただし、この手順を簡略化するために、エンジンは
getRandomNumber(int, int)
最初のパラメーターが返す最小値であるメソッドを提供します。この方法を使用すると、前の例を次のように書き直すことができます。
int number = getRandomNumber(100, 1000);
乱数を使用して、ランダムな配列要素を取得できます。
String [] names = {"Sarah", "Val", "Sergey"};
String randomName = names[getRandomNumber(names.length)]
一定の確率で特定のイベントを生成する。 人間の朝は、いくつかの考えられるシナリオで始まります。寝坊 – 確率 50%。時間通りに起きる - 確率 40%。1 時間早く起きた - 確率 10%。朝の成果ジェネレーターを作成していると想像してください。一定の確率でイベントを生成する必要があります。これを行うには、やはり乱数発生器を使用する必要があります。さまざまな実装が可能ですが、最も単純なものは次のアルゴリズムに基づく必要があります。
- 数値を生成するために使用される制限を設定します。
- 乱数を生成します。
- 取得した番号を処理します。
この場合、最大値は 10 になります。
getRandomNumber(10)
メソッドを作成し、返せるかどうかを分析します。10 個の数値 (0 から 9) を返すことができ、それぞれ同じ確率 (10%) で返します。次に、考えられるすべての結果を組み合わせて、考えられるイベントにマッピングする必要があります。あなたの想像力で考えられる組み合わせはたくさん考えられるかもしれませんが、最も明白なのは次のとおりです: 「乱数が [0..4] の範囲にある場合、「寝坊」イベントが発生します。数値が [5] の範囲にある場合は、「寝坊」イベントが発生します。 ..8] の場合は、「時間通りに起きます」イベントがあり、数字が 9 の場合は、「1 時間早く起きます」イベントがあります。すべて非常に単純です。範囲 [0] には 5 つの数字があります。 ..4]、それぞれが 10% の確率で返され、合計 50% になります。[5..8] の範囲には 4 つの数値があり、9 は、次の場合に表示される 1 つの数値にすぎません。確率は10%。
int randomNumber = getRandomNumber(10);
if (randomNumber < 5) {
System.out.println("Overslept");
} else if (randomNumber < 9) {
System.out.println("Woke up on time");
} else {
System.out.println("Woke up an hour early");
}
一般に、乱数を使用する方法はたくさんあります。あなたはあなたの想像力によってのみ制限されます。ただし、何らかの結果を繰り返し取得する必要がある場合に最も効果的に使用されます。その場合、新しい結果は前の結果とは異なります。もちろん、ある程度の確率で。それは今のところすべてです!「ゲーム」セクションについて詳しく知りたい場合は、次の役立つドキュメントを参照してください。
GO TO FULL VERSION