Behind the Scene: Simple Animation on C# – Memantul – Ep 01

OK, mulai sekarang gua memutuskan untuk membuat sebuah topik postingan berjudul Behind Scene khusus untuk hal-hal yang berbau teknis. Sehingga ke depannya gua harap seluruh postingan Behind Scene gua bisa membantu siapapun yang nyasar ke sini untuk dapat gambaran sederhana dari sebuah metode-metode sederhana untuk hal-hal fundamental yang sering kita temui sehari-hari. Happy reading guys! : D

Episode: Behind the Scene – 01
Title: Simple Animation on C# – Memantul
Tingkat Kesusahan: 1/5

Konsep

Animasi adalah hal yang paling tidak asing penggunaannya sekarang ini. Kita bisa membuat berbagai macam animasi dari gerakan berjalan kanan kiri atas bawah, menghilang, fade out in, ease, atau bahkan gerakan kompleks pada animasi 3D. Tapi pernahkah terbetik di benak kita, bagaimana cara membuat semua itu? Jawaban gampangnya ya, “Gampang kok, tinggal beli aja program khusus pembuatan animasi, kek Flash, Maya, atau klo mau gratisan, Blender”. Yoi~ Emang seperti itu cara gampangnya. Sebutlah itu sebagai end-user a.k.a pengguna akhir. Di mana ketika akan membuat sebuah film animasi, kita sudah kudu fokus ke berbagai hal lain seperti jalan cerita, karakter, twist, dan semacamnya.

Tapi bukan itu yang gua maksud. Yang gua maksud di sini, bagaimana membuat sang program pembuat animasi itu sendiri. Bagaimana program-program cem Flash, Maya, Blender tadi bisa membuat gerakan atau tampilan super memukau seperti itu. Dan itulah yang akan diperkenalkan di sini.

Mari kita mulai. Pada dasarnya, animasi itu berhubungan erat dengan apa yang disebut dengan gerak. Sesuatu disebut bergerak jika dia berpindah tempat. Seberapa cepat dia bergerak bisa diekspresikan dengan kelajuan, kecepatan, ataupun percepatan. Taruhlah kita memiliki sebuah partikel pada posisi x. Lalu partikel ini bergerak dengan kecepatan konstan sebesar v. Maka jika dia begitu terus selama t, maka kita akan dapati partikel tadi berpindah posisi menjadi x+vt. Tentu saja gerakan seperti ini sangat tidak ideal pada dunia nyata, karena akan susah membuat sebuah benda bergerak tiba-tiba dengan kecepatan konstan. Sedangkan salah satu daya tarik animasi adalah semakin gerakannya mendekati kenyataan, semakin terlihat nyata animasi tadi.

Gerak Pegas Sederhana

Sekarang kita ambil contoh sebuah gerakan dasar sederhana. Taruhlah kita ingin membuat sebuah animasi bola jatuh dari atas ke bawah. Ketika bola menyentuh tanah, bola akan memantul-mantul beberapa saat sampai dia terdiam berhenti memantul. Gerakan seperti ini bisa kita modelkan dengan gerak pegas sederhana. Di mana ada sebuah benda yang digantung di atas pegas yang diberi redaman, kemudian benda ditarik dari kedudukan semula dan dilepaskan setelah ditarik. Maka benda tadi akan memantul-mantul beberapa saat mengikuti jalur pegas sampai terdiam.

spring: thanks to nissansp

spring: thanks to nissansp

Sampai di sini kita tahu setidaknya ada 3 gaya yang bekerja, yaitu: gaya pegas, gaya redaman, dan gaya resultan yang bekerja pada benda tadi.

(F_{peg}, F_{red}, F_{res}) = (-kx, -cv, ma)

Sehingga kita akan dapatkan total ketiga gaya tadi memenuhi persamaan berikut ini

ma = -kx - cv \to m\ddot{x} + c\dot{x} + kx = \ddot{x} + (c/m)\dot{x} + (k/m)x = 0

Selanjutnya persamaan di atas bisa kita ubah menjadi persamaan yang lebih sederhana menjadi sebagai berikut

