Interaktiivsete esemete lisamine ja integreerimine¶
See juhend käsitleb maas asuvate korjatavate esemete (pickups) loomist, nende haldamist serveris ning korrektset sünkroniseerimist mängijate vahel.
Süsteemi ülesehitus ja loogika¶
Mitmikmängus on kriitiline, et mängu seis oleks kõigi jaoks identne. Selleks jagame loogika kolmeks: 1. Server: Hoiab ametlikku nimekirja kõigist maailmas olevatest esemetest. 2. Võrgukiht (DTO): Kerged paketid andmete kiireks edastamiseks. 3. Klient: Tegeleb ainult visualiseerimise ja kasutaja sisendi püüdmisega.
Serveri pool: Esemete haldamine¶
Serveris on vaja hoida esemeid struktuuris, mis võimaldab neid kiiresti leida ja kustutada. Selleks sobib kõige paremini HashMap, kus võtmeks on eseme unikaalne ID ja väärtuseks eseme objekt.
public class ServerItem {
private static int nextId = 0; // Genereerib igale uuele esemele unikaalse ID
public enum Type { AR1, PISTOL, SHOTGUN, SNIPER }
public final int id;
public final Type type;
public float x, y;
public ServerItem(Type type, float x, float y) {
this.id = nextId++;
this.type = type;
this.x = x;
this.y = y;
}
}
// Esemete hoiustamine serveri mänguloogikas
public HashMap<Integer, ServerItem> droppedItems = new HashMap<>();
Võrgukiht: Andmete edastamine (DTO)¶
Võrgu koormuse vähendamiseks ei saada me kunagi tervet ServerItem objekti. Kasutame DTO klassi, mis sisaldab ainult hädavajalikku infot kliendi jaoks.
ItemDTO: Sisaldab eseme ID-d, tüüpi ja asukohta.
OnSendItems: Pakett, millega server saadab kliendile nimekirja kõigist hetkel maas olevatest esemetest.
OnTake: Teavitus eseme üleskorjamise kohta.
public static class ItemDTO {
public int id;
public int typeOrdinal; // Enumi järjekorranumber (int), et säästa baite
public float x, y;
}
public static class OnSendItems {
public ArrayList<ItemDTO> items;
}
public static class OnTake {
public int id;
}
NB! Ära unusta neid DTO klasse nii serveris kui kliendis registreerida!
Kliendi pool: Visualiseerimine ja ressursid¶
Kliendis loome klassi ClientItem, mis tegeleb eseme joonistamisega. Jõudluse tagamiseks ei loo me eseme sees uusi tekstuure, vaid kasutame viiteid mälus olevatele TextureRegion-itele.
public class ClientItem extends Sprite {
public final int id;
public ClientItem(int id, TextureRegion region, float x, float y) {
super(region); // Kasutame juba laetud tekstuuri
this.id = id;
setPosition(x, y);
setSize(32, 32);
}
}
Esemete sünkroniseerimine ja üleskorjamine¶
Sünkroniseerimine toimub kindla tsüklina, et vältida olukorda, kus kaks mängijat saavad ühe eseme.
1. Interaktsiooni kontroll kliendis Klient kontrollib igas kaadris (update), kas mängija on mõne eseme lähedal. Kui mängija vajutab klahvi 'E', saadetakse serverile soov (OnTake).
private void update(float delta) {
for (ClientItem item : visibleItems) {
if (player.getBoundingRectangle().overlaps(item.getBoundingRectangle())) {
if (Gdx.input.isKeyJustPressed(Input.Keys.E)) {
sendTakeRequest(item.id);
}
}
}
}
2. Kinnitus serveris Server kontrollib, kas ese on veel saadaval. Kui on, siis ese eemaldatakse serveri andmebaasist ja teavitatakse kõiki kliente.
if (object instanceof OnTake) {
int id = ((OnTake) object).id;
if (droppedItems.containsKey(id)) { // Kontroll, kas ese on veel alles
droppedItems.remove(id);
server.sendToAllTCP(object); // Käsk kõigile klientidele ese kustutada
}
}
3. Eemaldamine klientides Alles siis, kui serverilt saabub kinnitus (OnTake), eemaldavad kliendid eseme oma ekraanilt. See tagab, et mängu seis on kõigil sünkroonis.
if (object instanceof OnTake) {
int id = ((OnTake) object).id;
Gdx.app.postRunnable(() -> {
// Eemaldame nimekirjast eseme, mille ID ühtib serverilt saaduga
visibleItems.removeIf(item -> item.id == id);
});
}
Järgmised sammud: Inventory¶
Nüüd, kui esemete maailma lisamine ja sealt korjamine on selge, saate edasi liikuda täiemahulise inventarisüsteemi arendamise juurde. See hõlmab esemete hoiustamist mängija nimekirjas, nende kasutamist ja asjade uuesti maha viskamist.
Jätkake oma mängu arendamist selle põhjaliku juhendi abil: Inventarisüsteemi loomine LibGDX-is
Olulised näpunäited¶
Mäluhaldus: Kasuta alati
AssetManageri(AssetManageri kasutamine LibGDX-is) tekstuuride laadimiseks. See hoiab ära mängu hakkimise uute esemete ilmumisel.Turvalisus: Serveris tuleks lisaks ID kontrollile veenduda, et mängija asukoht on esemele piisavalt lähedal, et vältida ebaausat mängu.