Membuat game penebang pohon dengan phaser part5

Hai semua,

Masih dengan tulisan yang hampir sama, yaitu meneruskan pembuatan game penebang pohon. Untuk tutorial kali ini adalah membuat score dan mengatur timer di ingamenya. Untuk part sebelumnya kalian bisa download di link ini

catatan

ini adalah tutorial dengan text untuk tutorial pembuatan game lumberjack / penebang pohon dengan menggunakan phaser framework. Jika mau liat videonya kalian bisa ke link youtube ini

Oh iya sebagai informasi, antara versi tulisan dan video mungkin tidak serupa, tapi memiliki tujuan sama, dan hasil akhir yang sama.

koding

Okeh langsung aja, seperti judul awalnya.. pertama kita akan menambahkan code untuk score, dan nampilin text dari scorenya.

menambahkan score, dan menampilkanya

cek code global dan buat variable baru dengan dengan nama score yang nantinya akan digunakan untuk menyimpan score yang didapat

1
2
3
var poolArrayBatangPohonTidakTerpakai = [];
var score = 0; //varibale ini yang ditambahkan
const DATA_RANTING_KOSONG = 0;

Setelah itu kita buat tambahkan gameobject text yang berfungsi untuk menampilkan score yang akan diperoleh. Letakan sebelum code input.keyboard

1
2
3
4
var textDisplay = this.add
.text(240, 40, score, { fontSize: 50, color: "#000", align: "center" })
.setOrigin(0.5);
textDisplay.setDepth(1);

Pada kode diatas, line 4 saya menambakan setDepth untuk mengatur posisi dari layering / zIndex yang befungsi untuk memastikan text tersebut selalu berada diatas atau digambar terakhir sehingga tidak tertutup dengan gambar lain. Sebagai informasi Phaser juga memiliki layer sistem, yang bisa di letakan oleh banyak object. Kalian bisa mencari tahu lebih banyak soal layering di https://photonstorm.github.io/phaser3-docs/Phaser.GameObjects.Layer.html

selanjutnya saya sedikit mengubah fungsi cekTumbukan dengan mengembalikan nilai boolean

1
2
3
4
5
6
7
8
9
10
this.cekTumbukan = function (posisiPlayer) {
var tumbukan = false; //membuat variable boolean
var batangPohon = arrayBatangPohon[0];
var posisiBatangPohon = batangPohon.data.get("ranting");
if (posisiPlayer == posisiBatangPohon) {
this.permainanBerakhir();
tumbukan = true; //mengubah nilai boolean menjadi true
}
return tumbukan; // mengembalikan nilai bolean
}

habis itu pada fungsi input keyboard kita ubah menjadi seperti ini

1
2
3
4
5
6
7
8
9
10
11
12
13
14
this.input.keyboard.on("keydown-RIGHT", () => {
char.x = 280;
char.flipX = true;
this.cekTumbukan(POSISI_PLAYER_KANAN);
var batangpohon = arrayBatangPohon[0];
this.animasiBatangPohon(batangpohon, "kiri");
arrayBatangPohon.shift();
this.turunkanBatangPohon();
var tumbukan = this.cekTumbukan(POSISI_PLAYER_KANAN); // tambahkan variable cek tumbukan
if (!tumbukan) {
score += 1;
textDisplay.text = score;
}
});

Pada code di atas kurang lebih logikanya adalah jika tidak terjadi tumbukan yang ke2 maka tambahkan score. Oh iya, jangan lupa juga tambahkan pula kode untuk input keyboard-LEFT seperti diatas. Jika sudah semua, kita bisa testing dan hasilnya akan kurang lebih seperti ini.

Tampilan Scoring

membuat indikator waktu, dan menggunakan fungsi update

Karena sudah membuat score, kita lanjutkan untuk membuat indikator waktu, yang berfungsi sebagai tambahan penghalang pemainan. Jadi pemain diharuskan untuk bermain lebih sebelum waktunya habis.

Untuk assets ini, kalian bisa download di kenney asset kembali, ataupun menggunakan UI dengan tampilan sederhana.

Selanjutnya buat variable seperti dibawah

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//tambahkan dibawah score 4 variable ini
var timeCountDown = 10000; //waktu permainan
var indicatortimer = null;
var reduceTimer = 1;
var gameover = false;

const DATA_RANTING_KOSONG = 0;
const POSISI_PLAYER_KIRI = 1;
const POSISI_PLAYER_KANAN = 2;
//varibale baru untuk const ada disini.
const MAX_DISPLAY_WIDTH = 127;
const MAX_TIME_COUNT = 10000;//constanta waktu permainan
const ADDITIONAL_TIMER = 200;
const MIN_REDUCER = 0.3;