\ddot{x} + 2 \alpha \dot{x} + \omega_0^2 x = 0

di mana \omega_0 = (k/m)^{1/2} dan \alpha = c \omega_0 /(2(mk)^{1/2}). Pada kasus ini \omega_0 sendiri biasa dikenal sebagai frekuensi natural, di mana pada frekuensi ini sistem biasanya mengalami resonansi. Pada persamaan orde dua di atas, kita bisa perkirakan solusi haruslah merupakan x=e^{st} dengan s merupakan bilangan kompleks. Sehingga persamaan tadi akan memenuhi

e^{st}(s^2 + 2 \alpha s + \omega_0^2) = 0 \to s_{12} = -\alpha \pm \omega_d, \omega_d = (\alpha^2 - \omega_0^2)^{1/2}

Nah sebetulnya dari persamaan orde dua ini, kita memungkinkan mendapat 4 macam variasi solusi utama, yaitu ketika \alpha=0, \omega_0 > 0 atau \alpha > \omega_0 > 0 atau \alpha = \omega_0 > 0 atau 0 < \alpha < \omega_0. Untuk 3 solusi pertama masing-masing memiliki solusi bertipe lossless (osilasi sempurna), redaman besar, dan redaman kritis. Khusus yang terakhir, kita menyebutnya sebagai solusi bertipe redaman kecil.

Apa maksud dari keempat solusi ini? Solusi pertama mengimplikasikan s=\pm j \omega_0 di mana j = (-1)^{1/2}. Artinya, solusi akan membentuk trace berupa sinusoid sempurna tanpa redaman. Solusi kedua dan ketiga, semuanya memiliki karakteristik s > 0 yang berimplikasi trace sinusoid akan teredam cukup sempurna dalam waktu kurang atau sama dengan satu periode gerakan sinusoid. Sedangkan solusi keempat akan menghasilkan solusi perhitungan

x = e^{-\alpha t}(e^{j \omega_d t} + e^{-j \omega_d t}) \to x = e^{-\alpha t}(\cos{\omega_d t} + \sin{\omega_d t})

Dalam hitung-hitungan yang lebih murni, sebetulnya kita perlu menggunakan konstanta tambahan untuk ekspresi yang lebih akurat seperti x = e^{-\alpha t}(A_1 \cos{\omega_d t} + A_2 \sin{\omega_d t}). Tapi karena konsen perhitungan ini hanyalah untuk mendekati gerakan memantul seperti pada pegas, maka kita bisa mengabaikan hal ini. Dan sekali lagi untuk mempermudah perhitungan simulasi gerakan ini, kita bisa abaikan bagian fungsi cosinus sehingga kita bisa modifikasi final fungsi di atas menjadi

modifikasi underdamp

modifikasi underdamp

f(t) = x = e^{-\alpha t}(\sin{\omega_d t} - 1)

di mana fungsi gerakan ini menjadi terbalik gerakannya dari fungsi yang semula. Dan sekarang, kita sudah mendapatkan fungsi gerakan memantul f(t) dalam representasi waktu dalam ruang satu dimensi. Maka langkah selanjutnya adalah mengaplikasikan fungsi ini ke dalam program.

Programming Praktikal

C# dipilih karena tingkat penggunaannya yang relatif mudah dan cepat dibanding bahasa tingkat rendah lainnya. Walau pada kenyataannya performansi bahasa tingkat rendah biasanya jauh melebihi bahasa-bahasa abstrak cem C#. Berhubung ini cuman sebagai pengenalan, mari kita coba aplikasikan gerakan ini pada bahasa pemrograman ini.

Pertama di projek yang kita buat, siapkan dulu gambar yang mau dianimasiin. Saya sih pakai gambar ini. Lucu euy. Ahahahaha…

pinguin: thanks to yellow icon

pinguin: thanks to yellow icon

Masukkin via PictureBox. Ganti nama objectnya. Di sini gua ganti jadi iPingu. Terus ambil tuh gambar di bagian Image via Import di kolom Local Resource.

nyiapin kontainer gambar

nyiapin kontainer gambar

ganti nama

ganti nama

masukkin gambar tadi

masukkin gambar tadi

