A CodeGym
"Játékok" részében izgalmas projekteket találhat, amelyekben népszerű számítógépes játékok írhatók. Szeretne saját verziót létrehozni a népszerű játékok 2048, Aknakereső, Snake és egyéb játékokból? Ez egyszerű. A játékírást lépésről lépésre történő folyamattá alakítottuk.
Ahhoz, hogy játékfejlesztőként teszteld képességeidet, nem kell haladó programozónak lenned, de szükség van egy meghatározott Java-ismeretre. Itt olyan információkat talál
, amelyek hasznosak lehetnek a játékírás során .
1. Öröklés
A CodeGym játékmotorral való munkavégzés magában foglalja az öröklődés használatát. De mi van, ha nem tudod, mi az? Egyrészt meg kell értened ezt a témát: a
11. szinten tanulmányozzák. Másrészt a motort kifejezetten nagyon egyszerűre tervezték, így megúszhatja az öröklődés felületes tudását. Tehát mi az öröklés? Nagyon leegyszerűsítve, az öröklődés két osztály közötti kapcsolat. Egyikük szülő lesz, a másikuk gyermek (leszármazott) lesz. Sőt, a szülő osztály nem is tudhatja, hogy vannak leszármazottai. Más szóval, nem szerez különösebb előnyt azzal, hogy leszármazottai vannak. De az öröklődés számos előnnyel jár a leszármazottnak. A legfontosabb pedig az, hogy a szülő osztály összes változója és metódusa úgy jelenik meg a leszármazottban, mintha a szülő osztály kódját a leszármazott osztályba másolták volna. Ez nem teljesen pontos leírás, de elegendő az öröklődés egyszerűsített megértéséhez.
1. példa: A legegyszerűbb öröklődés.
public class Parent {
}
|
A Child osztály a Parent osztályt örökli az extends kulcsszó használatával . |
public class Child extends Parent {
}
|
2. példa: A szülő osztály változóinak használata.
public class Parent {
public int age;
public String name;
}
|
A Gyermek osztály úgy használhatja a Szülő osztály életkor- és névváltozóit , mintha a Szülő osztályban lennének deklarálva . |
public class Child extends Parent {
public void printInfo() {
System.out.println(name+" "+age);
}
}
|
3. példa: A szülő osztály metódusainak használata.
public class Parent {
public int age;
public String name;
public getName() {
return name;
}
}
|
A Child osztály úgy használhatja a Parent osztály változóit és metódusait, mintha a Child osztályban lennének deklarálva. Ebben a példában a getName() metódust használjuk . |
public class Child extends Parent {
public void printInfo() {
System.out.println(getName()+" "+age);
}
}
|
Így néz ki a
Child osztály a fordító számára:
public class Child extends Parent{
public int age; // Inherited variable
public String name; // Inherited variable
public getName() { // Inherited method.
return name;
}
public void printInfo() {
System.out.println(getName()+" "+age);
}
}
2. Módszerek felülbírálása
Néha vannak olyan helyzetek, amikor a Child osztályunk egy nagyon hasznos Szülő osztályt örököl, annak összes változójával és metódusával együtt, de egyes metódusok nem úgy működnek, ahogy szeretnénk. Vagy egyáltalán nem úgy, ahogy szeretnénk. Mit tehetünk ebben a helyzetben? Felülírhatjuk a nekünk nem tetsző módszert. Ezt nagyon egyszerű megtenni: a Child osztályunkban egyszerűen deklarálunk egy metódust, amelynek aláírása megegyezik a Parent osztály metódusával, majd beleírjuk a saját kódunkat.
1. példa: Egy módszer felülbírálása.
public class Parent {
public String name;
public void setName(String nameNew) {
name = nameNew;
}
public getName() {
return name;
}
}
|
A printInfo() metódus a következőt jeleníti meg : "Luke, No!!!" |
public class Child extends Parent{
public void setName(String nameNew) {
name = nameNew + ", No!!!";
}
public void printInfo() {
setName("Luke");
System.out.println(getName());
}
}
|
Így néz ki a
Child osztály a fordító számára:
public Child extends Parent {
public String name; // Inherited variable
public void setName(String nameNew) // Overridden method instead of the inherited method {
name = nameNew + ", No!!!";
}
public getName() { // Inherited method.
return name;
}
public void printInfo() {
setName("Luke");
System.out.println( getName());
}
}
2. példa: Némi öröklődési mágia (és módszer felülbírálása).
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";
}
}
|
Ebben a példában, ha a
printInfo
metódus (a Parent osztályból) nincs felülírva a Child osztályban, amikor ezt a metódust egy Child objektum hívja meg, akkor annak
getName()
metódusa lesz meghívva a Parent osztály
getName()
metódusa helyett.
Parent parent = new Parent ();
parent.printnInfo();
|
Ez a kód a „Luke” feliratot jeleníti meg a képernyőn. |
Child child = new Child ();
child.printnInfo();
|
Ez a kód a „Luke, én vagyok az apád” szöveget jeleníti meg a képernyőn. |
Így néz ki a
Child osztály a fordító számára:
public class Child extends Parent {
public getName() {
return "Luke, I am your father";
}
public void printInfo() {
System.out.println(getName());
}
}
3. Listák
Ha még nem találkozott listákkal (Lista), itt egy rövid áttekintés.
A teljes információt a CodeGym tanfolyam 6-7. szintjén találja .
A listáknak sok közös vonásuk van a tömbökkel:
- sok, adott típusú adatot tárolhat;
- lehetővé teszik, hogy az indexük alapján elemeket kapjon;
- az elemindexek 0-tól kezdődnek.
A listák előnyei: A tömböktől eltérően a listák mérete dinamikusan változhat. A lista létrehozásakor a mérete 0. Amikor elemeket ad hozzá egy listához, a mérete növekszik. Íme egy példa lista létrehozására:
ArrayList<String> myList = new ArrayList<String>(); // Create a new ArrayList
A szögletes zárójelben lévő érték azt az adattípust jelzi, amelyet a lista tárolhat. Íme néhány módszer a listával való munkavégzéshez:
Kód |
Rövid leírás a kód működéséről |
ArrayList<String> list = new ArrayList<String>(); |
Hozzon létre új karakterlánclistát |
list.add("name"); |
Adjon hozzá egy elemet a lista végéhez |
list.add(0, "name"); |
Adjon hozzá egy elemet a lista elejéhez |
String name = list.get(5); |
Szerezzen be egy elemet az indexe alapján |
list.set(5, "new name"); |
Módosítson egy elemet az indexével |
int count = list.size(); |
Szerezze meg a listában szereplő elemek számát |
list.remove(4); |
Töröljön egy elemet a listából |
A listákról a következő cikkekből tudhat meg többet:
- ArrayList osztály
- ArrayList képekben
- Elem törlése egy ArrayList-ből
4. Tömbök
Mi az a mátrix? A mátrix nem más, mint egy téglalap alakú táblázat, amelyet meg lehet tölteni adatokkal. Más szóval, ez egy kétdimenziós tömb. Mint valószínűleg tudja, a Java tömbjei objektumok. Egy szabványos egydimenziós
int
tömb így néz ki:
int [] array = {12, 32, 43, 54, 15, 36, 67, 28};
Ezt így képzelhetjük el:
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
32 |
43 |
54 |
15 |
36 |
67 |
28 |
A felső sor a cellák címét jelzi. Más szavakkal, a 67-es szám eléréséhez el kell érnie a 6-os indexű tömbelemet:
int number = array[6];
Minden nagyon egyszerű. A kétdimenziós tömb egydimenziós tömbök tömbje. Ha először hall erről, álljon meg, és képzelje el a fejében. Egy kétdimenziós tömb így néz ki:
0 |
Egydimenziós tömb |
Egydimenziós tömb |
1 |
Egydimenziós tömb |
2 |
Egydimenziós tömb |
3 |
Egydimenziós tömb |
4 |
Egydimenziós tömb |
5 |
Egydimenziós tömb |
6 |
Egydimenziós tömb |
7 |
Egydimenziós tömb |
Kódban:
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 |
A 47-es értékhez a [4][2] helyen lévő mátrixelemre kell hivatkozni.
int number = matrix[4][2];
Talán észrevette, hogy a mátrix koordinátái eltérnek a klasszikus derékszögű koordinátarendszertől (derékszögű koordinátarendszer).
Amikor hozzáfér a mátrixhoz, először meg kell adnia az y koordinátát, majd az x koordinátát. A matematikában először az x koordinátát szokás megadni, azaz (x, y). Felmerülhet a kérdés: "Nos, miért nem forgatja el a mátrix reprezentációját, majd a szokásos módon (x, y) segítségével érheti el az elemeket? Ez nem változtatja meg a mátrix tartalmát." Igen, semmi sem változna. De a programozási világban az az elfogadott gyakorlat, hogy a mátrixokhoz "először y-val, majd x-el" kell hozzáférni. Ezt a helyes útnak kell elfogadnia. Most beszéljünk a mátrix kivetítéséről a motorunkra (
Game
osztály). Mint tudják, a motornak számos olyan módszere van, amelyek meghatározott koordinátákon megváltoztatják a játékmező celláit. Például a
setCellValue(int x, int y, String value)
módszer. Egy adott cellát állít be, amelynek koordinátái (x, y) megegyeznek az értékparaméterrel. Talán észrevette, hogy ez a módszer először x-et vesz igénybe, csakúgy, mint a klasszikus koordináta-rendszerben. A motor többi módszere is hasonlóan működik. A játékok fejlesztésekor gyakran szükséges egy mátrix állapotát reprodukálni a képernyőn. Hogyan csináljuk? Először is végig kell ismételnie egy ciklusban az összes mátrixelemet. Másodszor, hívja meg mindegyik megjelenítési módszerét, FORDÍTOTT koordinátákkal. Például:
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]));
}
}
}
Természetesen a megfordítás mindkét irányban működik. Az (i, j)-t átadhatja a
setCellValue
metódusnak, és ezzel egyidejűleg kiveheti a [j][i] elemet a mátrixból. A koordináták megfordítása kissé nehéznek tűnhet, de emlékeznie kell rá. És mindig, ha bármilyen probléma adódik, ragadjon egy darab papírt és egy tollat, rajzolja meg a mátrixot, és reprodukálja a mátrixot érintő folyamatokat.
5. Véletlen számok
Hogyan dolgozol véletlenszám-generátorral? Az
Game
osztály határozza meg a
getRandomNumber(int)
metódust. A motorháztető alatt a java.util csomag osztályát használja
Random
, de a véletlenszám-generátorral való munkamódszer nem változik.
getRandomNumber(int)
egész számot vesz argumentumként. Ez a szám lesz a generátor által visszaadható felső határ. Az alsó határ 0.
Fontos! A generátor SOHA nem adja vissza a felső határértéket. Például, ha meghívja a
getRandomNumber(3)
, véletlenszerűen 0, 1 vagy 2 értéket ad vissza. Amint látja, nem tud visszaadni 3-at. A generátor ilyen módon történő használata meglehetősen egyszerű, de sok esetben rendkívül hatékony.
Tegyük fel, hogy egy véletlen számot kell kapnia valamilyen tartományban: Képzelje el, hogy szüksége van egy háromjegyű számra a [100...999] tartományban. Mint már tudja, a visszaadott minimális szám 0. Tehát 100-at kell hozzáadnia. Ebben az esetben azonban ügyelnie kell arra, hogy ne lépje túl a felső határt. Ha a 999-et szeretné megkapni maximális véletlenszerű értékként, hívja a
getRandomNumber(int)
De most ne felejtsük el, hogy 100-at adunk az eredményhez: ez azt jelenti, hogy a felső korlátot 100-zal kell csökkenteni. Más szóval, a véletlenszerű háromjegyű számunk kódja így fog kinézni :
int number = 100 + getRandomNumber(900);
Az eljárás egyszerűsítése érdekében azonban a motor biztosítja azt a
getRandomNumber(int, int)
metódust, amelynek első paramétere a visszaadandó minimális szám. Ezzel a módszerrel az előző példa a következőképpen írható át:
int number = getRandomNumber(100, 1000);
A véletlen számok segítségével véletlenszerű tömbelemeket kaphatunk:
String [] names = {"Sarah", "Val", "Sergey"};
String randomName = names[getRandomNumber(names.length)]
Bizonyos események generálása bizonyos valószínűséggel. Emberek számára a reggelek néhány lehetséges forgatókönyvvel kezdődnek: Túlalvás – 50% esély; Időben felébredt – 40% esély; Egy órával korábban ébredtem – 10% az esély. Képzelje el, hogy reggeli eredménygenerátort ír. Bizonyos valószínűséggel eseményeket kell generálnia. Ehhez ismét véletlenszám-generátort kell használnia. Különböző megvalósítások lehetségesek, de a legegyszerűbbnek a következő algoritmuson kell alapulnia:
- állítsa be a számok generálásához használt korlátokat;
- véletlen számot generál;
- feldolgozza a kapott számot.
Ebben az esetben a maximum 10 lesz. Hívja a
getRandomNumber(10)
módszert, és elemezzük, hogy vissza tudjuk-e adni. 10 számot tud visszaadni (0-tól 9-ig), mindegyik azonos valószínűséggel - 10%. Most össze kell kapcsolnunk az összes lehetséges eredményt, és hozzá kell rendelnünk a lehetséges eseményekhez. Képzeleted sok lehetséges kombinációt kitalál, de itt van a legkézenfekvőbb: "Ha a véletlen szám a [0..4] tartományba esik, akkor az "Elaludt" eseményünk van; ha a szám a [5 tartományba esik ..8], megvan az "Időben ébredt" esemény; és ha a szám 9, akkor van az "Egy órával korábban ébredtem" esemény. Minden nagyon egyszerű. 5 szám van a tartományban [0 ..4], amelyek mindegyike 10% valószínűséggel adható vissza, összesen 50%; 4 szám van az [5..8] tartományban, nos, és a 9 csak egy szám, amely 10%-os valószínűséggel.
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");
}
Általában rengeteg módja van a véletlen számok használatának. Csak a képzeleted szab határt. De a leghatékonyabban akkor használhatók, ha ismételten valamilyen eredményt kell elérnie. Ekkor az új eredmény eltér az előzőtől. Persze némi valószínűséggel. Ez minden most! Ha többet szeretne megtudni a "Játékok" részről, itt van néhány hasznos dokumentáció, amely segíthet:
GO TO FULL VERSION