Pengenalan Game Design

Kondisional

Mari kita mulai bab ini dengan membahas sebuah contoh animasi sederhan yang mirip dengan yang telah kita pelajari sebelumnya.

Contoh 4-1 Animasi Sederhana

int posisiX=0;

void setup () {
    size (800, 400);

    //untuk menggambar lingkaran tanpa outline
    noStroke();
}

void draw() {
    background (200);
    fill (0, 120, 0);

    //mengatur posisi lingkaran
    posisiX++;

    //menggambar lingkaran
    ellipse (posisiX, height/2, 40, 40);

}

Yang terjadi di sini adalah kita mempunyai sebuah lingkaran yang bergerak dari kiri ke kanan. Namun, setelah lingkaran keluar layar, ia tak kembali lagi, karena posisinya sudah lebih besar dari panjang layar. Lalu, bagaimanakah jika kita ingin agar lingkaran ini kembali ke kiri setelah ia mencapai pojok kanan layar?

Untuk menjawab pertanyaan itu, maka kita bisa menggunakan kondisional. Kondisional adalah bagian dari sebuah program yang mengatur jalannya program sesuai dengan kondisi tertentu. Seringkali ini berarti program memiliki beberapa kemungkinan yang bisa terjadi, dan pemilihan kemungkinannya akan diatur oleh kondisional ini.

Sebagai contoh, program mungkin melakukan opsi A, B dan C. Namun, opsi mana yang dipilih akan bergantung pada tombol keyboard mana yang ditekan oleh pengguna.

Penulisan kondisional dalam Processing ini bisa dilakukan dengan 2 cara, yakni dengan notasi if-else dan notasi switch. Mari kita tengok notasi pertama.

Kondisional if-else

Kondisional ini bisa dituliskan sebagai berikut:

if (kondisi) {
    pernyataan1;
}

else {
    pernyataan2;
}

Arti dari penulisan tersebut adalah, jika kondisi terpenuhi, maka jalankan pernyataan1. Jika tidak, maka jalankan pernyataan2. Sederhana bukan? Konsep ini kemudian bisa kita aplikasikan untuk menjawab pertanyaan di awal bab tadi. Mari kita pecah alur program agar lebih mudah dianalisa:

  • Status awal: lingkaran bergerak dari kiri ke kanan
  • Kondisi: apakah posisi lingkaran sudah melebihi layar?
  • Jika iya: lingkaran bergerak dari kanan ke kiri
  • Jika tidak: lingkaran tetap bergerak dari kiri ke kanan

Sudah sepakat? Dengan alur seperti ini, mustinya jika lingkaran dalam program sudah melebih panjang layar, maka ia akan kembali ke kiri. Perlu kita ingat bahwa pengaturan posisi bola ini dilakukan oleh variabel posisiX, maka variabel inilah yang perlu diatur perilakunya di dalam kondisional agar gerak lingkaran menjadi seperti yang kita inginkan.

Dengan demikian, maka program kita akan menjadi:

int posisiX=0;
int arah=1;

void setup () {
  size (800, 400);

  //untuk menggambar lingkaran tanpa outline
  noStroke();
}

void draw() {
  background (200);
  fill (0, 120, 0);

  //mengatur posisi lingkaran
  posisiX+=arah;

  //mengatur arah gerak lingkaran
  if (posisiX > width) {
    arah*=-1;
  }

  //menggambar lingkaran
  ellipse (posisiX, height/2, 20, 20);
}

Ketika program dijalankan maka akan kita lihat, bola kita bisa kembali ke kiri setelah mencapai ujung kanan layar. Bagaimana bisa? Ini karena kita telah mengatur perilaku variabel posisiX yang menentukan di manakah lingkaran harus digambar.

Sebelumnya, kita menuliskan posisiX bisa berubah seiring dengan berjalannya loop di dalam draw() melalui pernyataan

posisiX++;