OK, kalau semua udah asoy, kita tambahin aja tombol yang bakal ngetrigger event biar nih gambar bisa gerak-gerak di space form. Di sini nih tombol gua kasih nama gerak. Oya, biar dramatisasinya keliatan formnya dibikin memanjang vertikal aja.

ngasih tombol

ngasih tombol

ganti nama

ganti nama

Dan voilah, interfacenya kurang lebih dijadiin gini aja biar rada kerasa efek jatuhnya.

final interface

final interface

Sekarang klo interfacenya udah jadi, kita tinggal tanem aja fungsi gerak memantul tadi ke dalam program.


private int getBounce(double t, double length)
{
double alpha = 1.6;
double wd = 5;

double fA = Math.Exp(-alpha * t);
double fB = Math.Sin(wd * t) - 1;

return ((int)(fA * fB * length));
}

Fungsi di atas adalah praktikal untuk f[t] = x = e^{-1.6 t}(\sin{5 t} - 1) dengan implementasi diskrit. Silahkan adjust sendiri nilai alpha dan wd sesuai keinginan. Di sini ada satu tambahan parameter yaitu length. Length diperlukan untuk memperbesar amplitudo pantulan karena rentang pantulan |f(t)|=1. Dalam hal ini, length berkorelasi dengan panjang pixel yang akan dipergunakan sebagai lintasan pantulan. Selanjutnya kita cukup aktifkan trigger pada tombol gerak yaitu ketika saat tombol diklik.

Idenya kurang lebih seperti ini. Posisi gambar iPingu berada pada koordinat kartesian komputer. Artinya sumbu Y yang ke bawah akan bernilai positif, dan sebaliknya sumbu Y yang ke atas akan bernilai negatif. Sebutlah posisi pingu adalah (12, 196). Posisi ini kita jadikan sebagai sumbu O. Ketika tombol gerak ditekan, maka program akan melakukan counter loop diskrit untuk rentang t dari 0 sampai 4. Berhubung diskrit, maka kita perlu step untuk countingnya. Di sini kita bisa pakai \delta t=0.02.

Karena kita hanya fokus pada gerakan jatuh, maka kita hanya perlu mengaplikasikan fungsi ini pada sumbu Y. Secara sederhana kita bisa katakan, posisi pinguin ketika jatuh ini bisa diketahui dengan melihatnya sebagai sebuah gerakan yang lama-lama akan jatuh pada posisi semula, yaitu O. Sehingga, posisi jatuh pinguin bisa kita ekspresikan dengan y_{jatuh}[t] = O_y + f[t].

Secara praktikal, kita bisa buat codenya menjadi kurang lebih seperti ini.


int Ox = iPingu.Location.X;
int Oy = iPingu.Location.Y;

double length = 500;

for (double i = 0; i < 4; i += 0.02)
{
iPingu.Location = new Point(Ox, Oy + getBounce(i, length));
this.Refresh();
}

Terakhir, tinggal compile codenya dan gerakan memantul sederhana pun bisa dinikmati. 😀

Moral

Gerakan cem tadi bisa juga diaplikasiin ke gerakan yang lain, misal, pop up window yang muncul tapi ada efek kelembamannya tertentu. Atau juga buat animasi zoom in out tombol yang ke-over dan semacamnya. Jadi intinya, klo kita coba liat keadaan sekitar kita, fenomena gerak, cahaya, gaya-gaya, dan semacamnya, klo kita modelkan dengan proporsional dan aplikasikan ke dalam sebuah pemrograman sederhana, kita bisa dapatkan gerakan animasi yang mendekati fenomena di dunia nyatanya. Dan nggak berhenti sampai di sini, kita juga bisa mengeksplore gerakan-gerakan yang mungkin tidak terbayang oleh kita sebelumnya, misal melihat lintasan probabilitas sebuah elektron mengelilingi pusatnya, atau prediksi visual pergerakan angin, atau bahkan melihat emulasi gaya-gaya medan magnetik secara real.

Baiklah, sampai di sini dulu. Have a nice day~ 🙂

Source code donlot di sini. Klo binary code di sini.

Advertisements