Sesi 1. Niat, Arsitektur, dan Alat Tempur Server Dewa
Sebelum kita ngomongin kode yang bikin pusing kepala, kita benerin mindset dulu. Bikin MMORPG pakai C++ itu ibarat ngebangun Candi Prambanan sendirian. Butuh kesabaran tingkat dewa.
Nah, bagian "waktu yang lama" (thuluz zaman) ini pas banget buat belajar C++. Nggak bisa instan kayak mi rebus, Cing!
Dari dunia modern, ada pepatah cakep dari Robert C. Martin (Uncle Bob) dalam bukunya yang legendaris, Clean Architecture:
"Satu-satunya cara untuk melaju cepat adalah dengan melangkah dengan benar (The only way to go fast, is to go well)."
Artinya apa Beh? Mending kita koding pelan-pelan tapi rapi, daripada ngebut tapi pas server game-nya jalan malah crash dan memory leak di mana-mana.
Tutorial Lengkap Membuat Web E-Commerce dengan Ruby dan Oracle Database
π️ 1. Paham Dulu Arsitekturnya (Biar Nggak Keder)
Di dunia MMORPG, ada dua kubu besar yang kerja bareng:
- Si Client (Bagian Depan): Ini game yang diinstal di HP atau PC pemain (pake Unreal Engine, Unity, dll). Tugasnya cuma nampilin gambar naga, suara pedang, dan nerima pencetan tombol dari pemain.
- Si Server (Bagian Belakang/Otak): Nah, INI YANG MAU KITA BIKIN PAKE C++. Server ini ibarat Babeh yang ngatur semuanya. Kalau ada pemain ngeklik "Serang Naga", Client bakal lapor ke Server. Server C++ kita yang ngitung, "Eh, damage-nya berapa nih? Naganya mati laka?". Kalau mati, Server lapor ke Database Oracle buat nyatet "Tambahin koin si A sebanyak 1000".
Kenapa Server harus C++? Karena pas pemainnya ada 10.000 orang nyerang barengan, cuma C++ yang kuat ngitung secepat kilat tanpa bikin servernya ngebul.
π ️ 2. Siapin Alat Tempur (Senjata buat Ngoding)
Encing dan Babeh nggak bisa nulis kode C++ di bungkus gorengan. Kita butuh alat khusus:
- IDE (Teks Editor Kelas Berat): Saya saranin pakai Visual Studio (Community Edition) buat yang pakai Windows, atau VS Code kalau mau entengan. Ini ibarat bengkel tempat kita ngerakit mesin.
- Compiler C++: Kalau pakai Visual Studio, ini udah otomatis ada (MSVC). Ini tugasnya nerjemahin tulisan bahasa Inggris kita jadi bahasa mesin 1 dan 0 yang dimengerti komputer.
- Database (Nanti dulu): Untuk Oracle, kita masukin di penjelasan yang agak jauhan. Kita fokus bikin Server-nya bisa napas dulu.
π» 3. Pemanasan: Bikin Server "Bisa Ngomong"
Biar tangannya lemes, mari kita tulis baris kode pertama. Buka IDE-nya, bikin file baru namanya ServerUtama.cpp. Ketik mantra sakti ini:
#include <iostream>
// Ini fungsi utama, jantungnya program C++ kita
int main() {
// std::cout itu ibarat kita nyuruh komputer ngomong
std::cout << "Assalamualaikum Dunia! Server MMORPG siap gass pol!" << std::endl;
// Return 0 tandanya program selesai tanpa error
return 0;
}
Penjelasan Santai:
#include <iostream>: Ini kayak kita ngambil kotak perkakas dari gudang biar program kita bisa ngeluarin tulisan di layar.int main(): Pintu masuknya program. Semua kejadian di game bakal berawal dari sini.
Kalau Encing Run atau jalankan programnya, bakal muncul tulisan hitam putih:
"Assalamualaikum Dunia! Server MMORPG siap gass pol!"
Sesi 2. Mengenal Konsep Class dan Object
dengerin kata Bjarne Stroustrup (Babehnya C++) di buku babonnya, The C++ Programming Language:
"Konsep paling penting di C++ adalah class. Class adalah tipe data yang secara langsung mewakili konsep dalam program Anda."
Intinya Enyak, Babeh, Cing... kalau mau bikin dunia MMORPG yang isinya bejibun (ada naga, ksatria, pedang, sihir), kita kudu paham yang namanya Class.
π️ 1. Apaan Tuh Class dan Object?
Biar gampang nyangkut di kepala, bayangin Cetakan Kue Pukis.
- Class: Cetakan kue pukisnya. Bentuknya udah pakem, ada bolongannya. Tapi cetakan ini nggak bisa dimakan, kan? Dia cuma konsep.
- Object: Kue pukis yang udah mateng. Ada yang rasa coklat, ada yang rasa keju. Semua dicetak dari cetakan yang sama, tapi wujud aslinya (Object) beda-beda.
Di game MMORPG:
- Class: KarakterPemain (Punya Darah/HP, Mana, Level, Nama).
- Object: Karakter Si Juki (HP 1000, Level 5) dan Karakter Si Pitung (HP 5000, Level 50).
π» 2. Mari Ngoding: Bikin Cetakan Karakter
Buka lagi alat tempur (Visual Studio) Encing sekalian. Kita bakal bikin Class sederhana buat karakter game kita.
#include <iostream>
#include <string> // Kita butuh ini buat nulis teks (nama karakter)
using namespace std;
// 1. INI DIA CETAKANNYA (CLASS)
class Karakter {
public: // Artinya sifat-sifat ini bisa diakses dari luar
string nama;
int hp; // Darah (Health Point)
int level;
int attack; // Kekuatan pukul
// Ini namanya "Method" atau aksi yang bisa dilakuin sama karakter
void tampilkanStatus() {
cout << "=== Status " << nama << " ===" << endl;
cout << "Level : " << level << endl;
cout << "HP : " << hp << endl;
cout << "Attack: " << attack << endl;
cout << "-----------------------" << endl;
}
void kenaPukul(int damage) {
hp = hp - damage;
cout << nama << " kena gebuk! HP ngurang " << damage << " poin." << endl;
if (hp <= 0) {
cout << "Innalillahi, " << nama << " udeh wassalam (Mati)." << endl;
} else {
cout << "Sisa HP " << nama << " sekarang: " << hp << endl;
}
}
};
// 2. INI PUSAT DUNIANYA (FUNGSI MAIN)
int main() {
// Kita bikin Object (Kue Pukisnya) dari cetakan Karakter
Karakter juki;
// Kita kasih 'ruh' atau data ke si Juki
juki.nama = "Juki Jagoan Silat";
juki.hp = 1000;
juki.level = 1;
juki.attack = 50;
// Kita panggil aksi buat nampilin statusnya
juki.tampilkanStatus();
// Ceritanya si Juki lagi jalan, eh digebuk monster
cout << "\n[Ceritanya ada monster iseng nimpuk batu...]\n" << endl;
juki.kenaPukul(300);
return 0;
}
π 3. Bedah Mesin (Biar Paham Nggak Cuma Copy-Paste)
Babeh, Enyak, Encing, perhatiin dah kode di atas:
class Karakter { ... };: Ini pondasi utamanya. Jangan lupa, di C++, nutup Class kudu pakai titik koma (;) di akhirnya. Kalau kelupaan, programnya ngambek minta ampun.public:: Ini ibarat kita buka gembok. Kalau nggak ditulis public, otomatis data si Juki (nama, hp) digembok sama C++ (private), nggak bisa kita ubah dari luar. (Nanti di penjelasan selanjutnya kita bahas kenapa kadang data kudu digembok biar aman dari hacker).juki.kenaPukul(300);: C++ itu pakai sistem titik (.). Ibarat kita nyuruh, "Eh Juki, lu lakuin aksi kena pukul sebesar 300 dong".
Sesi 3. Gembok Data (Encapsulation) & Constructor
Di penjelasan ini, kita bakal bahas jurus tingkat lanjut: Nggembok Data (Encapsulation) & Lahir Langsung Sakti (Constructor). Kenapa kudu digembok? Lah, ini kan server game Cing! Kalau datanya dibiarin telanjang, bisa di-hack sama cheater gampang banget.
π‘️ 1. Gembok Data Biar Kaga Kebobolan Cheat Engine
Sebelumnya di penjelasan, kita pakai kata kunci public:. Artinya, si Juki darahnya (HP) bisa diubah sembarangan dari luar fungsi. Bayangin kalau pemain iseng tiba-tiba nulis juki.hp = 9999999;. Rusak dah ekonomi dan keseimbangan game kita, Beh!
Makanya, kita kenalan sama Private (Gembok) dan Getter/Setter (Satpam).
- Private: Variabel cuma bisa dibaca dan diubah dari dalam cetakan (Class) itu sendiri.
- Getter/Setter: Fungsi resmi (satpam) buat baca atau ngubah data. Kalau mau kurangin HP, harus lewat pintu depan (fungsi kenaPukul), kaga boleh lewat jendela (langsung ubah variabel).
⚡ 2. Constructor: Bidan Persalinan Object
Dulu kita ngisi data si Juki satu-satu sehabis dia dibuat. Repot Cing! Di C++, ada yang namanya Constructor. Ini fungsi khusus yang namanya sama persis kayak nama Class-nya. Dia bakal otomatis dipanggil pas Object pertama kali dibikin (lahir). Ibaratnya, brojol langsung dikasih nama, baju, dan modal HP.
π» 3. Mari Ngoding: Server Makin Aman dan Rapi!
Buka lagi Visual Studio-nya Encing. Kita rombak kode Class Karakter kita biar lebih standar industri server!
#include <iostream>
#include <string>
using namespace std;
class Karakter {
// 1. BAGIAN PRIVATE (DIGEMBOK!)
// Ibarat jeroan atau hati, kaga boleh disentuh sembarangan dari luar
private:
string nama;
int hp;
int level;
int attack;
// 2. BAGIAN PUBLIC (PINTU DEPAN / SATPAM)
public:
// Ini dia CONSTRUCTOR! (Bidan persalinan)
// Dipanggil otomatis pas Karakter dibuat
Karakter(string namaBaru, int hpBaru, int levelBaru, int attackBaru) {
nama = namaBaru;
hp = hpBaru;
level = levelBaru;
attack = attackBaru;
cout << ">> [SISTEM] Karakter " << nama << " udah mendarat di dunia!" << endl;
}
// Fungsi Getter: Buat ngintip data (karena datanya di-private)
string getNama() {
return nama;
}
int getHP() {
return hp;
}
// Fungsi buat aksi (Setter/Logic)
void kenaPukul(int damage) {
// Karena ini di dalam Class, dia bebas ngakses variabel 'hp'
hp = hp - damage;
cout << nama << " kena sabetan pedang! HP ngurang " << damage << "." << endl;
if (hp <= 0) {
hp = 0; // Biar HP kaga jadi minus
cout << "Innalillahi, " << nama << " udeh tepar di tanah." << endl;
} else {
cout << "Sisa HP " << nama << " sekarang: " << hp << endl;
}
}
};
int main() {
// Bikin object sekarang LEBIH GAMPANG dan RAPI!
// Langsung panggil Constructor-nya
Karakter siPitung("Bang Pitung", 2000, 10, 150);
Karakter juki("Juki Polos", 500, 1, 20);
cout << "\n--- Pertarungan Dimulai ---\n" << endl;
// Coba Encing nulis: siPitung.hp = 99999; -> BISA KAGA?
// KAGA BISA! Pasti error kompilasi (merah), karena 'hp' udeh digembok (private).
// Ini yang bikin server kita kebal dari hack sembarangan!
// Si Pitung nyerang Juki (Ceritanya damage Pitung 150)
cout << siPitung.getNama() << " ngeluarin jurus silat!" << endl;
juki.kenaPukul(150);
return 0;
}
π 4. Bedah Mesin Singkat
Perhatiin pas bikin si Pitung: Karakter siPitung("Bang Pitung", 2000, 10, 150);. Kita nggak perlu repot-repot manggil siPitung.nama = ... lagi. Kodenya jadi bersih banget, enak dipandang.
Encing sekarang cuma bisa ngubah HP lewat fungsi kenaPukul. Artinya apa? Kita bisa naruh rumus pertahanan (Armor), chance ngeles (Dodge), atau efek racun (Poison) di dalam fungsi kenaPukul itu. Semua alur masuk data jadi kekontrol satu pintu!
Kopinya diseruput dulu, bismillah kita gas pol ke sesi 4: Bikin Kantong Ajaib (Sistem Inventory pake Vector).
Sesi 4. Bikin Kantong Ajaib (Sistem Inventory Pake Vector)
Di MMORPG, kaga asyik kan kalau karakter kita jalan-jalan tapi tangannya kosong, kaga punya tas buat nyimpen Potion (jamu penambah darah) atau Pedang? Nah, hari ini kita bakal ajarin si Juki bawa tas!
Saya bawain kutipan cakep dari buku legendarnya para programmer, yaitu "The Pragmatic Programmer" karya Andrew Hunt dan David Thomas:
"It's all about the data. The data is the most important part of your system. You have to manage it correctly." > (Semuanya itu tentang data. Data adalah bagian paling penting dari sistemmu. Kamu harus mengelolanya dengan bener).
Di C++, kalau kita mau nyimpen banyak data (misalnya 100 item di dalam tas), kita kaga mungkin bikin variabel satu-satu kayak barang1, barang2, sampai barang100. Keder, Beh! Makanya, kita kenalan sama Vector.
π 1. Apaan Tuh Vector? (Beda Sama Array Biasa)
Sebenernya buat nyimpen banyak barang berjejer, C++ punya yang namanya Array. Tapi Array biasa itu kaku, Cing. Kalau dari awal kita pesen tempat buat 5 barang, ya udah mentok 5. Kaga bisa nambah lagi.
Nah, di C++ modern, ada senjata rahasia namanya std::vector. Vector ini ibarat Kantong Ajaib Doraemon. Ukurannya bisa melar otomatis! Kalau barangnya nambah, tasnya otomatis makin gede. Kalau barangnya dibuang, tasnya nyusut lagi. Mantep bener, kan?
π» 2. Mari Ngoding: Karakter Kita Punya Ransel!
Buka lagi Visual Studio-nya. Kita bakal tambahin kotak perkakas baru namanya <vector> ke dalam kode kita Sebelumnya.
#include <iostream>
#include <string>
#include <vector> // INI DIA KOTAK PERKAKAS BARU KITA!
using namespace std;
class Karakter {
private:
string nama;
int hp;
// Nah, ini kita bikin Ransel!
// Formatnya: vector<tipe_datanya> nama_variabelnya;
vector<string> ransel;
public:
// Constructor (Bidan persalinan) dari sesi 3
Karakter(string namaBaru, int hpBaru) {
nama = namaBaru;
hp = hpBaru;
cout << ">> [SISTEM] " << nama << " mendarat di dunia!" << endl;
}
// Fungsi buat masukin barang ke dalem tas
void dapetBarang(string namaBarang) {
// push_back itu jurus andalan vector buat dorong barang ke urutan paling belakang
ransel.push_back(namaBarang);
cout << nama << " nemu barang: [" << namaBarang << "]" << endl;
}
// Fungsi buat ngintip isi tas
void bongkarRansel() {
cout << "\n=== Ransel Si " << nama << " ===" << endl;
// Kita cek dulu, ranselnya kosong apa kaga?
if (ransel.empty()) {
cout << "Yah, tasnya kosong melompong, debuan." << endl;
cout << "-----------------------" << endl;
return; // Kalo kosong, langsung kelar fungsinya
}
// Kalo ada isinya, kita pake LOOPING (Perulangan) buat ngeluarin satu-satu
cout << "Isi tas sekarang:" << endl;
for (string barang : ransel) {
cout << "-> " << barang << endl;
}
cout << "-----------------------" << endl;
}
};
int main() {
// Bikin si Juki
Karakter juki("Juki Polos", 500);
// Si Juki awal-awal ngecek tas
juki.bongkarRansel();
cout << "\n[Ceritanya Juki lagi jalan-jalan di hutan...]\n" << endl;
// Si Juki nemu barang-barang!
juki.dapetBarang("Pedang Kayu");
juki.dapetBarang("Jamu Kuat (HP Potion)");
juki.dapetBarang("Kulit Serigala");
// Si Juki ngecek tas lagi setelah dapet barang
juki.bongkarRansel();
return 0;
}
π 3. Bedah Mesin (Biar Paham Jeroannya)
Babeh, Enyak, Encing, ada dua jurus baru yang kita pelajarin di kode atas:
ransel.push_back(namaBarang);Ini ibarat Enyak masukin beras ke dalem karung. Fungsi push_back() ini otomatis ngegedein ukuran vector kita dan naruh datanya di antrean paling belakang.for (string barang : ransel)Ini namanya Range-based For Loop. Dibacanya gampang banget: "Untuk setiap barang (yang berupa teks) di dalam ransel, tolong tampilin ke layar." Mesin C++ bakal muter terus nampilin barang dari urutan pertama sampe barang terakhir, terus otomatis berhenti sendiri. Kaga perlu capek-capek ngitung!
Sesi 5. Logika Baku Hantam (Attack vs Defense)
Masa iya game MMORPG cuma jalan-jalan mungutin barang doang? Kaga asyik kalau kaga ada baku hantamnya! Hari ini kita bakal bikin rumus Damage yang danta, biar si Juki bisa berantem sama monster atau pemain lain.
Biar kodingannya makin berkah, kita kutip dari buku "Game Programming Patterns" karya Robert Nystrom:
"A game is a machine that runs on state. The core of that machine is the logic that changes that state over time." > (Game itu mesin yang jalan pake status. Inti dari mesin itu adalah logika yang ngubah status seiring berjalannya waktu).
Maksudnya apa Beh? Pas berantem, status HP (darah) karakter kita bakal berubah terus. Nah, tugas kita sebagai programmer C++ adalah bikin logika "perubahan" itu biar adil dan kaga bug.
⚔️ 1. Logika Baku Hantam (Attack vs Defense)
Kalo cuma HP - Damage, itu mah kado ulang tahun, kemurahan! Game yang bagus kudu punya sistem Defense (Pertahanan/Armor). Rumus sederhananya gini:
$$Total\ Damage = Damage\ Penyerang - Defense\ Korban$$Tapi hati-hati, jangan sampe hasilnya minus. Masa dipukul malah nambah darah? Kan lucu, Cing. Jadi kalau Defense lebih gede dari Damage, minimal si korban tetep kena 1 poin damage (kena mental dikit lah).
π» 2. Mari Ngoding: Jurus Pukul-pukulan!
Buka Visual Studio-nya. Kita tambahin variabel defense dan fungsi serang() di dalam Class Karakter kita.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Karakter {
private:
string nama;
int hp;
int attack;
int defense; // Variabel baru buat nahan serangan
public:
// Constructor kita tambahin input defense
Karakter(string namaBaru, int hpBaru, int atkBaru, int defBaru) {
nama = namaBaru;
hp = hpBaru;
attack = atkBaru;
defense = defBaru;
cout << ">> [SISTEM] " << nama << " siap tempur!" << endl;
}
// Fungsi buat NYERANG karakter lain
// Kita kirim "alamat" karakter lawan pake tanda (&) biar datanya sinkron
void serang(Karakter &lawan) {
cout << "\n[!] " << nama << " nerjang " << lawan.nama << "!" << endl;
// Panggil fungsi terimaDamage milik si lawan
lawan.terimaDamage(attack);
}
// Fungsi buat NERIMA serangan
void terimaDamage(int damageMasuk) {
// Rumus: Damage dikurangin Defense kita
int totalDamage = damageMasuk - defense;
// Biar kaga minus (kalo defense lebih gede dari damage)
if (totalDamage < 1) {
totalDamage = 1; // Minimal kena 1 poin lah
}
hp -= totalDamage;
cout << "[-] " << nama << " nahan serangan, kena " << totalDamage << " poin." << endl;
if (hp <= 0) {
hp = 0;
cout << "[XXX] " << nama << " udeh tepar, kaga bangun lagi!" << endl;
} else {
cout << "[+] Sisa HP " << nama << " : " << hp << endl;
}
}
};
int main() {
// Kita bikin dua petarung
// Nama, HP, Attack, Defense
Karakter juki("Juki Silat", 500, 80, 20);
Karakter preman("Preman Terminal", 600, 50, 40);
cout << "\n--- ARENA BAKU HANTAM DIMULAI ---" << endl;
// Ronde 1: Juki nyerang Preman
juki.serang(preman);
// Ronde 2: Preman bales nyerang Juki
preman.serang(juki);
return 0;
}
π 3. Bedah Mesin (Penting Nih, Cing!)
Perhatiin bagian ini: void serang(Karakter &lawan). Ada tanda & (Ampersand). Di C++ ini namanya Reference.
Kenapa pake &? Biar kita nyerang Object yang asli. Kalau kaga pake &, C++ bakal bikin "fotokopian" si lawan. Kita gebukin fotokopiannya sampe mati, eh lawan yang aslinya masih seger bugar di pojokan. Kan berabe, bisa diprotes pemain kita!
Logika Kerja: Pas juki.serang(preman), si Juki ngirim nilai attack-nya ke fungsi terimaDamage milik si Preman. Di sana, HP si Preman langsung dipotong setelah dikurangin defense-nya dia. danta kan?
Sesi 6. Sistem Level Up & EXP (Experience Points)
Nah, di sesi 6 ini, kita bakal bikin si Juki makin gahar. Masa iya dipukul terus tapi kaga pinter-pinter? Di MMORPG, makin sering kita berantem, kudu makin jago dong. Kita bakal bahas Sistem Level Up & EXP (Experience Points). Jadi kalau si Juki menang lawan musuh, dia dapet ilmu (EXP) terus naik pangkat!
"Programming is about problem-solving. Every time you solve a problem, you become a better programmer." > (Ngoding itu tentang nyelesain masalah. Tiap kali Encing nyelesain satu masalah, Encing bakal jadi programmer yang lebih jago).
Sama kayak di game, tiap monster yang dikalahin itu masalah yang kelar, makanya karakter kita dapet reward berupa EXP buat naik level.
π 1. Konsep Naik Level (Biar Kagak Ribet)
Biar sistemnya danta, kita kudu punya aturan:
- EXP Target: Berapa poin yang dibutuhin buat naik level? (Misalnya: Level 1 butuh 100 EXP).
- Stat Bonus: Pas naik level, jangan cuma angkanya doang yang berubah. Darah (HP) kudu nambah, pukulan (Attack) kudu makin sakit, dan pertahanan (Defense) makin keras.
- Progresi: Tiap naik level, target EXP-nya kudu makin gede. Masa dari level 1 ke 2 sama susahnya ama level 99 ke 100? Bisa protes nanti pemainnya, Beh!
π» 2. Mari Ngoding: Si Juki Latihan Biar Sakti!
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Karakter {
private:
string nama;
int hp, maxHp; // Kita tambah maxHp buat patokan sembuh
int attack, defense;
int level;
int exp;
int expNextLevel; // Target EXP buat naik level selanjutnya
public:
Karakter(string namaBaru, int hpBaru, int atkBaru, int defBaru) {
nama = namaBaru;
hp = hpBaru;
maxHp = hpBaru;
attack = atkBaru;
defense = defBaru;
level = 1;
exp = 0;
expNextLevel = 100; // Awalnya butuh 100 EXP
cout << ">> [SISTEM] " << nama << " lahir ke dunia (Level 1)!" << endl;
}
// Fungsi buat dapet EXP pas menang
void dapetExp(int poin) {
exp += poin;
cout << "[+] " << nama << " dapet " << poin << " EXP." << endl;
// Cek apakah EXP-nya udah cukup buat naik level
if (exp >= expNextLevel) {
naikLevel();
}
}
// Fungsi otomatis naik level (Hanya bisa dipanggil dari dalam/Private-ish)
void naikLevel() {
level++;
exp -= expNextLevel; // Sisa EXP dibawa ke level berikutnya
expNextLevel += 50; // Level berikutnya makin susah nambah 50
// Bonus Stat pas naik level (Makin Gahar!)
maxHp += 50;
hp = maxHp; // Darah penuh lagi pas naik level
attack += 10;
defense += 5;
cout << "\n========================================" << endl;
cout << ">>> ALHAMDULILLAH! " << nama << " NAIK KE LEVEL " << level << "! <<<" << endl;
cout << ">>> Darah, Attack, & Defense nambah makin kuat! <<<" << endl;
cout << "========================================\n" << endl;
}
void tampilkanStatus() {
cout << "--- Status " << nama << " ---" << endl;
cout << "Level : " << level << endl;
cout << "HP : " << hp << "/" << maxHp << endl;
cout << "Attack : " << attack << endl;
cout << "EXP : " << exp << "/" << expNextLevel << endl;
cout << "-----------------------" << endl;
}
};
int main() {
// Si Juki baru lahir
Karakter juki("Si Juki", 100, 20, 5);
juki.tampilkanStatus();
cout << "\n[Ceritanya Juki abis gebukin Kecoa Raksasa...]\n" << endl;
// Juki menang, dapet 60 EXP
juki.dapetExp(60);
juki.tampilkanStatus();
cout << "\n[Juki gebukin Tikus Got Mutasi, dapet 50 EXP lagi...]\n" << endl;
// Juki dapet 50 lagi, total 110. Harusnya naik level!
juki.dapetExp(50);
juki.tampilkanStatus();
return 0;
}
π 3. Bedah Mesin (Dengerin Baeke, Cing!)
maxHpvshp: Ini penting, Beh. Kalau cuma punya variabel hp, pas naik level kita bingung mau nambahin darah sampe mana. Dengan adanya maxHp, kita punya batas atas buat nyembuhin karakter pas dia naik level atau minum potion nanti.- Logika
exp >= expNextLevel: Ini jantungnya sistem progresi. Begitu tabungan EXP si Juki lewat dari target, fungsi naikLevel() langsung teriak dan ngerombak semua status si Juki jadi lebih kuat. - Efek Domino: Perhatiin pas naik level, saya nambahin
expNextLevel += 50;. Ini trik biar tiap level kerasa tantangannya. Makin tinggi level, makin banyak monster yang kudu digebuk.
Sesi 7. Menyimpan Data (Saving to File)
Bayangin udah cape-cape ngebabu gebukin monster dari level 1 sampe level 50, eh tiba-tiba mati lampu atau servernya ngadat. Pas dinyalain lagi, si Juki balik lagi ke level 1. Apa kaga mau banting monitor itu pemainnya? Nah, makanya kita butuh yang namanya Persistence (Data yang awet).
"The primary purpose of software is to manage data. Data is the raison d'Γͺtre of most programs." > (Tujuan utama dari software itu ya buat ngelola data. Data itu adalah alasan kenapa program itu ada).
Maksudnya apa Beh? Ya percuma program Encing canggih, grafiknya kinclong, tapi pas ditutup datanya ilang. Itu mah bukan MMORPG, tapi maen tebak-tebakan!
π️ 1. Kenalan ama Oracle dan Temen-temennya
Di dunia industri, buat nyimpen data jutaan pemain MMORPG, kita kaga bisa cuma ngandelin harapan. Kita butuh database kelas berat kayak Oracle. Kenapa Oracle? Karena dia punya sistem yang namanya ACID (Atomicity, Consistency, Isolation, Durability). Intinya: Sekali data "Simpan" diklik, biarpun petir nyamber server, datanya kaga bakalan korup atau ilang di tengah jalan.
Gimana C++ Ngomong ama Oracle? Kita pake library namanya OCCI (Oracle C++ Call Interface). C++ bakalan ngirim perintah "Bahasa SQL" ke Oracle buat nyatet status si Juki.
π» 2. Mari Ngoding: Belajar "Nulis" Data (Pemanasan pake File)
Karena nyambungin C++ ke Oracle itu butuh instalasi library yang rada ribet (kudu pasang Oracle Client dulu), sebagai pemanasan di sesi 7 ini saya ajarin dulu cara Saving ke dalam file teks (.txt). Logikanya sama kok, nanti tinggal ganti pintunya doang ke Oracle.
Kita pake kotak perkakas baru namanya <fstream> (File Stream).
#include <iostream>
#include <string>
#include <fstream> // KOTAK PERKAKAS BUAT NYIMPEN KE FILE
using namespace std;
class Karakter {
private:
string nama;
int hp, level, exp;
public:
Karakter(string n, int h, int l, int e) : nama(n), hp(h), level(l), exp(e) {}
// JURUS SIMPEN DATA (SAVE GAME)
void simpanData() {
// ofstream itu 'Output File Stream' (Buat nulis ke file)
ofstream fileSimpanan("data_pemain.txt");
if (fileSimpanan.is_open()) {
fileSimpanan << nama << endl;
fileSimpanan << hp << endl;
fileSimpanan << level << endl;
fileSimpanan << exp << endl;
fileSimpanan.close(); // Jangan lupa ditutup pintunya, Beh!
cout << "[SISTEM] Data " << nama << " berhasil disimpen di memori!" << endl;
} else {
cout << "[SISTEM] Waduh, gagal nulis file, Cing!" << endl;
}
}
void tampilkan() {
cout << "Status Saat Ini: " << nama << " | Lvl: " << level << " | HP: " << hp << endl;
}
};
int main() {
// Ceritanya si Juki udah level 5
Karakter juki("Si Juki", 250, 5, 450);
cout << "--- Sebelum Disimpen ---" << endl;
juki.tampilkan();
// Kita jalanin perintah simpen!
juki.simpanData();
cout << "\nCoba Encing cek di folder kodingannya, ada file 'data_pemain.txt' kaga?" << endl;
return 0;
}
π 3. Bedah Mesin (Danta-in Dulu)
ofstream: Ini ibarat pulpen buat nulis di kertas digital. Namanya data_pemain.txt.Operator <<: Sama kayak kita mau nampilin tulisan di layar (cout), tapi bedanya ini kitaarahin ke dalem file.- Alur ke Oracle: Nanti kalau udah pake Oracle, kodenya berubah dikit. Bukan nulis ke file, tapi C++ bakal ngirim perintah SQL kayak:
UPDATE pemain_table SET level = 5 WHERE nama = 'Si Juki';.
Sesi 8. Bangkitin Data (Loading Data/Deserialization)
sebelumnya kita udah belajar cara "Nulis" atau nyimpen data si Juki ke dalem file biar kaga ilang pas mati lampu. Nah, sekarang di sesi 8, kita bakal bahas kebalikannya: Cara Bangkitin Data (Loading Data/Deserialization).
Ibaratnya nih Beh, si Juki baru bangun tidur (login lagi), dia kudu inget sebelumnya levelnya udah berapa, darahnya sisa berapa. Jangan sampe si Juki kena amnesia gara-gara kita kaga bisa ngebaca data yang udah kita simpen!
"Input and output are about how we communicate with the world outside our program. To do this effectively, we must understand how to represent our data in a way that can be stored and retrieved reliably."
Maksudnya apa Cing? Ya itu tadi, nyimpen data (Save) itu baru setengah jalan. Kalau kaga bisa diambil lagi (Load), ya wassalam, usaha kita sia-sia!
π 1. Konsep Ngebaca Data (ifstream)
Kalau sebelumnya kita pake ofstream (Output File Stream) buat nulis, sekarang kita pake kembarannya: ifstream (Input File Stream).
- ofstream: Kita jadi penulis yang nyoret-nyoret di kertas.
- ifstream: Kita jadi pembaca yang ngebaca tulisan di kertas itu terus dimasukin ke otak (memori komputer).
π» 2. Mari Ngoding: Bangkitin Si Juki dari Kubur (File)!
Ayo buka lagi Visual Studio-nya. Kita tambahin fungsi muatData() di dalem Class Karakter kita.
#include <iostream>
#include <string>
#include <fstream> // Masih pake ini buat urusan file
using namespace std;
class Karakter {
private:
string nama;
int hp, level, exp;
public:
// Constructor kosong dulu buat wadah data yang bakal dibaca
Karakter() : nama(""), hp(0), level(0), exp(0) {}
// JURUS MUAT DATA (LOAD GAME)
bool muatData() {
// ifstream itu 'Input File Stream' (Buat ngebaca dari file)
ifstream fileSimpanan("data_pemain.txt");
if (fileSimpanan.is_open()) {
// Kita baca urutannya kudu SAMA PAS KITA NYIMPEN sebelumnya!
// 1. Baca Nama
getline(fileSimpanan, nama);
// 2. Baca HP, Level, dan EXP
fileSimpanan >> hp >> level >> exp;
fileSimpanan.close(); // Kelar baca, tutup lagi pintunya
cout << "[SISTEM] Data berhasil dimuat! Selamat dateng lagi, " << nama << "!" << endl;
return true;
} else {
cout << "[SISTEM] Waduh, kaga ada file simpenannya, Cing!" << endl;
return false;
}
}
void tampilkanStatus() {
cout << "\n=== Status Login " << nama << " ===" << endl;
cout << "Level : " << level << endl;
cout << "HP : " << hp << endl;
cout << "EXP : " << exp << endl;
cout << "-----------------------" << endl;
}
};
int main() {
// Kita bikin object kosong dulu, ibarat badan tanpa nyawa
Karakter juki;
cout << "--- Mencoba Bangkitin Data Juki... ---" << endl;
// Kita suruh si Juki ngebaca file yang sebelumnya kita bikin
if (juki.muatData()) {
juki.tampilkanStatus();
} else {
cout << "Coba cek lagi, sebelumnya udeh jalanin sesi 7 belom? Hehe." << endl;
}
return 0;
}
π 3. Bedah Mesin (Danta-in Dulu, Beh!)
getline(fileSimpanan, nama): Kenapa pake getline? Karena nama si Juki mungkin ada spasinya (kayak "Juki Silat"). Kalau pake>>biasa, dia bakal kepotong pas nemu spasi.- Urutan itu Harga Mati: Pas di sesi 7 kita nyimpen: Nama -> HP -> Level -> EXP. Pas ngebaca di sesi 8, urutannya KUDU SAMA. Kalau kebalik (misal baca Level dulu baru Nama), programnya bakal keder dan datanya jadi ngaco. Level si Juki bisa-bisa isinya malah teks nama!
bool: Fungsi muatData() saya kasih tipe bool biar kita tau sukses apa kaga. Kalau file-nya kaga ada (misal belom pernah Save), program kaga bakal crash.
Sesi 9. Dunia Rame (Managing Multiple Players)
Nah, di sesi 9 ini, kita bakal bikin Dunia Rame (Managing Multiple Players). Kita bakal belajar gimana caranya server C++ kita nampung banyak pemain sekaligus di dalem satu list, biar mereka bisa ngeronda bareng di dalem game!
"An aggregate object, such as a list, should give you a way to access its elements without exposing its internal structure." > (Sebuah objek gabungan, kayak list gitu, kudu ngasih cara buat kita ngakses isinya tanpa perlu pamerin jeroannya).
Maksudnya apa Cing? Maksudnya, kita butuh satu "Wadah" (List) buat nampung semua pemain yang lagi online, tapi kita ngaturnya kudu rapi, kaga boleh berantakan!
π 1. Konsep "Dunia" (Server Manager)
Kalo sebelumnya kita cuma bikin variabel juki, sekarang kita bakal bikin satu Class baru namanya DuniaGame. Ibaratnya nih, DuniaGame ini adalah Kelurahan. Di dalem Kelurahan, ada daftar warga (Pemain). Si Lurah (Server) tugasnya nyatet siapa aja yang lagi ada di wilayahnya.
Kita bakal pake senjata rahasia dari sebelumnya, yaitu std::vector, tapi kali ini isinya bukan cuma teks, melainkan Object Karakter!
π» 2. Mari Ngoding: Bikin Server Rame Pemain!
Ayo tarik kursinya, kita rakit "Kelurahan Digital" kita.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
// Ini Class Karakter yang sebelumnya (disingkat biar kaga kepanjangan)
class Karakter {
public:
string nama;
int level;
Karakter(string n, int l) : nama(n), level(l) {}
void info() {
cout << "[Pemain] Nama: " << nama << " | Level: " << level << endl;
}
};
// --- INI DIA CLASS BARU: DUNIA GAME ---
class DuniaGame {
private:
// List buat nampung semua pemain yang lagi online
vector<Karakter> daftarPemain;
public:
// Fungsi buat nambahin pemain baru ke dalem dunia
void pemainMasuk(Karakter p) {
daftarPemain.push_back(p);
cout << ">> [SERVER] " << p.nama << " baru aja login (Masuk ke Dunia)." << endl;
}
// Fungsi buat ngabsen: Siapa aja sih yang lagi online?
void absenWarga() {
cout << "\n=== DAFTAR PEMAIN ONLINE SAAT INI ===" << endl;
if (daftarPemain.empty()) {
cout << "Sepi bener, kaga ada orang..." << endl;
} else {
for (int i = 0; i < daftarPemain.size(); i++) {
cout << i + 1 << ". ";
daftarPemain[i].info();
}
}
cout << "=====================================\n" << endl;
}
};
int main() {
// Kita bikin Kelurahannya dulu
DuniaGame serverJakarta;
// Ada warga baru dateng
Karakter p1("Si Juki", 10);
Karakter p2("Mpok Hindun", 25);
Karakter p3("Bang Pitung", 99);
// Mereka semua login masuk server
serverJakarta.pemainMasuk(p1);
serverJakarta.pemainMasuk(p2);
serverJakarta.pemainMasuk(p3);
// Pak Lurah (Server) ngabsen siapa aja yang ada
serverJakarta.absenWarga();
return 0;
}
π 3. Bedah Mesin (Dengerin Baeke, Cing!)
vector<Karakter> daftarPemain:Ini kuncinya! Kita bikin tas yang isinya adalah orang (Object). C++ pinter, dia bisa nampung jutaan Object di dalem sini asal memorinya cukup.daftarPemain.size():Ini cara kita nanya ke vector, "Eh, ada berapa orang sih di dalem?". Sangat berguna buat nampilin jumlah pemain online.- Encapsulation (Lagi!): Perhatiin deh, daftarPemain ditaruh di private. Kenapa? Biar kaga ada pemain iseng yang bisa ngapus temennya dari daftar secara ilegal. Semua kudu lewat pintu resmi yaitu fungsi pemainMasuk.
Sesi 10. Sistem Siaran Jagat (World Chat & Broadcasting)
Di sesi 10 ini, kita bakal bikin Sistem Siaran Jagat (World Chat & Broadcasting). Kita bakal belajar gimana caranya satu orang ngomong, eh semuanya denger!
"The Observer Pattern: Keeping your objects in the know. It defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically." > (Pola Observer: Menjaga objek-objekmu tetep tau informasi terbaru. Ini nentuin hubungan satu-ke-banyak antar objek, jadi pas satu objek berubah, semua yang terkait bakal dapet kabar dan otomatis terupdate).
Maksudnya apa Beh? Di game MMORPG, kalau ada satu pemain teriak "Woy, bantuin lawan naga!", semua pemain yang lagi online kudu dapet pesan itu di layar mereka. Inilah yang namanya Broadcasting.
π£ 1. Konsep Siaran (Broadcast)
Bayangin Babeh lagi di dalem masjid pake mik (mikrofon). Pas Babeh ngomong, semua orang di dalem masjid denger suara Babeh.
- Babeh: Si pengirim pesan (Broadcaster).
- Mikrofon: Server C++ kita.
- Jamaah: Semua objek pemain di dalem vector kita.
Di C++, kita bakal bikin fungsi di dalem DuniaGame yang tugasnya muterin daftar pemain satu-satu, terus "nempelin" pesan chat itu ke masing-masing layar mereka.
π» 2. Mari Ngoding: Dunia Game Makin Rame!
Ayo buka lagi Visual Studio-nya. Kita tambahin fitur chat di Class Karakter dan fitur siaran di Class DuniaGame.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Karakter {
public:
string nama;
int level;
Karakter(string n, int l) : nama(n), level(l) {}
// Fungsi buat nampilin chat di layar pemain
void terimaChat(string pengirim, string isiPesan) {
cout << "[" << nama << " nerima pesan]: " << pengirim << " ngomong: \"" << isiPesan << "\"" << endl;
}
};
class DuniaGame {
private:
// Pake tanda (&) atau pointer biasanya lebih mantep,
// tapi buat belajar kita pake vector biasa dulu ya Cing
vector<Karakter> daftarPemain;
public:
void pemainMasuk(Karakter p) {
daftarPemain.push_back(p);
cout << ">> [SERVER] " << p.nama << " masuk ke server." << endl;
}
// --- INI DIA JURUS SIARAN JAGAT (BROADCAST) ---
void siaranPesan(string pengirim, string pesan) {
cout << "\n>>> [WORLD CHAT] " << pengirim << ": " << pesan << " <<<" << endl;
// Kita absen satu-satu warganya, terus kasih tau pesannya
// Pake tanda & (reference) biar kita akses objek yang asli
for (Karakter &p : daftarPemain) {
p.terimaChat(pengirim, pesan);
}
}
};
int main() {
// 1. Setup Server
DuniaGame serverJakarta;
// 2. Warga pada Login
Karakter juki("Si Juki", 10);
Karakter hindun("Mpok Hindun", 25);
Karakter pitung("Bang Pitung", 99);
serverJakarta.pemainMasuk(juki);
serverJakarta.pemainMasuk(hindun);
serverJakarta.pemainMasuk(pitung);
// 3. Waktunya Siaran!
// Ceritanya si Juki lagi butuh bantuan
cout << "\n--- Kejadian di Dunia Game ---" << endl;
serverJakarta.siaranPesan(juki.nama, "Woy, ada yang liat naga lewat kaga?");
// Ceritanya Bang Pitung ngerespon
cout << endl;
serverJakarta.siaranPesan(pitung.nama, "Tenang Juk, udeh ane sabet pake golok!");
return 0;
}
π 3. Bedah Mesin (Danta-in Dulu, Beh!)
for (Karakter &p : daftarPemain):Perhatiin ada tanda & di situ. Di C++, ini penting banget. Kalau kagak pake &, C++ bakal bikin "fotokopian" pemain pas lagi muter-muter di dalem loop. Kalau cuma fotokopiannya yang nerima chat, eh pemain yang asli malah kagak tau apa-apa. Jadi kita pake & biar langsung kena ke orangnya.- Logika Interaksi: Si pengirim (misal: Juki) ngirim teks ke Server (DuniaGame), terus Server ngebantuin Juki buat teriak ke semua orang di daftarPemain. Inilah dasar gimana sistem komunikasi di MMORPG bekerja.
Kopinya disruput dulu, biar pikiran makin danta (jelas) dan kaga gampang spaneng.
Sesi 11. Sistem Koordinat (X, Y) & Jalan-jalan Cantik
sebelumnya kita udeh bikin warga server pada bisa ngobrol (World Chat). Tapi masa iya pemain MMORPG cuma bengong di satu titik doang sambil ngerumpi? Kaga seru, Beh! Kita butuh yang namanya Perpindahan Posisi. Nah, di sesi 11 ini, kita bakal bahas Sistem Koordinat (X, Y) & Jalan-jalan Cantik.
"At its core, a game engine is a tool for managing the state of a virtual world over time. One of the most fundamental parts of that state is the position and orientation of objects in space." > (Intinya mah, mesin game itu alat buat ngatur kondisi dunia virtual. Salah satu kondisi yang paling mendasar ya posisi dan arah objek di dalem ruang tersebut).
Maksudnya apa Cing? Ya kalau si Juki kaga punya posisi (X, Y), dia itu ibarat ghaib, ada suaranya (chat) tapi kaga keliatan wujudnya di peta!
πΊ️ 1. Konsep Koordinat (Biar Kagak Nyasar)
Bayangin dunia game kita itu kayak Kertas Kotak-kotak (Grid) atau kayak ubin di teras rumah Encing.
- Sumbu X: Garis mendatar. Kalau X nambah, Juki jalan ke Kanan (Timur). Kalau X ngurang, Juki jalan ke Kiri (Barat).
- Sumbu Y: Garis tegak. Kalau Y nambah, Juki jalan ke Atas (Utara). Kalau Y ngurang, Juki jalan ke Bawah (Selatan).
Ibaratnya nih, posisi awal Juki ada di (0,0). Kalau dia mau ke warung di posisi (3,2), berarti dia kudu geser 3 ubin ke kanan dan 2 ubin ke depan.
π» 2. Mari Ngoding: Si Juki Mulai Melangkah!
Ayo buka Visual Studio-nya lagi. Kita tambahin variabel posisi x dan y di dalem Class Karakter kita.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Karakter {
public:
string nama;
// Koordinat posisi si Juki
int x, y;
Karakter(string n, int startX, int startY) {
nama = n;
x = startX;
y = startY;
cout << ">> [SISTEM] " << nama << " muncul di koordinat (" << x << "," << y << ")" << endl;
}
// Fungsi buat geser posisi
void jalan(int deltaX, int deltaY) {
x += deltaX;
y += deltaY;
cout << "[LOG] " << nama << " pindah ke posisi baru: (" << x << "," << y << ")" << endl;
}
void statusPosisi() {
cout << "Posisi " << nama << " sekarang ada di: [" << x << ", " << y << "]" << endl;
}
};
class DuniaGame {
private:
vector<Karakter*> daftarPemain; // Kita pake pointer biar gampang update-nya
public:
void pemainMasuk(Karakter* p) {
daftarPemain.push_back(p);
}
// Fungsi buat ngasih tau semua orang kalau ada yang jalan
void updateDunia() {
cout << "\n--- UPDATE POSISI DUNIA ---" << endl;
for (auto p : daftarPemain) {
p->statusPosisi();
}
cout << "---------------------------\n" << endl;
}
};
int main() {
DuniaGame serverJakarta;
// Juki dan Pitung login di titik tengah (0,0)
Karakter juki("Si Juki", 0, 0);
Karakter pitung("Bang Pitung", 0, 0);
serverJakarta.pemainMasuk(&juki);
serverJakarta.pemainMasuk(&pitung);
// Ceritanya si Juki mau nyari naga ke arah Timur (X+)
cout << "\n[Aksi Juki]" << endl;
juki.jalan(5, 0); // Geser 5 langkah ke kanan
// Ceritanya Bang Pitung mau ke pasar di arah Utara (Y+)
cout << "[Aksi Pitung]" << endl;
pitung.jalan(0, 3); // Geser 3 langkah ke depan
// Cek posisi semua pemain di server
serverJakarta.updateDunia();
return 0;
}
π 3. Bedah Mesin (Dengerin Baeke, Cing!)
x += deltaX;: Ini cara C++ nambahin nilai variabel lama sama nilai baru. Jadi kalau tadinya x itu 0, terus dijalanin jalan(5, 0), sekarang x jadi 5.deltaX dan deltaY: Ini maksudnya adalah "selisih" langkahnya. Kalo mau jalan ke kiri, tinggal kasih angka minus, misal jalan(-2, 0).Pointer Karakter*: Perhatiin di vector, saya pake tanda bintang (*). Ini namanya Pointer. Di server MMORPG beneran, kita harus pake pointer biar data pemain yang di-update di satu tempat, otomatis berubah di semua tempat. Kalo kaga pake ini, nanti si Juki jalannya di layar dia doang, di layar orang lain dia masih diem bae!
Sesi 12. Sistem Tabrakan (Collision Detection)
sebelumnya kan si Juki udeh bisa geser-geser posisi pake koordinat $X$ dan $Y$. Tapi ada yang kurang sreg: si Juki masih kayak hantu, bisa nembus apa aja! Nah, di sesi 12 ini, kita bakal bikin Sistem Tabrakan (Collision Detection). Biar si Juki kagak bisa nembus tembok atau nyungsep ke dalem empang!
"Collision detection is the process of detecting when two or more objects collide. It is a fundamental component of most games, used to keep objects from passing through each other." > (Deteksi tabrakan itu proses buat tau kapan dua objek atau lebih saling tabrakan. Ini bagian penting di hampir semua game, gunanya biar objek kagak saling tembus satu sama lain).
Maksudnya apa Cing? Ya kalau si Juki kagak kita kasih aturan "tabrakan", dia bisa jalan di atas air, tembus gunung, atau malah keluar dari peta game-nya. Berantakan dah urusannya!
π§± 1. Konsep Peta (Tilemap)
Biar gampang, kita bayangin dunia game kita itu kayak lantai ubin di rumah Encing. Ada ubin yang boleh diinjek (lantai), ada yang kagak boleh (tembok/lemari).
Kita bakal bikin "Peta" sederhana pake angka:
0: Artinya Lantai (Boleh lewat).
1: Artinya Tembok (Kagak boleh lewat).
π» 2. Mari Ngoding: Bikin Aturan "Dilarang Lewat!"
Ayo buka Visual Studio-nya lagi. Kita bakal bikin Class Peta dan ngerombak dikit cara si Juki jalan.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
// --- 1. CLASS PETA (Dunia Tempat Juki Jalan) ---
class Peta {
public:
// Peta 5x5 sederhana: 0 = Jalan, 1 = Tembok
int dataPeta[5][5] = {
{0, 0, 1, 0, 0},
{0, 1, 1, 0, 1},
{0, 0, 0, 0, 0},
{1, 1, 0, 1, 0},
{0, 0, 0, 1, 0}
};
// Fungsi buat ngecek: Boleh lewat kagak nih?
bool cekBisaLewat(int x, int y) {
// Cek dulu biar kaga keluar dari batas ubin (0-4)
if (x < 0 || x > 4 || y < 0 || y > 4) {
return false;
}
// Kalo ubinnya angka 0, berarti boleh lewat
return (dataPeta[y][x] == 0);
}
};
// --- 2. CLASS KARAKTER (Si Juki) ---
class Karakter {
public:
string nama;
int x, y;
Karakter(string n, int startX, int startY) : nama(n), x(startX), y(startY) {}
// Fungsi jalan yang sekarang udeh pinter!
void cobaJalan(int deltaX, int deltaY, Peta &dunia) {
int targetX = x + deltaX;
int targetY = y + deltaY;
// Si Juki nanya dulu sama dunianya: "Boleh lewat kagak, Beh?"
if (dunia.cekBisaLewat(targetX, targetY)) {
x = targetX;
y = targetY;
cout << "[LOG] " << nama << " sukses geser ke (" << x << "," << y << ")" << endl;
} else {
cout << "[!] " << nama << " GAGAL JALAN! Depannya ada tembok atau jurang, Cing!" << endl;
}
}
};
int main() {
Peta tanahAbang; // Kita bikin petanya
Karakter juki("Si Juki", 0, 0); // Juki mulai di (0,0)
cout << "--- Petualangan Juki Dimulai ---" << endl;
// 1. Juki coba jalan ke kanan (X+1) -> ke (1,0)
juki.cobaJalan(1, 0, tanahAbang);
// 2. Juki coba jalan ke kanan lagi -> ke (2,0).
// Kalo liat dataPeta[0][2], isinya itu 1 (Tembok). Kudu gagal!
juki.cobaJalan(1, 0, tanahAbang);
// 3. Juki coba jalan ke bawah (Y+1) -> ke (1,1).
// dataPeta[1][1] isinya 1. Kudu gagal juga!
juki.cobaJalan(0, 1, tanahAbang);
return 0;
}
π 3. Bedah Mesin (Danta-in Dulu, Beh!)
dataPeta[y][x]: Perhatiin deh, di C++ (dan banyak bahasa lain), kalau kita akses array dua dimensi, urutannya biasanya Baris ($Y$) dulu baru Kolom ($X$). Jangan sampe kebalik ya Cing, nanti si Juki jalannya malah kayang!targetX & targetY: Ini penting. Kita kaga langsung ngubah posisi si Juki. Kita "bayangin" dulu posisi tujuannya. Kalau tujuannya aman, baru deh kita beneran pindahin koordinatnya. Ibaratnya: "Liat-liat dulu sebelum melangkah".Peta &dunia: Kita kirim referensi petanya ke fungsi jalan si Juki, biar si Juki tau aturan main di tanah tempat dia berpijak.
Sesi 13. Musuh yang "Idup" (Sistem Monster & AI Sederhana)
sebelumnya, si Juki udeh pinter, kaga bakal nyungsep nabrak tembok. Tapi ya masa dunia MMORPG isinya cuma si Juki doang sama tembok? Sepi bener kayak kuburan! Nah, di sesi 13 ini, kita bakal bikin Musuh yang "Idup" (Sistem Monster & AI Sederhana). Kita bakal belajar gimana caranya bikin karakter yang bisa jalan-jalan sendiri tanpa perlu kita gerakin!
πΉ 1. Konsep "Anak Cucu" (Inheritance)
Babeh sama Encing kudu tau, monster itu kan sebenernya mirip sama pemain: punya nama, punya HP, punya posisi X dan Y. Masa kita kudu ngetik ulang semua kodenya? Capek, Beh!
Di C++ ada jurus namanya Inheritance (Pewarisan). Kita bikin Class Monster yang "numpang" atau mewarisi sifat dari Class Karakter.
π» 2. Mari Ngoding: Bikin Monster "Kecoa Raksasa"
Ayo buka lagi Visual Studio-nya. Kita bakal bikin monster yang bisa gerak acak (Random Move).
#include <iostream>
#include <string>
#include <vector>
#include <cstdlib> // Buat jurus angka acak (random)
#include <ctime> // Buat patokan waktu angka acak
using namespace std;
// --- 1. CLASS UTAMA (Udeh kita bahas di sesi sebelumnya) ---
class Entitas {
public:
string nama;
int x, y;
Entitas(string n, int startX, int startY) : nama(n), x(startX), y(startY) {}
};
// --- 2. CLASS MONSTER (Anak cucu dari Entitas) ---
// Tanda ( : public Entitas ) artinya Monster dapet semua sifat Entitas
class Monster : public Entitas {
public:
Monster(string n, int startX, int startY) : Entitas(n, startX, startY) {
cout << "[SISTEM] Monster " << nama << " muncul di (" << x << "," << y << ")!" << endl;
}
// Jurus AI Sederhana: Jalan Ngasal
void updateAI() {
// Kita acak angkanya: 0=Diem, 1=Kanan, 2=Kiri, 3=Atas, 4=Bawah
int arah = rand() % 5;
switch(arah) {
case 1: x++; cout << nama << " geser ke Kanan." << endl; break;
case 2: x--; cout << nama << " geser ke Kiri." << endl; break;
case 3: y++; cout << nama << " geser ke Atas." << endl; break;
case 4: y--; cout << nama << " geser ke Bawah." << endl; break;
default: cout << nama << " lagi bengong..." << endl; break;
}
}
};
int main() {
// Biar angka acaknya beda-beda tiap kali dijalanin
srand(time(0));
// Kita bikin musuh bebuyutan Juki
Monster musuh("Kecoa Raksasa", 2, 2);
cout << "\n--- Simulasi Waktu Berjalan ---" << endl;
// Ceritanya waktu game jalan 3 detik (3 kali update)
for(int i = 1; i <= 3; i++) {
cout << "\nDetik ke-" << i << ":" << endl;
musuh.updateAI();
cout << "Posisi " << musuh.nama << " sekarang: (" << musuh.x << "," << musuh.y << ")" << endl;
}
return 0;
}
π 3. Bedah Mesin (Danta-in Dulu, Beh!)
class Monster : public Entitas:Ini bagian paling penting. Kita kaga perlu nulis string nama, int x, dsb lagi di dalem Monster. Cukup panggil "Bapak"-nya (Entitas), otomatis si Monster punya semua variabel itu. Irit tenaga, kan?rand() % 5:Ini cara C++ buat ngacak angka dari 0 sampe 4.updateAI():Di MMORPG beneran, fungsi ini dijalanin terus-menerus sama server. Jadi monster keliatan "idup" karena posisinya berubah-ubah terus secara otomatis tanpa nunggu dipencet tombol sama pemain.
Sesi 14. Sistem Aggro & Deteksi Jarak
Di sesi 14 ini, kita bakal bikin si monster makin pinter dan galak. Kita bakal bahas Sistem Aggro & Deteksi Jarak. Intinya, kalau si Juki meleng dikit dan masuk ke wilayah si monster, dia bakal langsung dikejar!
π 1. Rumus Jarak (Biar Kagak Asal Kejar)
Babeh sama Encing pasti inget pelajaran sekolah dulu soal Pythagoras. Buat tau jarak antara si Juki $(x_1, y_1)$ dan si Monster $(x_2, y_2)$, kita pake rumus jarak:
$$d = \sqrt{(x_2 - x_1)^2 + (y_2 - y_1)^2}$$Tapi di C++, fungsi akar (sqrt) itu lumayan berat buat mesin kalau dijalankan ribuan kali di server. Makanya, trik suhu programmer biasanya pake Jarak Kuadrat aja buat dibandingin sama Radius Aggro-nya. Lebih enteng, Cing!
π» 2. Mari Ngoding: Si Monster Mulai Beraksi!
Ayo buka lagi Visual Studio-nya. Kita tambahin logika "Pendeteksi Jarak" di dalem Class Monster.
#include <iostream>
#include <string>
#include <cmath> // Buat fungsi math
using namespace std;
// Class Karakter si Juki (Target)
class Karakter {
public:
string nama;
int x, y;
Karakter(string n, int startX, int startY) : nama(n), x(startX), y(startY) {}
};
// Class Monster yang udeh makin pinter
class Monster {
public:
string nama;
int x, y;
int aggroRadius; // Jarak pandang si monster
Monster(string n, int startX, int startY, int radius)
: nama(n), x(startX), y(startY), aggroRadius(radius) {}
// FUNGSI UTAMA: Ngecek si Juki deket apa kaga
void updateAI(Karakter &target) {
// 1. Itung selisih jarak X dan Y
int diffX = target.x - x;
int diffY = target.y - y;
// 2. Itung jarak pake rumus (tanpa akar biar enteng)
float jarak = sqrt((diffX * diffX) + (diffY * diffY));
if (jarak <= aggroRadius) {
cout << "[!] " << nama << ": \"Liat si " << target.nama << "! KEJAR!!\"" << endl;
// Logika ngejar: gerak 1 langkah ngedeketin posisi target
if (target.x > x) x++; else if (target.x < x) x--;
if (target.y > y) y++; else if (target.y < y) y--;
cout << "[LOG] " << nama << " sekarang di (" << x << "," << y << ")" << endl;
} else {
cout << "[...] " << nama << " lagi ngeronda santai, Juki masih jauh." << endl;
}
}
};
int main() {
Karakter juki("Si Juki", 10, 10); // Juki ada di kejauhan
Monster kecoa("Kecoa Raksasa", 0, 0, 5); // Monster punya jarak pandang 5 ubin
cout << "--- Simulasi Kejar-kejaran ---" << endl;
// Kejadian 1: Juki masih jauh
kecoa.updateAI(juki);
// Kejadian 2: Juki kaga sengaja deketin monster
cout << "\n[SISTEM] Juki jalan ngedeketin wilayah monster..." << endl;
juki.x = 3;
juki.y = 3;
// Monster harusnya sadar dan mulai ngejar
kecoa.updateAI(juki);
kecoa.updateAI(juki); // Ngejar lagi
return 0;
}
π 3. Bedah Mesin (Danta-in Dulu, Beh!)
aggroRadius:Ini ibarat "lingkaran kewaspadaan" si monster. Kalau Encing pasang angka 5, berarti kalau Juki ada di jarak 5 ubin atau kurang, si monster bakal langsung auto-galak.Logika Ngejar:Perhatiin bagianif (target.x > x) x++;. Ini cara paling simpel buat bikin NPC ngejar. Dia bakal bandingin posisinya sama posisi si Juki. Kalau si Juki ada di sebelah kanan dia ($target.x > x$), dia bakal geser ke kanan juga biar makin deket.Karakter &target:Masih inget kan tanda &? Kita pake ini biar si monster ngeliat data Juki yang asli, bukan fotokopiannya.
Sesi 15. State Machine (Mesin Perubahan Kelakuan)
Di sesi 15 ini, kita bakal bikin si monster punya "Akal" yang lebih rapi pake sistem State Machine (Mesin Perubahan Kelakuan). Jadi dia tau kapan kudu jalan-jalan santai, kapan kudu ngejar, dan kapan kudu Otomatis Gebuk!
π€ 1. Konsep State Machine (FSM)
Biar kagak pusing, kita bayangin si monster punya 3 kondisi (State):
- PATROL (Ngeronda): Jalan ngasal, Juki kaga keliatan.
- CHASE (Ngejar): Juki keliatan, monster lari nyamperin.
- ATTACK (Gebuk): Juki udeh nempel, monster langsung nyerang.
π» 2. Mari Ngoding: Monster yang Punya "Akal"
Ayo buka lagi Visual Studio-nya. Kita pake fitur C++ namanya enum buat bikin daftar setelan mood si monster.
#include <iostream>
#include <string>
#include <cmath>
using namespace std;
// Daftar setelan mood monster
enum State { PATROL, CHASE, ATTACK };
class Karakter {
public:
string nama;
int x, y, hp;
Karakter(string n, int startX, int startY) : nama(n), x(startX), y(startY), hp(100) {}
};
class Monster {
public:
string nama;
int x, y, attackPower;
State statusSekarang; // Ini "Tombol Setelan" nya
Monster(string n, int startX, int startY) : nama(n), x(startX), y(startY) {
attackPower = 10;
statusSekarang = PATROL; // Awalnya ngeronda dulu
cout << "[SISTEM] " << nama << " lagi ngeronda di (" << x << "," << y << ")" << endl;
}
void updateAI(Karakter &target) {
// Itung jarak dulu kayak sebelumnya
float jarak = sqrt(pow(target.x - x, 2) + pow(target.y - y, 2));
// --- LOGIKA PERUBAHAN MOOD (STATE TRANSITION) ---
if (jarak <= 1.0f) {
statusSekarang = ATTACK;
} else if (jarak <= 5.0f) {
statusSekarang = CHASE;
} else {
statusSekarang = PATROL;
}
// --- EKSEKUSI SESUAI MOOD ---
switch (statusSekarang) {
case PATROL:
cout << "[...] " << nama << " lagi ngeronda santai..." << endl;
break;
case CHASE:
cout << "[!] " << nama << " lagi NGEJAR " << target.nama << "!" << endl;
if (target.x > x) x++; else if (target.x < x) x--;
if (target.y > y) y++; else if (target.y < y) y--;
break;
case ATTACK:
cout << "[*] CEPREEEET! " << nama << " ngegebuk " << target.nama << "!" << endl;
target.hp -= attackPower;
cout << "[HP " << target.nama << " sisa: " << target.hp << "]" << endl;
break;
}
}
};
int main() {
Karakter juki("Si Juki", 10, 10);
Monster kecoa("Kecoa Raksasa", 0, 0);
cout << "--- Simulasi Kehidupan Monster ---" << endl;
// Kejadian 1: Juki deketin monster
cout << "\n[SISTEM] Juki masuk ke jarak pandang monster..." << endl;
juki.x = 4; juki.y = 4;
kecoa.updateAI(juki); // Monster bakal CHASE
// Kejadian 2: Juki udeh nempel (jarak deket banget)
cout << "\n[SISTEM] Juki kepeleset pas di depan monster..." << endl;
juki.x = 1; juki.y = 1;
kecoa.updateAI(juki); // Monster bakal ATTACK
return 0;
}
π 3. Bedah Mesin (Danta-in Dulu, Beh!)
enum State:Ini cara paling rapi buat bikin daftar pilihan di C++. Daripada pake angka 0, 1, 2 yang bikin pusing, mending pake nama kayak PATROL atau ATTACK.switch (statusSekarang):Ini ibarat "Rel Kereta". C++ bakal ngecek mood si monster sekarang apa, terus dia langsung loncat ke kode yang pas. Jauh lebih kenceng dan rapi daripada pake if-else yang numpuk-numpuk.- Transition Logic: Perhatiin cara kita ngubah mood. Urutannya kudu bener! Kita cek dulu jarak yang paling deket (ATTACK), baru jarak menengah (CHASE), sisanya baru PATROL. Kalau kebalik, nanti monsternya keder.
Sesi 16. Sistem Hadiah (Loot System & Drop Rate)
Di sesi 16 ini, kita bakal bahas Sistem Hadiah (Loot System & Drop Rate). Kita bakal bikin gimana caranya pas monster udeh wassalam (mati), dia ninggalin barang berharga atau koin buat dipungut.
π° 1. Konsep Drop Rate (Gacha Sederhana)
Di MMORPG, kaga semua monster drop barang bagus setiap saat. Ada yang namanya Drop Rate (Persentase Kemunculan).
- Barang Sampah (Common): Munculnya sering (misal 70% ).
- Barang Bagus (Rare): Munculnya jarang-jarang (misal 5%).
Kita bakal pake fungsi rand() % 100 buat nentuin keberuntungan si Juki.
π» 2. Mari Ngoding: Pas Mati Dapet Rejeki!
Ayo buka lagi Visual Studio-nya. Kita tambahin sistem Loot di dalem Class Monster.
#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>
#include <ctime>
using namespace std;
// 1. Struktur Item (Barangnya)
struct Item {
string namaItem;
int harga;
};
class Karakter {
public:
string nama;
int hp;
vector<Item> tas; // Inget sebelumnya
Karakter(string n) : nama(n), hp(100) {}
void pungutBarang(Item barangBaru) {
tas.push_back(barangBaru);
cout << "[+] " << nama << " dapet barang: " << barangBaru.namaItem << "!" << endl;
}
};
class Monster {
public:
string nama;
int hp;
Monster(string n, int h) : nama(n), hp(h) {}
// FUNGSI UTAMA: Ngeluarin hadiah pas mati
void cekKematian(Karakter &pembunuh) {
if (hp <= 0) {
cout << "\n[!] " << nama << " MATI! Nyawanya udeh wassalam." << endl;
// Logika Drop Rate (0 - 99)
int keberuntungan = rand() % 100;
if (keberuntungan < 10) { // Cuma 10% kemungkinan
Item pedangSakti = {"Golok Naga Cengkareng", 5000};
cout << ">> [RARE DROP] Monster ngejatuhin barang langka!" << endl;
pembunuh.pungutBarang(pedangSakti);
}
else if (keberuntungan < 50) { // 40% kemungkinan
Item ramuan = {"Jamu Kuat (Potion)", 100};
cout << ">> [COMMON DROP] Ada barang jatoh nih." << endl;
pembunuh.pungutBarang(ramuan);
}
else {
cout << ">> [ZONK] Monsternya bokek, kaga bawa ape-ape." << endl;
}
}
}
};
int main() {
srand(time(0)); // Biar acaknya danta
Karakter juki("Si Juki");
Monster kecoa("Kecoa Raksasa", 20);
cout << "--- Juki Gebuk Monster Sampe Mati ---" << endl;
// Ceritanya Juki ngeluarin jurus terakhir
kecoa.hp -= 25;
// Server ngecek kondisi monster
kecoa.cekKematian(juki);
return 0;
}
π 3. Bedah Mesin (Danta-in Dulu, Beh!)
struct Item:Ini cara bikin tipe data baru yang ringkas. Cocok buat barang-barang yang punya banyak sifat (nama, harga, berat, dsb).rand() % 100:Ini mesin judi kita, Cing. Dia bakal ngeluarin angka acak. Kalau dapet angka di bawah 10, si Juki dapet barang dewa. Kalau dapet angka gede, ya dapetnya jamu doang atau malah kaga dapet ape-ape.pembunuh.pungutBarang(...):Perhatiin cara monsternya ngasih barang. Monsternya manggul fungsi milik si Juki buat masukin barang ke dalem vector tasnya. Rapi kan?
Sesi 17. Sistem Equipment (Pake Senjata)
Di sesi 17 ini, kita bakal ngerakit Sistem Equipment (Pake Senjata). Kita bakal bikin gimana caranya pas senjata itu dipake, serangan si Juki otomatis makin bureh (berbobot)!
⚔️ 1. Konsep Stat Tambahan (Bonus Stats)
Di MMORPG, kekuatan karakter itu biasanya gabungan dari dua hal:
- Status Dasar (Base Stats): Kekuatan asli dari lahir/leveling.
- Status Tambahan (Bonus Stats): Kekuatan dari baju zirah atau senjata.
Rumus total serangan si Juki nantinya jadi begini:
$$\text{Total Attack} = \text{Base Attack} + \text{Bonus Senjata}$$π» 2. Mari Ngoding: Pasang Goloknya, Juk!
Ayo buka lagi Visual Studio-nya. Kita bakal bikin struct khusus buat Senjata dan nambahin "Slot" di dalem Class Karakter.
#include <iostream>
#include <string>
using namespace std;
// 1. Cetakan buat Senjata
struct Senjata {
string nama;
int bonusSerang;
};
class Karakter {
private:
string nama;
int baseAttack;
// Kita bikin "Slot" buat naro senjata (pake pointer biar fleksibel)
Senjata* senjataDipake;
public:
Karakter(string n, int atk) : nama(n), baseAttack(atk) {
senjataDipake = nullptr; // Awalnya kaga bawa ape-ape (tangan kosong)
}
// Fungsi buat masang senjata
void pakeSenjata(Senjata* s) {
senjataDipake = s;
cout << "[SISTEM] " << nama << " sekarang megang: " << s->nama << endl;
}
// Fungsi buat tau total kekuatan sekarang
int itungTotalAttack() {
if (senjataDipake == nullptr) {
return baseAttack; // Kalo tangan kosong, ya cuma base attack
}
return baseAttack + senjataDipake->bonusSerang;
}
void statusTempur() {
cout << "--- Status Tempur " << nama << " ---" << endl;
cout << "Base Attack : " << baseAttack << endl;
if (senjataDipake != nullptr) {
cout << "Senjata : " << senjataDipake->nama << " (+" << senjataDipake->bonusSerang << ")" << endl;
}
cout << "Total Attack : " << itungTotalAttack() << endl;
cout << "-----------------------" << endl;
}
};
int main() {
// 1. Juki lahir dengan bakat silat (Attack 50)
Karakter juki("Si Juki", 50);
juki.statusTempur();
// 2. Ceritanya Juki nemu golok sakti
Senjata golokNaga = {"Golok Naga Cengkareng", 150};
cout << "\n[Aksi] Juki nyabut golok dari sarungnya..." << endl;
// 3. Juki pake goloknya
juki.pakeSenjata(&golokNaga);
// 4. Cek status lagi, kudunya makin gahar!
juki.statusTempur();
return 0;
}
π 3. Bedah Mesin (Danta-in Dulu, Beh!)
Senjata* senjataDipake:Perhatiin ada tanda bintang (*). Ini namanya Pointer. Kita kagak mau "ncopy" senjata ke dalem karakter, kita cuma mau si Juki "nunjuk" ke senjata yang ada. Jadi kalau senjatanya rusak atau di-upgrade, datanya sinkron!nullptr:Ini tandanya "Kosong". Sangat penting buat ngecek apakah si Juki lagi megang senjata apa kaga. Kalau kagak dicek pake if (senjataDipake == nullptr), program bisa crash pas si Juki lagi tangan kosong.- Logika Penjumlahan: Perhatiin fungsi itungTotalAttack. Ini yang bikin server kita adil. Dia bakal selalu ngejumlahin kekuatan asli sama bonus dari barang yang dipake.
Sesi 18. Networking C++ (Socket & IP)
Di sesi 18 ini, kita bakal mulai ngerakit Jantungnya MMORPG, yaitu Networking (Koneksi Antar Komputer). Kita bakal belajar gimana caranya komputer Encing bisa ngomong sama komputer Babeh lewat kabel internet!
Assalamualaikum Enyak, Babeh, Encing sekalian! Waduh, makin kerasa nih hawa-hawa suhu kodingannya. Kopinya masih ada kan? Kalo udeh dingin, mending angetin dulu biar otak kita kagak hang pas masuk ke materi yang rada "berat" tapi paling ditunggu-tunggu.
sebelumnya, si Juki udeh makin gahar pake "Golok Naga Cengkareng". Tapi ya masa si Juki cuma tebas-tebasan angin doang sendirian? Nah, di sesi 18 ini, kita bakal mulai ngerakit Jantungnya MMORPG, yaitu Networking (Koneksi Antar Komputer). Kita bakal belajar gimana caranya komputer Encing bisa ngomong sama komputer Babeh lewat kabel internet!
"Network programming is the art of getting computers to communicate with each other. It is the foundation of the modern internet and every multiplayer game you’ve ever played." > (Pemrograman jaringan itu seni bikin komputer saling ngobrol. Ini pondasi internet modern dan semua game multiplayer yang pernah Encing maenin).
Maksudnya apa Beh? Ya tanpa Networking, si Juki cuma bakal jadi pendekar kesepian. Biar bisa jadi MMORPG, kita butuh "Jembatan" biar ribuan pemain bisa kumpul di satu dunia yang sama.
π 1. Konsep Telepon (Socket & IP)
Biar gampang nyangkut di kepala, bayangin Networking itu kayak Main Telepon-teleponan.
- IP Address: Ini nomor telepon rumah Encing. Biar orang tau mau nelpon ke mana.
- Port: Ini nomor ekstensi (kamar). Misalnya, kamar 80 buat buka web, kamar 443 buat belanja online, nah kita bakal pake kamar khusus (misal 8888) buat game kita.
- Socket: Ini kabel teleponnya. Pintu buat ngirim dan nerima suara (data).
Di C++, kita bakal pake yang namanya Socket Programming.
π» 2. Mari Ngoding: Bikin Server "Halo Dunia!"
Ayo buka Visual Studio-nya lagi. Berhubung Networking di C++ murni itu rada panjang (kalo di Windows pake Winsock, di Linux pake sys/socket), saya kasih liat Logika Dasarnya dulu biar kagak pusing duluan.
#include <iostream>
#include <string>
// Catatan: Di realita, kita butuh library kayak <winsock2.h> buat Windows
// Tapi buat belajar, kita pahamin alur "Jabat Tangan" (Handshake) nya dulu:
using namespace std;
class ServerGame {
public:
void mulaiServer(int port) {
cout << "[SISTEM] Membuka pintu (Socket) di Port: " << port << "..." << endl;
cout << "[SISTEM] Server lagi nungguin ada pemain nelpon (Listen)..." << endl;
}
void terimaKoneksi(string namaPemain) {
cout << "[SERVER] >> Assalamualaikum! " << namaPemain << " udeh nyambung!" << endl;
}
void kirimPesanKePemain(string pesan) {
cout << "[SERVER] >> Ngirim paket data: \"" << pesan << "\"" << endl;
}
};
int main() {
// 1. Nyalain Mesin Server
ServerGame serverKita;
serverKita.mulaiServer(8888);
cout << "\n--- Simulasi Pemain Masuk ---\n" << endl;
// 2. Ceritanya ada pemain (Client) dari komputer lain nyambung
string pemainBaru = "Si Juki";
serverKita.terimaKoneksi(pemainBaru);
// 3. Server nyapa si Juki lewat kabel jaringan
serverKita.kirimPesanKePemain("Selamat dateng di Dunia Persilatan, Juk!");
return 0;
}
π 3. Bedah Mesin (Danta-in Dulu, Beh!)
- Listen (Nungguin): Server itu pasif, Beh. Dia cuma diem nungguin ada yang "ngetok pintu" (koneksi). Begitu ada pemain masuk, server baru bereaksi.
- TCP vs UDP:
- TCP: Kayak kirim surat tercatat. Pasti nyampe, urutannya bener, tapi rada lambat. Cocok buat urusan Inventory atau Chat.
- UDP: Kayak lempar batu. Cepet banget, tapi bisa aja batunya ilang di jalan. Cocok buat urusan jalan-jalan (posisi X, Y) biar kaga lag.
- Buffer: Ini "kantong" sementara buat nampung data yang dateng lewat kabel sebelum dibaca sama si Juki.
Sesi 19 Multi-threading (Ngerjain Banyak Tugas Barengan)
Di sesi 19 ini, kita bakal belajar Multi-threading (Ngerjain Banyak Tugas Barengan). Biar server kita bisa kerja "keroyokan" kayak panitia kawinan!
π’ 1. Analogi Tukang Sate Khas Betawi
Biar gampang nyangkut di kepala, bayangin Tukang Sate:
- Single-threaded (Satu Orang): Si abangnya yang kipas sate, dia juga yang ngiris lontong, dia juga yang nerima duit, dia juga yang nyuci piring. Kalau yang beli 50 orang? Antreannya bisa sampe depan gang, Beh!
- Multi-threaded (Banyak Orang): Ada abang yang khusus kipas sate, ada Enyak yang ngiris lontong, ada Encing yang jagain kasir. Semuanya kerja barengan di detik yang sama. Sate mateng, pesenan kelar, semua seneng!
Di C++, tiap "pekerja" itu namanya Thread.
π» 2. Mari Ngoding: Bikin Server "Keroyokan"
Ayo buka lagi Visual Studio-nya. Kita bakal pake kotak perkakas sakti namanya <thread>.
#include <iostream>
#include <string>
#include <thread> // KOTAK PERKAKAS BARU KITA!
#include <chrono> // Buat simulasi waktu (istirahat/delay)
using namespace std;
// 1. Tugas pertama: Ngurusin si Juki
void urusPemainJuki() {
for (int i = 1; i <= 3; i++) {
cout << "[THREAD 1] Lagi ngitung posisi Juki ke-" << i << "..." << endl;
// Simulasi kerjaan berat (istirahat 1 detik)
this_thread::sleep_for(chrono::seconds(1));
}
cout << "[THREAD 1] Kelar ngurusin Juki!" << endl;
}
// 2. Tugas kedua: Ngurusin si Pitung (Jalan barengan!)
void urusPemainPitung() {
for (int i = 1; i <= 3; i++) {
cout << "[THREAD 2] Lagi cek tas (Inventory) Pitung ke-" << i << "..." << endl;
// Simulasi kerjaan berat (istirahat 1 detik)
this_thread::sleep_for(chrono::seconds(1));
}
cout << "[THREAD 2] Kelar ngurusin Pitung!" << endl;
}
int main() {
cout << "--- SERVER MMORPG DINYALAIN (MODE KEROYOKAN) ---\n" << endl;
// Kita bikin dua "pekerja" (Thread) buat ngerjain tugas masing-masing
thread pekerja1(urusPemainJuki);
thread pekerja2(urusPemainPitung);
// .join() itu tandanya si Main Server nungguin mereka berdua kelar
pekerja1.join();
pekerja2.join();
cout << "\n[SERVER] Semua urusan kelar barengan. Kagak pake antre!" << endl;
return 0;
}
π 3. Bedah Mesin (Danta-in Dulu, Beh!)
std::thread: Ini cara kita manggil "pegawai" baru. Kita kasih tau dia tugasnya apa (misalnya fungsiurusPemainJuki), terus dia bakal langsung lari ngerjain tugas itu tanpa nungguin program utama.- Parallel Execution: Pas Encing jalanin kode di atas, tulisannya bakal muncul selang-seling! "Thread 1 lagi ngitung..." terus bawahnya langsung "Thread 2 lagi cek...". Itu tandanya mereka beneran jalan barengan di waktu yang sama.
.join(): Ini penting banget. Ini perintah biar program utama (Main) jangan mati dulu sebelum anak buahnya (Thread) kelar ngerjain tugas. Kalau kagak di-join, nanti servernya udeh bubar tapi pegawainya masih pada kerja, bisa crash mesinnya, Beh!
Keamanan Data (Mutex & Race Condition)
sebelumnya, kita udeh bikin server yang pegawainya banyak (Thread). Tapi ada masalah baru, Beh. Gimana kalau pegawai-pegawai itu rebutan satu barang yang sama di waktu yang barengan? Wah, bisa berantakan urusannya!
π° 1. Analogy: "Duit Kas RT"
Biar gampang nyangkut di kepala, bayangin Duit Kas RT:
- Ada satu kotak isi duit (Data/Variabel).
- Encing, Babeh, ama Enyak (Thread) semuanya pengen nambahin duit ke kotak itu di detik yang barengan.
- Pas Encing lagi ngitung duit mau dimasukin, eh Babeh udeh masukin duluan. Pas Encing naruh duitnya, hitungan Babeh malah ketutup atau ilang.
- Hasil akhirnya? Duitnya kurang dari yang semestinya! Ini yang namanya Race Condition.
Solusinya? Kita butuh Gembok (Mutex). Cuma orang yang pegang kunci yang boleh buka kotak duit. Yang lain kudu antre nungguin gemboknya dibuka lagi.
π» 2. Mari Ngoding: Ngegembok Saldo Pemain
Ayo buka Visual Studio-nya buat terakhir kali di seri ini. Kita bakal pake <mutex> biar data kita aman dari "cheater" sistem.
#include <iostream>
#include <thread>
#include <vector>
#include <mutex> // KOTAK PERKAKAS BARU: SI GEMBOK!
using namespace std;
int saldoServer = 0; // Data yang bakal direbutin
mutex gembokSaldo; // Kunci buat ngamanin saldo
void tambahSaldo(string namaPegawai) {
for (int i = 0; i < 1000; i++) {
// --- PROSES NGEGEMBOK (LOCK) ---
// Pake lock_guard biar otomatis kebuka pas kelar (aman bin danta)
lock_guard<mutex> penjaga(gembokSaldo);
saldoServer++; // Cuma satu thread yang bisa ngerjain ini di satu waktu
}
cout << "[SISTEM] " << namaPegawai << " kelar nambahin 1000 koin." << endl;
}
int main() {
cout << "--- SIMULASI TRANSAKSI SERVER MMORPG ---\n" << endl;
// Kita bikin dua pegawai yang nambahin koin barengan
thread pegawai1(tambahSaldo, "Encing");
thread pegawai2(tambahSaldo, "Babeh");
pegawai1.join();
pegawai2.join();
cout << "\n[HASIL AKHIR] Total Saldo di Server: " << saldoServer << " Koin." << endl;
cout << "Kalo kodenya bener, hasilnya kudu PAS 2000!" << endl;
return 0;
}
π 3. Bedah Mesin (Danta-in Dulu, Beh!)
std::mutex: Ini benda ghaibnya. Dia bertugas jadi satpam yang megang kunci pintu data.std::lock_guard: Ini cara paling aman di C++ modern. Begitu baris ini dibaca, pintu langsung dikunci. Pas fungsinya kelar atau keluar dari kurung kurawal, pintu otomatis kebuka sendiri. Jadi Encing kagak bakal lupa buka gembok (kalo lupa buka gembok, server bisa hang selamanya/Deadlock).- Kenapa Penting? Di MMORPG, kalau si Juki beli pedang seharga 100 koin, server kudu ngunci saldo si Juki dulu sebelum motong. Kalau kaga, bisa aja si Juki beli dua barang barengan tapi duitnya cuma kepotong satu kali. Rugi bandar, Beh!
π― Kesimpulan Akhir Seri Dasar MMORPG
Alhamdulillah! Enyak, Babeh, sama Encing sekarang udeh tamat seri dasarnya. Dari cuma bisa nulis "Hello World", sekarang udeh paham gimana caranya ngerakit:
- Karakter & Inventory (Data & Vector).
- Sistem Level & Combat (Logika Game).
- Simpen & Muat Data (Persistence File).
- Dunia & Pergerakan (Koordinat & Collision).
- Monster & AI (State Machine & Aggro).
- Server & Networking (Socket & Threads).
- Keamanan Data (Mutex & Race Condition).
Ini udeh jadi modal awal yang sangat kuat buat jadi Game Developer atau Backend Developer C++ yang handal.
Nah, biasanya abis belajar begini, pasti di palenya Encing atau Babeh masih ada yang ngeganjel. Makanya, saya buatin FAQ (Frequently Asked Questions) alias kumpulan pertanyaan yang paling sering ditanyain sama pendekar koding pemula.
π§ FAQ: Tanya Jawab Seputar MMORPG & C++
1. "Cing, kenapa sih kita kudu pake C++? Kagak ada yang lebih gampang apa, kayak Python atau JS?"
Jawab: Bisa banget pake bahasa lain, tapi C++ itu ibarat mesin Formula 1. MMORPG itu sistem yang super sibuk, tiap detik ada ribuan data (posisi pemain, nyawa, chat, serangan) yang kudu diitung barengan. C++ ngasih kita kendali penuh buat ngatur memori dan prosesor. Kalau pake bahasa yang terlalu "santai", nanti pas pemainnya rame, servernya bisa lag parah atau malah meleduk (overheat).
2. "Server kita ini kuat nampung berapa orang, Beh?"
Jawab: Kalau cuma pake satu komputer rumahan biasa, mungkin 50-100 orang masih kuat. Tapi MMORPG beneran itu pake sistem Cluster. Artinya, dunianya dipecah-pecah. Misalnya, server Jakarta ngurusin daerah Monas, server Bekasi ngurusin daerah Mall. Dengan ilmu Threading (sesi 19) dan Networking (sesi 18) yang kita pelajarin, kita bisa nambahin banyak server biar bisa nampung jutaan orang.
3. "Gimana caranya biar pemain kaga bisa nge-hack darah (HP) jadi tak terhingga?"
Jawab: Inget sesi 3 soal Encapsulation dan sesi 5 soal Server Logic. Aturan utamanya: "Jangan Pernah Percaya sama Client (Aplikasi di HP/PC Pemain)". Semua hitungan (HP ngurang berapa, level berapa) kudu kejadian di Server. Aplikasi pemain cuma nampilin gambar doang. Kalau ada pemain iseng ngerubah HP di HP-nya dia, server bakal bilang: "Kaga bisa, Tong! Di catetan saya, lu udeh mati!".
4. "Bisa kaga kalau databasenya diganti pake yang gratisan dulu selain Oracle?"
Jawab: Bisa banget, Cing! Logika yang saya ajarin di sesi 7 dan 8 itu standar umum. Encing bisa ganti Oracle pake MySQL atau PostgreSQL yang gratis. Yang penting Encing paham cara "nyimpen" dan "manggil" datanya. Tapi emang kalau udeh kelas kakap dan pengen data yang super aman, Oracle itu emang rajanya.
5. "Berapa lama sih waktu yang dibutuhin buat bikin game MMORPG sampe jadi beneran?"
Jawab: Jujur ya Beh, kalau dikerjain sendirian, bisa bertahun-tahun. Makanya di industri game, biasanya ada tim: ada yang khusus ngurusin Server (C++), ada yang ngurusin Grafik (Unreal Engine), ada yang bikin cerita. Tapi dengan paham 20 sesi ini, Encing udeh punya modal buat jadi Lead Programmer atau Server Architect.
6. "Abis tamat buat game ini, saya kudu belajar apa lagi?"
Jawab: Jalannya masih panjang, tapi makin seru! Saran saya:
- Belajar Library Socket (Winsock atau Boost.Asio): Biar bisa bikin koneksi internet beneran.
- Belajar Game Engine (Unreal Engine): Buat nampilin grafik 3D yang cakep pake C++.
- Belajar Algoritma Pathfinding (A*): Biar monster (sesi 13) jalannya makin pinter nyari jalan di labirin.
"Ilmu itu bukan yang dihafal, tapi yang memberi manfaat."
Alhamdulillah, seneng banget bisa nemenin Enyak, Babeh, sama Encing ngerakit mimpi bikin game MMORPG sendiri. Jangan kapok buat ngulik ya! Kalau ada error merah-merah di layar, jangan emosi, itu tandanya komputernya lagi ngajak diskusi.