Kali ini, kita atur agar posisiX ini tidak hanya bisa bertambah, namun juga dengan mengikuti arah tertentu, hingga akhirnya ia bisa ke kiri atau ke kanan. Ini dilakukan dengan pernyataan berikut:

posisiX+=arah;

Variabel arah, sesuai namanya akan menentukan arah gerak bola. Besar variabel inilah yang akan kita atur dalam kondisional.

Sesuai dengan koordinat dalam Processing, sumbu x akan bertambah ke kanan layar dan berkurang ke kiri layar. Aturan ini kemudian kita implementasikan saat menentukan besarnya variabel arah dengan dua kemungkinan:

  1. Ketika arah positif, posisiX akan bertambah, yang menyebabkan bola bergerak ke kanan
  2. Ketika arah negatif, posisiX akan berkurang, yang menyebabkan bola bergerak ke kiri

Perubahan arah gerak ini kita atur akan terjadi saat bola sudah menyentuh ujung kanan layar. Dengan demikian, pernyataan yang mengatur variabel arah adalah:

if (posisiX > width) {
  arah*=-1;
}

Semua nampak bagus saat ini. Namun, ada satu kekurangan dari program tadi. Ketika bola kembali ke sisi kiri layar, atau saat posisiX sudah mencapai 0 kembali, maka bola tetap bergerak ke kiri dan akhirnya hilang. Untuk memperbaiki kesalahan ini, maka kita bisa mengubah pernyataan kondisional sebelumnya menjadi:

if (posisiX > width || posisiX < 0) {
  arah*=-1;
}

Pernyataan ini berarti arah akan berubah apabila posisiX lebih besar dari panjang layar ATAU posisiX lebih kecil dari titik 0 yang merupakan sisi paling kiri layar. Dua garis horizontal tadi disebut operator boolean or yang akan melakukan operasi logika OR. Lebih lanjut mengenai operator boolean ini akan dibahas pada bagian selanjutnya. Namun sebelum itu, mari kita simak program yang telah kita buat dan perbaiki tadi:

Contoh 4-2 Animasi Bola Memantul Horizontal

int posisiX=0;
int arah=1;

void setup () {
  size (800, 400);

  //untuk menggambar lingkaran tanpa outline
  noStroke();
}

void draw() {
  background (200);
  fill (0, 120, 0);

  //mengatur posisi lingkaran
  posisiX+=arah;

  //mengatur arah gerak lingkaran
  if (posisiX > width || posisiX < 0) {
    arah*=-1;
  }

  //menggambar lingkaran
  ellipse (posisiX, height/2, 20, 20);
}

Operator Logika

Pada bab sebelumnya, kita telah berkenalan dengan operator matematika. Operator logika sengaja penulis simpan untuk bab ini, karena di sinilah ia akan terasa faedahnya.

Operator logika, akan mengecek kebenaran sebuah pernyataan dan akan menghasilkan salah satu dari 2 kemungkinan, benar (TRUE) atau salah (FALSE). Lebih lanjut lagi, seringkali salah dianggap sebagi 0 (zero) dan benar sebagai non-zero. Hasil dari operasi inilah yang kemudian bisa kita gunakan dalam mmembuat pernyataan kondisional, karena kembali lagi, sebuah pernyataan dalam blok kondisional bisa berjalan atau tidak, akan bergantung dari kebenaran pernyataan kondisi yang dievaluasi.

Dengan menggunakan operator logika, maka kita bisa mengecek kondisi lebih dari satu variabel. Hasil operasi ini kemudian akan menentukan pernyataan apa yang harus dijalankan program.

Ada 3 operator logika yang tersedia di Processing:

  1. Operator AND (&&) Operator ini akan menghasilkan true, atau non-zero apabila kedua variabel yang menjadi operand bernilai true atau non-zero
  2. Operator OR (||) Operator ini akan menghasilkan true, atau non-zero apabila salah satu variabel yang menjadi operand bernilai true atau non-zero
  3. Operator NOT (!) Operator ini akan menghasilkan lawan dari nilai boolean variabel tersebut.

