Sissejuhatus¶
Saate järgida neid samme koos selle videoga (igal sammul on ka timestamp).
1. Looge uus projekt GitLabis ja kloonige see IntelliJ-sse.
Projekti loomisel looge kaust
client
(game
kaust videos) ja pärast LibGDX seadistamist loogeserver
moodul.
Klient: tegeleb kasutajaliidese ja mänguloogikaga, see osa mängust töötab mängija seadmel.
Server: haldab mitme kliendi vahelist suhtlust, võimaldades mitmikmängu suhtlust.
Klient suhtleb serveriga, et vahetada teavet mängumaailma ja mängija tegevuste kohta.
Alustamine LibGDX-iga¶
(timestamp) Alustamine LibGDX-iga:
2. Looge LibGDX-projekt, luues IntelliJ mänguprojektis kausta libs
.
Laadige alla LibGDX Project Setup Tool.
Avage IntelliJ projektis terminal.
Navigeerige kausta
libs
(kaust, kuhu installisite.jar
faili) (käsucd libs
abil).- Kasutage
java -jar gdx-liftoff-x.x.x.x.jar
, et avadaProject Setup
. "x"-ide asemele pange versioon failist, mis alla tõmbasite (näiteks
gdx-liftoff-1.13.1.1.jar
).
- Kasutage
3. Konfigureerige oma projekti üksikasjad seadistusaknas:
Project name: Nimetage projekt vastavalt oma mängule.
Package name: Paketi nimeks valige ee.taltech.[oma mängu nimi].
Game class: Nimetage oma mänguklass vastavalt oma mängule.
Output folder: Väljundkausta sisestage oma
client
kausta tee.Supported Platforms: Valige
Desktop
toetatud platvormiks.Official Extensions: Valige mõni kasulik ametlik laiendus (nt Bullet, box2d, AI).
LibGDX-is on laiendused kas teegid või moodulid, mille abil saab lisada erinevaid lisafunktsioone.
Bullet: Pakub täiustatud 3D-füüsika- ja simulatsioonivõimalusi (
collision detection
,soft body dynamics
,rigid body dynamics
jne).box2d: Sarnane
Bulletile
, aga 2D.AI: Lihtsustab AI programmeerimist. Vajalik, kui tahta oma mängu lisada intelligentseid NPC-d (
enemies
,allies
jne).
4. Pärast genereerimist avage client
kaust uues IntelliJ aknas.
Projekti ehitamiseks kasutage:
Tasks > build > build
Mängu käivitamiseks kasutage:
Tasks > other > run
Serveri seadistamine¶
(timestamp) Serveri seadistamine:
- 5. Loo
server
moodul Gradle ehitussüsteemi jaoks ja kasuta Gradle DSL-ina Groovy't. (
New -> Module
)vali
Build system
altGradle
Gradle DSL
alt valiGroovy
.Ava
server
moodul uues IntelliJ aknas.
6. Ava server
moodul uues IntelliJ aknas.
Projekti ehitamiseks kasutage
Tasks > build > build
Serveri käivitamiseks kasutage
Tasks > other > run
Gradle: Automatiseerib sõltuvuste (dependencies
) allalaadimist, uuendamist, leidmist.
Groovy: Gradle build scripts
kirjutamiseks.
Serveri loogika rakendamine Kryonet’iga¶
(timestamp) Serveri loogika rakendamine Kryonet'iga:
7. Loo server
klass, lisades:
Uus directory
src\main\java
,Luues package
ee.taltech.game.server
,Lisades uue Java klassi serveri loogika jaoks (nt
GameServer
).
Külastage Kryoneti GitHubi lehte rakenduse üksikasjade kohta.
Vaadake Kryonet’i kasutamise näiteid.
Lisa Kryonet’i dependency Gradle’ile¶
(timestamp) Lisa Kryonet’i dependency Gradle’ile:
8. Ava build.gradle
fail ja navigeeri Kryoneti Maveni
Repository,
et leida sobiv Gradle’i dependency teave.
Lisa Kryonet’i dependency oma projekti, muutes
build.gradle
faili.Ehita projekt lisatud sõltuvusega kasutades
Tasks > build > build
Kryonet’i rakendamine Serveri klassis¶
(timestamp) Kryonet’i rakendamine Serveri klassis:
9. Impordi com.esotericsoftware.kryonet.Server
oma serveri klassi.
10. Lisage oma serveri klassi Server instance:
private Server server = new Server();
11. Konstruktoris initsialiseerige server ja käsitlege vigu järgmise koodiga:
server = new Server();
server.start();
try {
server.bind(8080, 8081);
} catch (IOException e) {
throw new RuntimeException(e);
}
server.start()
algatab serveri ja valmistab selle ette ühenduste käsitlemiseks.server.bind(8080, 8081)
seob serveri TCP pordile 8080 ja UDP pordile 8081, try-catch plokk aitab vigu käsitleda.
12. Lisage oma serveri klassi põhimeetod vastavalt oma serveri klassi nimele:
public static void main(String[] args) { GameServer gameServer = new GameServer(); }
(timestamp) 13. Järgmine asi, mida lisada oma konstruktorisse, on
Listener
.
Kryonet'i listener: vastutab erinevate sündmuste ja sõnumite käsitlemise eest Kryonet’i serveri käivitamise ajal. Kood, mis lisab
listener
, et printida vastuvõetud objekte, on järgmine:
server.addListener(new Listener() {
public void received(Connection connection, Object object) {
System.out.print(object);
}
});
Klient¶
(timestamp) Klient:
LibGDX on genereerinud meie projekti kliendi osa, mis koosneb kahest moodulist:
Desktop
moodul võimaldab lihtsat viisi mängu testida ja arendada töölauakeskkonnas.Core
moodul on koht, kuhu saate panna ühise koodi, mis hõlmab tavaliselt mängu loogikat või ressursside laadimist.
Vaadake näidisklienti GitHubis.
Kryonet’i seadistamine kliendi jaoks¶
(timestamp) Kryonet’i seadistamine kliendi jaoks:
14. Peate lisama Kryonet’i implementation Gradle’i dependency ka kliendi jaoks:
Navigeeri
client -> core -> build.gradle
Navigeeri Kryoneti Maveni Repository, et leida sobiv Gradle’i dependency teave.
Ehita projekt lisatud sõltuvusega kasutades
Tasks > build > build
Kliendi mänguklass¶
15. Nüüd avage oma kliendi mänguklass (client -> core -> src
).
LibGDX genereeris mõned meetodid mängu loomiseks:
create
meetodit kutsutakse üks kord, kui rakendus luuakse esmakordselt. Siin initsialiseeritakse tavaliselt ressursid, seatakse mängumaailm ja tehakse muud seadistamise ülesanded.render
meetod on koht, kus värskendatakse mänguloogikat, käsitsetakse sisendit ja joonistatakse graafikat.dispose
meetod kutsutakse rakenduse sulgemisel või hävitamisel. Siin tuleks vabastada kõik ressursid, näiteks tekstuurid, helid või muud varad, et vabastada mälu ja vältida ressursilekkeid.
Kliendi connection serveriga¶
(timestamp) Kliendi connection serveriga:
16. Impordi Kryonet oma kliendi mänguklassi:
import com.esotericsoftware.kryonet.Client;
17. Loo create
meetodis Kryonet’i klient:
client = new Client();
client.start();
Sõnumi saatmiseks serverile mängu alguses kasutage create
meetodis:
client.sendTCP("Start");
selleks, et saata sõna “Start” serverile.
Testige render meetodit, kirjutades sinna:
client.sendTCP("test");
18. Connect serveriga järgmise koodiga create meetodis:
try {
client.connect(5000, "localhost", 8080, 8081);
} catch (IOException e) {
throw new RuntimeException(e);
}
kus:
5000 on aegumisaeg, mille jooksul klient ootab connectioni loomist.
Localhost on serveri hostinimi või IP-aadress.
8080 ja 8081 on TCP ja UDP portide numbrid, millele klient connectib.
19. Pärast sessiooni lõppu sulgege klient dispose meetodis:
client.close();
try {
client.dispose();
} catch (IOException e) {
throw new RuntimeException(e);
}
20. Käivitage oma server (kui pole veel käivitatud) ja käivitage oma klient connectioni testimiseks.
Peaksite nägema pidevat sõnumit “test”.
Liikumise lisamine kliendile¶
(timestamp) Liikumise lisamine kliendile:
21. Nüüd lisame näiteks juba genereeritud LibGDX-assetile liikumise:
Render meetodis kasutatakse sprite’i renderdamiseks SpriteBatchi
.
begin()
jaend()
meetodid määratlevad partii ulatuse.draw()
meetodit kasutatakse iga individuaalse sprite’i jaoks.
Näeme, et batch.draw(img, 0, 0);
:
Esimene 0 on img sprite’i x-koordinaat ja teine 0 on y-koordinaat.
Sprite’i liigutamiseks peame olema võimelised muutma neid koordinaate.
22. Lisage klassile privaatsed int muutujad:
private int x = 0, y = 0;
23. Render meetodis pange batch.draw(img, 0, 0);
asemele batch.draw(img, x, y);
Liikumise käsitlemine¶
(timestamp) Liikumise käsitlemine:
24. Render meetodisse lisage järgmine kood, et muuta liikumist vastavalt nupulevajutusele:
if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) {
x -= 10;
}
if (Gdx.input.isKeyPressed(Input.Keys.RIGHT)) {
x += 10;
}
Nüüd muutub x-koordinaat. Saate klientmängu käivitada selle testimiseks.
Nüüd laseme mängijate koordinaadid serverile saata.
25. Rakendage meetod mängija koordinaatide saatmiseks serverile:
private void sendPositionInfoServer() { client.sendUDP(x + " " + y);}
26. Kutsuge seda iga kord pärast koordinaatide muutmist, nii et see oleks näiteks:
if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) {
x -= 10;
sendPositionInfoServer();
}
if (Gdx.input.isKeyPressed(Input.Keys.RIGHT)) {
x += 10;
sendPositionInfoServer();
}
ja nüüd iga kord, kui liigute, saadab see teie koordinaatide teabe serverile.
N-mängijate connection¶
(timestamp) N-mängijate connection:
27. Mitmete eksemplaride lubamine:
Mine
Run / Debug Configurations
Vali sealt
Edit Configurations...
Modify options
alt valiAllow multiple instances
Mitmete eksemplaride lubamine (Allow multiple instances
) tähendab seda, et saate oma
arvutis panna käima mitu mängu korraga. Ilma selleta saate jooksutada vaid ühte korraga.
(timestamp) Serveri listeneri
korral
kasutage,
server.sendToAllUDP(object);
et saata teavet kõigile klientidele.
(timestamp) 28. Kliendi create
meetodisse lisage listener, et
vastu võtta andmeid serverilt:
client.addListener(new Listener.ThreadedListener(new Listener() {
@Override
public void received(Connection connection, Object object) {
System.out.print("received: " + object);
}
}));
Nüüd saadab server teavet igale connected
kliendile.
(timestamp) Klientide eristamiseks kasutage serveris connectionide ID-sid ja haldage mänguobjekte ID-de ja koordinaatidega.
28. Serveri klassi lisage,
private Map<Integer, String> gameObjects = new HashMap<>();
et jälgida mänguobjekte.
29. Nüüd lisage see kood serveri listeneri
received
meetodi sisse:
if (object instanceof String) {
gameObjects.put(connection.getID(), (String) object);
}
server.sendToAllUDP(gameObjects.entrySet().stream().map(entry -> entry.getKey() + ":" + entry.getValue()).collect(Collectors.joining("|")));
See kood saadab iga connected
kliendi ID ja koordinaadid kõigile
klientidele.
Teiste klientide nähtavaks muutmine¶
(timestamp) Teiste klientide nähtavaks muutmine:
Teise näitena teiste klientide nähtavaks muutmiseks kasutame LibGDX-i vara “drop.png”.
30. Kliendi klassi:
Lisa
Texture opponentImg;
Initsialiseeri tekstuur
create
meetodis:opponentImg = new Texture("drop.png");
Disconnectioni käsitlemine¶
(timestamp) Disconnectioni
käsitlemine:
31. Serveri listeneri
korral ülekirjutage disconnected
meetod ja eemaldage
connected
mängijad:
@Override
public void disconnected(Connection connection) {
gameObjects.remove(connection.getID());
}
32. Muutke serveri edastusjoont serveri listeneri
korral:
server.sendToAllUDP(gameObjects.entrySet().stream().map(entry -> entry.getKey() + ":" + entry.getValue()).collect(Collectors.joining("|")));
saab
server.sendToAllUDP(gameObjects);
Selgitus:
Algne koodirida muudab enne saatmist andmed string
formaati, et neid oleks lihtsam lugeda.
Uus koodirida saadab koju objekti ilma töötlemiseta, mis võimaldab paindlikumalt kasutada edastatud andmeid kliendi poolel.
Saadetud mänguobjektide käsitlemine kliendil¶
(timestamp) Saadetud mänguobjektide käsitlemine kliendil:
33. Loo vastaste SpriteBatchide
jaoks kaardistus:
private Map<Integer, SpriteBatch> opponentBatches = new HashMap<>();
34. Lisage kaart vastu võetud mänguobjektide salvestamiseks kliendile:
private Map<Integer, String> receivedGameObjects = new HashMap<>();
35. Render
meetodis käitle vastaste renderdamist järgmise koodiga:
for (Map.Entry<Integer, String> entry : receivedGameObjects.entrySet()) {
int id = entry.getKey();
if (id == clientId) continue;
if (!opponentBatches.containsKey(id)) {
opponentBatches.put(id, new SpriteBatch());
}
SpriteBatch b = opponentBatches.get(id);
String[] coordinates = entry.getValue().split(",");
b.begin();
b.draw(opponentImg, Integer.parseInt(coordinates[0]), Integer.parseInt(coordinates[1]));
b.end();
}
if (receivedGameObjects != null) {
receivedGameObjects = null;
}
36. Kliendi klassis, lisage muutuja klient ID salvestamiseks:
private int clientId;
37. Määrake kliendi ID create
meetodis:
clientId = client.getID();
38. Kliendi listeneri
received
meetodis salvestage saadud andmed
receivedGameObjects
:
if (object instanceof Map) {
receivedGameObjects = (Map<Integer, String>) object;
}
Kryo registreerimine¶
(timestamp) Kryo registreerimine:
Veenduge, et Kryo registreerimine oleks nii serveris kui ka kliendis.
See tuleks teha võrguklassis nii serveris kui ka kliendis (näide), kuid me teeme selle põhiklassis näitena.
NB! Palun kasutage oma projektis selleks võrguklassi.
Kryo registreerimist kasutatakse kõigi klasside jaoks, kuna see teavitab Kryo serialiseerimise raamistikku klassidest, mis võivad võrgu kaudu saata.
39. Loo meetodis create
HashMap’i
registreerimiseks:
Kryo kryo = client.getKryo();
kryo.register(HashMap.class);
40. Serveri konstruktoris registreerige HashMap
:
Kryo kryo = server.getKryo();
kryo.register(HashMap.class);
Lõplik kaustade/failide hierarhia¶
Järgmine osa videost käsitleb serveri JAR-faili loomist ja selle üleslaadimist TalTech’i serverisse. Te ei pea seda hetkel tegema, kuna see toimub semestri teises pooles.