Dasar Grafis dan Animasi Java

Repost dari artikel saya di PC Mild 02/2011

Java menyediakan library untuk grafis dan multithreading sebagai modal untuk pembuatan animasi. Dengan menggunakan library tersebut, ditambah sedikit interaksi input mouse, Anda bisa membuat game sederhana. Namun artikel kali ini hanya akan membahas dasar-dasar penggunaan grafis, animasi, dan input sederhana saja. Anda bisa mengembangkannya sendiri lebih lanjut.

Hampir semua komponen grafis 2 dimensi Java terletak dalam package java.awt dan javax.swing. Bahkan untuk event dari mouse dan keyboard pun terletak dalam package java.awt.event. Sedangkan untuk threading, terletak pada package java.lang yang otomatis digunakan oleh seluruh program Java.

  1. Sebelum memulai membuat program, Anda harus mendeklarasikan library apa saja yang dipakai dalam program Anda, melalui statement import yang ditulis di luar deklarasi class public. Berikut ini beberapa library yang dibutuhkan dalam dasar pembuatan animasi Java.
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import javax.imageio.ImageIO;
    import javax.swing.JPanel;
  2. Dalam animasi, hal paling penting adalah Container dari animasi tersebut. Container bisa diasumsikan sebagai kanvas tempat animasi tersebut ditampilkan. Ada banyak cara menampilkan gambar dengan Java, antara lain dengan class java.awt.Panel, javax.swing.JPanel, java.awt.Canvas, dan beberapa class lainnya. Namun pada umumnya, konsep pemakaiannya sama saja. Untuk membuat bidang gambar sendiri, Anda cukup membuat class baru turunan dari salah satu class di atas. Simpan dengan nama file PanelClickable.java.
    public class PanelClickable extends JPanel {
    
      public PanelClickable() {
        // mengatur ukuran
        setPreferredSize(new Dimension(400, 300));
      }
    
      @Override
      protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        // tempat penggambaran
      }
    }
    
  3. Karena tujuan utamanya adalah membuat media penggambaran sendiri, maka method paintComponent(Graphics g) harus di-override. Maksudnya adalah agar class tersebut melakukan penggambaran sesuai program yang Anda tulis. Untuk mencoba menampilkan program tersebut, Anda bisa membuat main program sederhana menggunakan JFrame. Jika tidak muncul error dan jendela tampil tepat di tengah layar, maka langkah berikutnya siap dikerjakan.
    import javax.swing.JFrame;
    
    public class Demo {
      public static void main(String[] args) {
        JFrame frame = new JFrame("Demo animasi");
        frame.add(new PanelClickable());
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
      }
    }
    
  4. Siapkan class untuk object yang akan digambar. Contoh sederhananya adalah membuat class Ball yang merepresentasikan sebuah bola. Pada pembuatan sebenarnya, property dan method harus dibuat sedemikian rupa, agar dapat benar-benar merepresentasikan perilaku object yang sesungguhnya.
      class Ball {
        public BufferedImage image;
        public int x, y;
        public int nextX, nextY;
    
        public Ball(int x, int y) {
          this.x = x;
          this.y = y;
          nextX = x;
          nextY = y;
          try {
            image = ImageIO.read(getClass().getResource("ball.png"));
          } catch (IOException ex) {}
        }
    
        public void drawBall(Graphics2D gd) {
          gd.drawImage(image, x, y, null);
        }
    
        public void update() {
          if (x != nextX) {
            x = x > nextX ? x - 1 : x + 1;
          }
          if (y != nextY) {
            y = y > nextY ? y - 1 : y + 1;
          }
        }
      }
    

    Pembuatannya dapat dilakukan sebagai class tersendiri, atau inner class yang ada di dalam class public. Terdapat 2 pasang variable yang merepresentasikan koordinat. Pasangan pertama adalah koordinat asli dari bola, sedangkan pasangan kedua adalah koordinat tujuan pergerakan bola.

    Constructor akan mendefinisikan letak awal bola, serta mengambil gambar dari file “ball.png” menggunakan class ImageIO. Class ImageIO merupakan class bantu yang berfungsi untuk input/output file bertipe image. Karena merupakan class input output, maka ImageIO akan “throws” IOException jika terjadi suatu error.

    Method drawBall adalah method yang digunakan untuk menggambar bola tersebut. Perhatikan bahwa parameter yang digunakan adalah Graphics2D, yaitu class yang berfungsi melakukan penggambaran pada kanvas (lihat kembali method paintComponent pada JPanel). Method update() nantinya akan dipanggil pada loop animasi, yang akan menggerakkan bola menuju koordinat tujuan.

  5. Tahap berikutnya adalah membuat inner class yang akan mendeteksi event dari mouse. Class tersebut cukup extend class MouseAdapter yang mengimplementasikan interface MouseListener. Sebagai langkah awal yang sederhana, Anda cukup mengoverride method mouseClicked saja. Event tersebut akan mengubah nilai koordinat tujuan bola.
      class ClickDetector extends MouseAdapter {
        PanelClickable parent;
    
        public ClickDetector(PanelClickable parent) {
          this.parent = parent;
        }
    
        @Override
        public void mouseClicked(MouseEvent e) {
          super.mouseClicked(e);
          parent.ball.nextX = e.getX();
          parent.ball.nextY = e.getY();
        }
      }
    
  6. Tambahkan kedua inner class yang telah dibuat sebelumnya ke dalam class PanelClickable. Cara paling mudah adalah mendeklarasikannya dalam constructor.
    public class PanelClickable extends JPanel {
      Ball ball;
    
      public PanelClickable() {
        setPreferredSize(new Dimension(400, 300));
        addMouseListener(new ClickDetector(this));
        ball = new Ball(0, 0);
      }
    // kode lainnya
    
  7. Tahap terakhir adalah membuat animasi untuk kanvas tersebut. Konsep dari animasi adalah membuat thread yang berbeda. Maksud dari thread yang berbeda adalah membuat suatu garis proses baru sehingga proses animasi akan berbeda dari proses thread untuk program utama. Konsep ini dikenal dengan nama multithreading. Dalam Java, multithreading dapat dilakukan dengan cara membuat object thread baru. Anda bisa membuatnya secara sederhana dalam constructor PanelClickable.
        Thread t = new Thread(new Runnable() {
          public void run() {
            while(true) {
              ball.update();
              repaint();
              try {
                Thread.sleep(15);
              } catch (InterruptedException ex) {}
            }
          }
        });
        t.start();
    

    Perhatikan bahwa terdapat endless loop atau loop yang akan selalu berputar dengan cara membuat while(true). Pada baris awal akan melakukan pemanggilan pada method update() milik object ball. Setelah lokasi berubah, maka harus dilakukan pemanggilan method repaint() yang akan menggambar ulang kanvas dengan nilai property yang baru tadi. Setelah itu, thread diberhentikan sementara selama 15 milidetik untuk memperlihatkan animasi secara cepat. Jika dihitung secara kasar, maka akan ada 1000/15 frame per second, atau 66,6 penggambaran ulang setiap detiknya.

  8. Program telah selesai, Anda bisa mencobanya dengan mengklik suatu area pada kanvas. Jika berjalan lancar, maka bola akan bergerak menuju titik yang anda klik.

    Hasil percobaan grafis Java

Selamat mencoba..!! :D

Download source code secara keseluruhanArtikel ini telah dipublikasikan di media cetak tabloid PC Mild edisi 02 tahun 2011 lalu.