Tabel berikut ini menunjukkan operator-operator logika tersebut, serta hasil operasinya untuk 2 variabel yang berbeda. Nilai true ditulis 1, serta false ditulis 0.

a b a && b (b AND b) a && b (b AND b) ~a (NOT a) ~b (NOT b) 1 1 1 1 0 0 1 0 0 1 0 1 0 1 0 1 1 0 0 0 0 0 1 1

Operator Perbandingan Selain operator logika, untuk mengecek kebenaran sebuah pernyataan, kita juga bisa menggunakan operator perbandingan. Sesuai namanya, operator ini akan membandingkan besar dua buah angka dan hasilnya adalah true atau false.

Operator perbandingan yang tersedia adalah:

  1. Operator sama dengan (==) Operator ini memeriksa apakah 2 operand-nya sama besarnya.
  2. Operator tidak sama dengan (!=) Operator ini memeriksa apakah 2 operand-nya berbeda
  3. Operator lebih besar (>) Operator ini memeriksa apakah operand yang di kiri lebih besar daripada operand yang di kanan
  4. Operator lebih besar sama dengan (>=) Operator ini memeriksa apakah operand yang di kiri lebih besar atau sama besar dengan operand yang di kanan
  5. Operator lebih kecil (<) Operator ini memeriksa apakah operand yang di kiri lebih kecil daripada operand yang di kanan
  6. Operator lebih kecil sama dengan (<=) Operator ini memeriksa apakah operand yang di kiri lebih kecil atau sama besar dengan operand yang di kanan

Tabel berikut memberikan contoh hasil keenam operator ini dengan operandnya berupa variabel x=90 dan y=60. Sama seperti tabel sebelumnya, hasil 1 menunjukkan true dan 0 menunjukkan false

a b a == b a != b a > b a >= b a < b a <= b 90 60 0 1 1 1 0 0

Baik operator logika maupun operator perbandingan, keduanya sudah digunakan pada contoh 3-2 di atas. Diharapkan setelah perkenalan formal dengan keduanya ini, pembaca bisa membayangkan operasi apa saja yang bisa dilakukan dalam membuat sebuah perintah kondisional dalam program.

Struktur if-else if-else

Struktur if-else yang telah kita pelajari sebelumnya sangatlah cocok untuk membuat program yang mengandung struktur atau perintah kondisional dengan 2 kemungkinan hasil, ya dan tidak, atau true dan false, atau benar dan salah. Dengan menggunakan struktur ini maka kita telah bisa membuat sebuah animasi sederhana berupa bola yang memantul dari kiri ke kanan layar secara berulang-ulang.

Ketika membuat program tadi, mungkin muncul pertanyaan, “bagaimana kalau seandainya program kita membutuhkan struktur kondisional dengan lebih dari dua kemungkinan kondisi?” Mungkin saja kita ingin apabila bola yang memantul tadi warnanya berubah tergantung dari posisinya di layar. Untuk menjawab pertanyaan itu, maka kita bisa mengembangkan struktur if-else yang telah kita pelajari, menjadi struktur if-else if-else.

Struktur if-else if-else ini memungkinkan kita untuk membuat lebih dari 2 skenario kondisional, berapapun yang dibutuhkan oleh program. Penulisan strukturnya kira-kira seperti ini:

if (kondisi 1) {
    pernyataan1;
}
else if (kondisi 2) {
    pernyataan2;
}
else if (kondisi 3) {
    pernyataan3;
}
.
.
.
else if (kondisi N) {
    pernyataanN;
}
else {
    pernyataanAkhir;
}

Bisa dilihat di situ bahwa ada banyak sekali kemungkinan skenario kondisi yang bisa kita aplikasikan dengan menggunakan struktur ini. Tentu saja ini berbeda dengan struktur if-else yang hanya memungkinkan kita menggunakan 2 jenis kondisi yang berlawanan. Perlu dicatat juga bahwa penggunaan else di akhir bisa kita lewatkan, jadi kita cukup menulis if-else if saja.