Dicode diatas saya langsung menambahkan 4 variable tambahan serta 4 constanta tambahan. Saya akan coba jelaskan dari line ke 2 hingga kebawahnya. Pertama untuk waktu saya 10detik (dalam milisecond menjadi 10000).

Dilanjutkan dengan membuat variable indicatortimer yang saya letakan global, berfungsi untuk tempat meletakan UI dari indikatornya, lalu lanjut ke variable reduceTimer yang akan menjadi skala variable tambahan untuk menambahkan waktu saat pohon di potong, dan variable terkahir adalah gameover, untuk mendeteksi apakah permainan sudah selesai atau belum.

Selain itu ada juga constanta yang sudah sesuai dengan namanya, dimulai dari MAX_DISPLAY_WIDTH yang fungsi untuk mengatur tampilan width dari waktunya (dalam pixel).
MAX_TIME_COUNT adalah maximal waktu dalam hitungan milisecond, atau 10 detik. Jadi waktu permainan tidak akan lebih dari 10 detik.
ADDITIONAL_TIMER adalah waktu yang ditambahkan dalam milisecond, jadi setiap pohon jatuh akan ditambah 200 miliksecond atau 0.2 detik.
MIN_REDUCER adalah minimal skala waktu yang ditambahkan dari ADDITIONAL_TIMER, untuk lebih jelasnya akan di lanjutkan di bawah.

Lanjut kita akan menampilkan 2 gambar indikator waktunya, tapi sebelumnya gambar tersebut harus di load di dalam game.

1
2
3
4
5
6
7
8
9
function preload() {
this.load.image("char", "assets/char-0.png");
this.load.image("bg", "assets/img_bg.png");
this.load.image("log", "assets/basic-log.png");
this.load.image("ranting", "assets/branch-1.png");
///tambahan untuk indikator waktu
this.load.image("ui-indicator", "assets/red_indicator.png");
this.load.image("bg-indicator", "assets/grey_bg.png");
}

setelah gambarnya sudah di load, kita lanjutkan dengan menambahkanya di bawah code score kita

1
2
3
this.add.image(80, 30, "bg-indicator").setScale(0.7, 0.7);
indicatortimer = this.add.image(16, 30, "ui-indicator").setScale(0.5, 0.5).setOrigin(0, 0.5);
indicatortimer.displayWidth = MAX_DISPLAY_WIDTH;

nah karena kebetulan saya download UI assetsnya dari kenney, maka saya merasa terlalu besar, sehingga saya scale dan mengatur tampilanya menggunakan MAX_DISPLAY_WIDTH. Oh iya saya juga set origin atau titik dari gambar UInya tidak ditengah karena akan berpengaruh dalam melakukan scaling ataupun saat mengubah gambarnya.

nah lanjut ke fungsi update yang baru kita gunakan untuk pertama kalinya dalam tutorial code ini. Ubah code updatenya menjadi seperti ini

1
2
3
4
function update(timestep, dt) {
timeCountDown -= dt;
indicatortimer.displayWidth = MAX_DISPLAY_WIDTH * (timeCountDown / MAX_TIME_COUNT);
}

jika sudah kita bisa testing codenya, dan lihat hasilnya. Kurang lebih hasilnya menjadi seperti ini

Tampilan Indikator scaling kearah berlawanan

Bisa di lihat bahwa indikator waktunya turun terus, tetapi jika dilanjukan bisa tambah tapi dengan posisi kearah sebaliknya. Nah disitulah kita akan menggunakan varible dan konstanta yang lain yang sudah dibuat.

Lanjut dengan menggunakan variable gameover terlebih dahulu. Cek kembali pada fungsi permainanBerakhir, kita akan meletakan gameover dan mengubahnya disitu

1
2
3
4
5
this.permainanBerakhir = function () {
console.log("permainan berakhir");
gameover = true; // kita ubah gameover menjadi true
this.input.keyboard.enabled = false;
};

lalu disini fungsi input keyboard RIGHT dan keyboard LEFT, pada line pertama di dalam fungsi arrownya.

