Bayangkan Anda baru saja membuka kanvas kosong yang siap diisi garis, warna, dan gerakan. Di dunia p5.js, semua keajaiban visual itu hampir selalu dimulai dari dua “pintu utama”: setup() dan draw(). Dua fungsi inilah yang diam-diam mengatur ritme karya Anda-mulai dari menyiapkan ukuran kanvas, hingga mengontrol apa yang muncul di layar setiap detik.
Bagi banyak pemula, setup() dan draw() sering terlihat seperti sekadar “kode wajib” yang harus ada agar sketsa bisa berjalan. Namun, di balik kesederhanaan namanya, keduanya adalah fondasi yang menentukan bagaimana sketsa Anda lahir, bernapas, dan terus bergerak. Tanpa pemahaman yang kuat terhadap dua fungsi ini, animasi tampak acak, interaksi terasa kaku, dan logika program mudah berantakan.
Artikel ini akan mengajak Anda mengenal lebih dekat peran setup() dan draw() dalam p5.js: kapan masing-masing dijalankan, apa yang sebaiknya ditempatkan di dalamnya, dan mengapa pembagian tugas di antara keduanya sangat penting. Dengan memahami fondasi ini, Anda akan lebih leluasa bereksperimen-dari membuat animasi sederhana hingga merancang visual interaktif yang kompleks-dengan struktur yang kokoh dan mudah dikembangkan.
Memahami Peran setup dan draw sebagai Jantung Siklus Program di p5.js
Kalau diibaratkan tubuh, setup() adalah detak pertama yang menyiapkan semuanya, sedangkan draw() adalah detak yang terus berulang dan menjaga “kehidupan” sketsa kamu. Di awal, p5. cuma memanggil setup() satu kali untuk melakukan hal-hal seperti membuat kanvas, mengatur ukuran jendela, atau menyiapkan variabel awal. Setelah itu, barulah draw() dipanggil berulang-ulang, frame demi frame, untuk menggambar ulang tampilan di layar. Dalam siklus ini, kamu bisa membayangkan waktu berjalan dalam potongan singkat (frame), dan di setiap potongan itu kamu punya kesempatan untuk mengubah posisi objek, warna, atau logika interaksi.
setup()cocok untuk inisialisasi, jalankan sekali, beres.draw()berjalan terus seperti loop tanpa henti.- Animasi, gerakan, dan interaksi hidup di dalam
draw(). - Struktur rapi di dua fungsi ini bikin kode lebih teratur dan gampang dikembangkan.
| Bagian | Kapan Jalan | Fokus Utama |
|---|---|---|
setup() |
Sekali di awal | Persiapan & konfigurasi |
draw() |
Berkali-kali per frame | Update & visualisasi |
“`javascript
function setup() {
createCanvas(400, 400); // disiapkan sekali di awal
}
function draw() {
background(220); // digambar ulang tiap frame
ellipse(mouseX, mouseY, 50, 50);
}
“`
Mendesain Struktur Kode yang Rapi dengan Memisahkan Inisialisasi dan Logika Gambar
Bayangkan setup() sebagai ruangan persiapan dan draw() sebagai panggung utama. Di ruangan persiapan, kamu bereskan semua hal yang sifatnya sekali jalan: bikin kanvas, load gambar, set warna dasar, atau bikin objek. Begitu masuk panggung, barulah animasi dan logika visual dijalankan berulang-ulang. Dengan memisahkan dua “dunia” ini, kode jadi lebih gampang diikuti, di-debug, dan dikembangkan. Kamu juga bisa fokus: kalau ada yang salah di tampilan, kamu cek bagian gambar (biasanya di draw()); kalau ada yang salah di pengaturan awal, kamu telusuri setup().
- Inisialisasi di awal: ukuran kanvas, variabel global, objek, font, gambar.
- Logika gambar berulang: gerak objek, animasi, perubahan warna, interaksi mouse/keyboard.
- Lebih mudah di-scale: saat proyek makin besar, pemisahan ini mencegah kode jadi “spaghetti”.
| Bagian | Fokus Utama | Waktu Eksekusi |
|---|---|---|
setup() |
Pengaturan awal & pembuatan objek | Sekali di awal |
draw() |
Animasi, update posisi, render ulang | Berkali-kali per frame |
“`javascript
let x, speed;
function setup() {
createCanvas(400, 200); // inisialisasi kanvas
x = 0; // set posisi awal
speed = 2; // set kecepatan awal
}
function draw() {
background(240); // logika gambar berulang
ellipse(x, height / 2, 40, 40);
x += speed;
if (x > width || x < 0) { speed *= -1; // logika pantulan } } ```
Mengoptimalkan Kinerja Animasi lewat Penggunaan draw yang Efisien dan Terukur
Kalau proyek mulai terasa “berat”, biasanya masalahnya ada di cara kita menggambar ulang frame di dalam draw(). Alih-alih menaruh semua logika di satu tempat, coba pecah jadi beberapa fungsi kecil yang spesifik: satu buat update posisi, satu buat menggambar, satu buat hitung logika game. Dengan begitu, kamu bisa lebih mudah mengontrol bagian mana yang butuh dijalankan setiap frame, dan mana yang bisa diperjarang. Misalnya, elemen UI statis tidak perlu digambar ulang secara penuh kalau tidak ada perubahan besar. Kamu juga bisa menerapkan praktik kecil tapi berdampak, seperti menghindari pembuatan objek baru di setiap frame, serta memanfaatkan variabel global yang sudah dihitung di setup() untuk mengurangi kerja ulang yang tidak perlu.
- Kurangi perhitungan berat di dalam loop animasi
- Gunakan kondisi untuk menggambar hanya saat ada perubahan
- Pisahkan logika update dan render ke dalam fungsi terstruktur
- Manfaatkan frameRate() untuk menyeimbangkan kelancaran dan beban CPU
| Pola | Dampak ke Kinerja |
|---|---|
| Hitung ulang data kompleks di setiap frame | Boros CPU, animasi terasa patah |
| Simpan hasil perhitungan di variabel | Frame lebih stabil dan halus |
| Gambar semua elemen setiap saat | Overdraw, terutama di kanvas besar |
| Hanya gambar area yang berubah | Performa lebih ringan dan responsif |
Selain itu, jangan ragu memanfaatkan teknik “pengukuran” sederhana. Kamu bisa menyisipkan penghitungan waktu eksekusi di sekitar blok kode yang terasa berat untuk tahu bagian mana yang bikin lag. Dengan pendekatan ini, kamu tidak menebak-nebak, tapi benar-benar punya data kecil untuk jadi acuan. Kalau perlu, buat versi debug mode yang menampilkan info seperti jumlah objek yang digambar, nilai frameRate(), atau status animasi di pojok kanvas. Dari situ, kamu bisa makin berani melakukan optimasi berulang: menghapus efek visual yang tak terlalu penting, menyederhanakan bentuk, atau mengubah kecepatan update objek tertentu supaya keseluruhan pengalaman tetap terasa halus dan enak dilihat.
Menerapkan Pola Praktik Terbaik setup dan draw untuk Proyek Interaktif Berskala Kecil hingga Besar
Mulai dari sketsa kecil sampai instalasi interaktif di galeri, kunci utamanya adalah mengatur alur logika sejak awal. Untuk proyek yang lebih serius, jangan letakkan semua logika di draw(); pisahkan antara inisialisasi, update, dan render. Biasanya, hal-hal yang jarang berubah (seperti ukuran kanvas, loading gambar, pembuatan objek awal) cukup ditaruh di setup(), sementara perhitungan frame-per-frame dan interaksi pengguna jalan di draw(). Biar makin rapi, biasakan bikin fungsi kecil yang punya tugas jelas, lalu panggil dari dalam draw() daripada menjejalkan semua hal jadi satu blok besar.
- Gunakan struktur modular (fungsi, class, atau file terpisah) untuk skala menengah-besar.
- Jaga frame rate dengan menghindari operasi berat berulang di
draw()(misalnya load file, hitung ulang data statis). - Kelompokkan state (variabel global) ke dalam objek agar mudah dikelola saat proyek membesar.
- Desain siklus hidup: apa yang terjadi saat mulai, saat loop berjalan, dan saat reset.
| Skala Proyek | Fokus setup() | Fokus draw() |
|---|---|---|
| Kecil | Buat kanvas, variabel simpel | Animasi dasar, sedikit interaksi |
| Menengah | Load aset, buat objek & layout | Update objek, kontrol input |
| Besar | Inisialisasi scene, state, dan sistem | Manajemen banyak elemen & performa |
Untuk menjaga performa di proyek yang makin kompleks, pikirkan kapan sesuatu benar-benar perlu dipanggil setiap frame, dan kapan cukup sekali saja. Contohnya, hitung jalur partikel atau pola kompleks satu kali di setup(), lalu di draw() hanya dipakai ulang dan dianimasikan. Kalau perlu, pakai flag sederhana seperti isInitialized atau needsUpdate untuk mengontrol kapan sebuah proses dijalankan. Di proyek besar, pola seperti ini bisa sangat mengurangi “lag” tanpa harus mengorbankan visual.
- Kurangi redraw penuh kalau efek yang diinginkan lebih ke “jejak” atau layering visual.
- Simulasikan langkah demi langkah (step-by-step) ketimbang menghitung ulang seluruh dunia tiap frame.
- Gunakan variabel waktu (misalnya
deltaTime) untuk animasi yang lebih konsisten di berbagai perangkat. - Logging seperlunya di dalam
draw(), lalu matikan saat rilis untuk menghindari spam dan penurunan performa.
Closing Remarks
Pada akhirnya, memahami setup() dan draw() bukan sekadar menghafal “fungsi wajib” di p5.js, tetapi belajar cara berpikir dalam dua fase: satu kali persiapan, lalu pembaruan terus-menerus. Begitu pola ini tertanam di kepala, tiba-tiba banyak hal lain terasa lebih mudah: animasi, interaksi, bahkan eksperimen visual yang sebelumnya tampak rumit.
Dari satu kanvas yang lahir di setup() hingga ribuan frame yang menari di draw(), p5.js memberi kita ruang untuk bereksperimen tanpa takut “merusak” apa pun-cukup ubah kode, simpan, dan lihat apa yang terjadi. Di titik ini, fondasi sudah kamu pegang; selebihnya adalah soal bermain, mencoba hal-hal aneh, dan membiarkan rasa penasaran memandu baris-baris kode berikutnya.
Jadi, setelah ini, cobalah hapus satu baris, tambahkan bentuk baru, ubah warna, atau buat gerakan kecil pada objek di kanvas. Biarkan setup() dan draw() menjadi panggung, dan imajinasimu yang mengarahkan pertunjukan. Dari fondasi sederhana inilah, dunia visual p5.js mulai terbuka lebar.