Sekarang, setelah berkenalan dengan struktur ini, mari kita aplikasikan pengetahuan baru ini untuk membuat animasi yang kita bicarakan sebelumnya. Di animasi ini, saya ingin warna lingkaran berubah setiap seperempat panjang layar, hingga nantinya warnanya berubah seiring dengan perjalanannya. Dengan demikian, program pada contoh 4-2 sebelumnya, bisa kita kembangkan lebih lanjut menjadi

Contoh 4-3 Mengganti Warna Lingkaran Bergerak

int posisiX=0;
int arah=1;

void setup () {
  size (800, 400);

  //untuk menggambar lingkaran tanpa outline
  noStroke();
}

void draw() {
  background (200);
  //mengatur warna lingkaran
  if (posisiX < width/4) {
    fill (120, 0, 0);
  }
  else if (posisiX > width/4 && posisiX < width/2) {
    fill (0, 120, 0);
  }
  else if (posisiX > width/2 && posisiX < 3*width/4) {
    fill (0, 0, 120);
  }
  else { //tidak memenuhi kondisi 1,2 dan 3
    fill (0, 120, 120);
  }

  //mengatur posisi lingkaran
  posisiX+=arah;

  //mengatur arah gerak lingkaran
  if (posisiX > width || posisiX < 0) {
    arah*=-1;
  }

  //menggambar lingkaran
  ellipse (posisiX, height/2, 20, 20);
}

Pada contoh tadi, kita menggunakan struktur if-else if-else untuk menentukan perubahan warna lingkaran, tergantung pada posisinya. Ada 4 skenario yang mungkin terjadi yang kita aplikasikan pada contoh tersebut:

  1. Bila koordinat x lingkaran pada seperempat pertama panjang layar, maka lingkaran berwarna merah
  2. Bila koordinat x lingkaran berada di antara seperempat pertama dan setengah panjang layar, maka lingkaran berwarna hijau
  3. Bila koordinat x lingkaran berada di antara setengah dan tiga perempat panjang layar, maka lingkaran berwarna biru
  4. Bila koordinat x lingkaran berada lebih dari tiga perempat panjang layar, maka lingkaran berwarna biru muda

Keempat skenario itu kemudian diaplikasikan pada baris-baris source code berikut:

if (posisiX < width/4) {
    fill (120, 0, 0);
  }
else if (posisiX > width/4 && posisiX < width/2) {
    fill (0, 120, 0);
}
else if (posisiX > width/2 && posisiX < 3*width/4) {
    fill (0, 0, 120);
}
else { //tidak memenuhi kondisi 1,2 dan 3
    fill (0, 120, 120);
}

Kita bisa lihat bahwa skenario kita akan bergantung pada besar variabel posisiX, yang mengandung koordinat x dari lingkaran. Besar variabel ini kemudian akan dibandingkan dengan panjang layar program yang kita miliki. Apabila perbandingan ini benar, atau hasilnya true, maka program akan mengeksekusi pernyataan yang sesuai dengan kondisi perbandingan yang bernilai benar. Dengan demikian, maka warna lingkaran bisa berganti-ganti sesuai dengan posisinya pada layar.

Tentu saja, kondisi terakhir bisa kita tuliskan pula dalam bentuk else if, sehingga aplikasinya menjadi:

if (posisiX < width/4) {
    fill (120, 0, 0);
  }
else if (posisiX > width/4 && posisiX < width/2) {
    fill (0, 120, 0);
}
else if (posisiX > width/2 && posisiX < 3*width/4) {
    fill (0, 0, 120);
}
else if (posisiX > 3*width/4) { //tidak memenuhi kondisi 1,2 dan 3
    fill (0, 120, 120);
}

Struktur Switch

Selain menggunakan struktur if-else if-else, ada satu struktur lagi yang memungkinkan kita menggunakan kondisional dengan beberapa skenario. Struktur ini disebut struktur switch, yang bisa diartikan dengan mengganti (switch) kondisi program ke skenario tertentu.