1
2
3
4
5
6
7
8
9
this.input.keyboard.on("keydown-RIGHT", () => {
if (gameover) return; //ini ditambahkan disini
//... code selanjutnya tidak saya tulis
}

this.input.keyboard.on("keydown-LEFT", () => {
if (gameover) return;
//... code selanjutnya tidak saya tulis
}

yang kurang lebih fungsi dari code diatas jika gameover, maka tidak perlu melanjukan kode selanjutnya.

Dan yang terakhir adalah mengubah code updatenya menjadi seperti ini

1
2
3
4
5
6
7
8
9
10
function update(timestep, dt) {
if (gameover) return;//sama seperti code sebelumnya
timeCountDown -= dt;
//nah disini kita memastikan timeCountDown tidak lebih kecil dari 0
if (timeCountDown <= 0) {
timeCountDown = 0;
gameover = true;
}
indicatortimer.displayWidth = MAX_DISPLAY_WIDTH * (timeCountDown / MAX_TIME_COUNT);
}

di Line 5 kita mengecheck jika timeCountDown lebih kecil dari 0, maka set kembali menjadi 0, dan mengubah gameover menjadi true.

nah yang terakhir adalah menamahkan waktu saat pohon di tebang, sehingga dari yang seharusnya 10 detik, menjadi ada waktu tambahan yang bisa di mainkan.

okey sekarang cek kembali fungsi input keyboard yang sudah dibuat dan kita akan ubah menjadi seperti ini

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
this.input.keyboard.on("keydown-RIGHT", () => {
if (gameover) return;
char.x = 280;
char.flipX = true;
var tumbukan = this.cekTumbukan(POSISI_PLAYER_KANAN);
if (tumbukan) return;
//tumbangkan pohon ke kiri
var batangpohon = arrayBatangPohon[0];
this.animasiBatangPohon(batangpohon, "kiri");
arrayBatangPohon.shift();
this.turunkanBatangPohon();
//check posisi batang pohon terbawah dan posisi player
tumbukan = this.cekTumbukan(POSISI_PLAYER_KANAN);
if (!tumbukan) {
score += 1;
textDisplay.text = score;
if (reduceTimer < MIN_REDUCER) reduceTimer = MIN_REDUCER;
timeCountDown += ADDITIONAL_TIMER * reduceTimer;
}
});

di line 5 dan 6 yang sebelumnya tidak saya tulis, tetapi disini saya perbaiki karena saat permainan berjalan, ada saat terjadi tumbukan dan gameover, tetapi posisi batang pohon sudah di buang. Oleh sebab itu saya buat variablenya untuk checking.

Dan di line 17 saya dilakukan pengecheckan biasa supaya variable reduceTimer tidak lebih kecil dari MIN_REDUCER. Sehabis itu waktu akan ditambahkan menggunakan perhitungan ADDITIONAL_TIMER * reduceTimer. Maksud dari code itu adalah menambahkan waktu yang seharusnya 0.2 detik menjadi dikalikan kembali dengan skala permainan berjalan. Kalian akan mengerti setelah kita update code di update function. Oh iya jangan lupa ubah code untuk yang keyboard LEFT yah..

Jika sudah kita ubah tambahkan kembali di function update, supaya indikator waktunya tidak lebih dari 10detik, dan tidak melewati batas yang sudah di buat.

1
2
3
4
5
6
7
8
9
10
11
function update(timestep, dt) {
if (gameover) return;
timeCountDown -= dt;
if (timeCountDown <= 0) {
timeCountDown = 0;
gameover = true;
}
reduceTimer -= dt * 0.0001;
if (timeCountDown > MAX_TIME_COUNT) timeCountDown = MAX_TIME_COUNT;
indicatortimer.displayWidth = MAX_DISPLAY_WIDTH * (timeCountDown / MAX_TIME_COUNT);
}

Di line 8 reduceTimer akan terus berkurang, sehingga waktu yang ditambahkan akan berkurang (lihat kembali kode saat menambahkan waktu saat pohon ditebang).

Di line 9 di check apakah waktu lebih dari 10 DETIK / 10000ms (phaser menggunakan ms untuk hitungan waktunya), supaya tidak melebihi batas yang sudah di buat.

Penutup

Wah tutorial yang panjang kembali 😀, dan untuk tutorial kali ini kita mempelajari :

  1. setDepth fungsi untuk mengatur layering, selain itu juga ada layering system yang lain
  2. setOrigin walau tidak saya mention, tetapi kita menggunakanya untuk meletakan posisi tengah pada text, dan memposisikan indikator timernya
  3. fungsi update yang akan selalu di pangil oleh phaser scene secara berkala.

Oh iya jika kalian ingin melihat full code dari tutorial ini silahkan cek atau download filenya disini. Untuk tutorial selanjutnya mungkin kita akan memberikan background music ataupun efek suara.