Sama seperti struktur if, kondisi dalam struktur ini juga diatur dengan mengacu pada variabel tertentu. Artinya, pernyataan mana yang dijalankan akan bergantung dari nilai variabel yang mengontrol pernyataan switch ini. Namun, berbeda dengan if, nilai yang menentukan perubahan kondisi pada switch, haruslah 1 nilai unik. Dengan kata lain, tidak boleh mengontrol switch dengan menggunakan nilai yang memiliki rentang tertentu, hanya boleh 1 nilai saja.

Struktur switch ini bisa dituliskan seperti berikut:

switch (variabel_pengontrol) {
    case nilai_variabel_pengontrol_1:
        pernyataan1;
        break;
    case nilai_variabel_pengontrol_2:
        pernyataan2;
        break;
    case nilai_variabel_pengontrol_3:
        pernyataan3;
        break;
    .
    .
    .
    case nilai_variabel_pengontrol_N:
        pernyataanN;
        break;
}

Untuk menunjukkan penggunaan switch, mari kita buat program mirip dengan contoh 3-3. Hanya saja, kali ini, warna lingkaran akan berganti setiap koordinat X lingkaran berada pada kelipatan 100, atau pada saat titik x bernilai 100, 200, 300, dst. Dengan demikian, syarat untuk menggunakan switch sudah terpenuhi, karena kondisi akan berganti hanya pada 1 angka tertentu saja.

Berikut ini contoh programnya:

Contoh 4-4 Mengganti Warna Lingkaran dengan Switch

int posisiX=0;
int arah=1;

void setup () {
  size (800, 400);

  //untuk menggambar lingkaran tanpa outline
  noStroke();
}

void draw() {
  background (200);
  //menggambar garis batas sebagai referensi
  for (int i=0; i < 8; i++) {
    stroke (0);
    line (i*100, 0, i*100, height);
  }
  //mengatur warna lingkaran
  noStroke();
  switch (posisiX) {
  case 0:
    fill (0, 255/4, 100);
    break;
  case 100:
    fill (0, 255/3, 100);
    break;
  case 200:
    fill (0, 255/2, 100);
    break;
  case 300:
    fill (0, 255/1, 100);
    break;
  case 400:
    fill (0, 255/1, 200);
    break;
  case 500:
    fill (0, 255/2, 200);
    break;
  case 600:
    fill (0, 255/3, 200);
    break;
  case 700:
    fill (0, 255/4, 200);
    break;
  }

  //mengatur posisi lingkaran
  posisiX+=arah;

  //mengatur arah gerak lingkaran
  if (posisiX > width || posisiX < 0) {
    arah*=-1;
  }

  //menggambar lingkaran
  ellipse (posisiX, height/2, 20, 20);
}

Perlu diketahui bahwa, tidak diperbolehkan untuk menuliskan case dengan menggunakan operasi dan bukan dengan konstanta. Sehingga sebagai contoh, kasus kedua tidak bisa kita ubah dari

case 100:
    fill (0, 255/3, 100);
    break;

menjadi

case width/8:
    fill (0, 255/3, 100);
    break;

Sequence dan Animasi Interaktif

Penggunaan struktur switch ini menjadi dasar dari penulisan sequence atau urutan kejadian pada animasi atau film pada umumnya. Sebagaimana kita semua ketahui, pada dasarnya, animasi adalah kumpulan dari gambar-gambar yang ditampilkan mengikuti urutan tertentu.

Ada banyak sekali contoh untuk menggambarkan ini. Yang paling dasar adalah flipbook, di mana gambar-gambar diletakkan pada sisi sebuah buku, lalu kemudian masing-masing halaman pada buku ini dibalik secara berurutan sehingga nampak seperti animasi. Semakin cepat membalikkannya maka semakin muluslah animasi yang dilihat oleh mata.

Nah, dengan menggunakan struktur switch ini, maka kita bisa berlatih bagaimana meng-sequence atau mengurutkan kejadian yang terjadi pada animasi kita. Contoh yang kita bahas pada bab ini mungkin cukup intuitif bagi kita, karena kita mengurutkan warna lingkaran sesuai pada posisinya di sumbu x yang mana posisinya terus bertambah seiring waktu.

Untuk membuat program animasi sederhana di mana kita menampilkan gambar-gambar secara berurutan pada waktu tertentu, kita bisa menggunakan besaran dari salah satu variabel bawaan Processing, yakni frameCount. Variabel ini kemudian kita gunakan untuk mengontrol pernyataan switch, sehingga kita bisa menentukan apa yang akan terjadi pada saat frame ke-sekian. Contohnya kira-kira seperti berikut:

Contoh 4-5 Sequence Animasi Sederhana

int posisiX=0;
int arah=1;
int posisiY=height/2;

void setup () {
  size (800, 400);

  //untuk menggambar lingkaran tanpa outline
  noStroke();
}

void draw() {
  background (200);
  //mengatur warna lingkaran
  switch (frameCount) {
    case 0:
      fill (0, 255/4, 100);
      posisiY = height/8;
      break;
    case 120:
      fill (0, 255/3, 100);
      posisiY = height/2;
      break;
    case 240:
      fill (0, 255/2, 100);
      posisiY = height/3;
      break;
    case 360:
      fill (0, 255/1, 100);
      posisiY = height/4;
      break;
  }

  //mengatur posisi lingkaran
  posisiX+=arah;

  //mengatur arah gerak lingkaran
  if (posisiX > width || posisiX < 0) {
    arah*=-1;
  }

  //menggambar lingkaran
  ellipse (posisiX, posisiY, 20, 20);
}

Ada sedikit matematika yang terjadi di situ. Secara default, Processing akan menentukan bahwa program akan berjalan dengan laju pertambahan frame sebesar 60 FPS (frame per second). Artinya, dalam 1 detik ada 60 frame yang terus bertambah. Dengan demikian, kita menghitung 1 detik = 60 frame dan selanjutnya perhitungan urutan kejadian kita hitung dalam satuan frame. Sehingga, program tadi menunjukkan bahwa kita mengganti posisi lingkaran pada sumbu Y setiap 120 frame, atau 2 detik sampai frame ke 360 atau 6 detik pertama.

Pada praktiknya, tentu saja kita bisa menggunakan struktur switch ini untuk mengurutkan kejadian-kejadian tertentu berdasarkan parameter tertentu pula, tidak perlu berdasarkan waktu sebagaimana yang pasti kita jumpai pada animasi tradisional non-interaktif. Ini kemudian yang menjadi dasar dari animasi interaktif kita.

Sebagai contoh, kita bisa saja menggunakan switch untuk mengubah warna dan posisi lingkaran pada sumbu Y, bergantung dari tombol keyboard mana yang ditekan seperti pada contoh berikut:

Contoh 4-6 Lingkaran Interaktif

int posisiX=0;
int arah=1;
int posisiY=height/2;

void setup () {
  size (800, 400);

  //untuk menggambar lingkaran tanpa outline
  noStroke();
}

void draw() {
  background (200);
  //mengatur warna dan posisi lingkaran pada sumbu Y
  if (keyPressed) {
    switch (key) {
    case 'a':
      fill (0, 255/4, 100);
      posisiY = height/8;
      break;
    case 's':
      fill (0, 255/3, 100);
      posisiY = height/2;
      break;
    case 'd':
      fill (0, 255/2, 100);
      posisiY = height/3;
      break;
    case 'f':
      fill (0, 255/1, 100);
      posisiY = height/4;
      break;
    }
  }

  //mengatur posisi lingkaran
  posisiX+=arah;

  //mengatur arah gerak lingkaran
  if (posisiX > width || posisiX < 0) {
    arah*=-1;
  }

  //menggambar lingkaran
  ellipse (posisiX, posisiY, 20, 20);
}