Minggu, 18 Maret 2012

MEMBUAT GAME JAVA SNACK HQ DENGAN NETBEANS

/*
 * DO NOT REMOVE THIS COPYRIGHT
 * 
 * This source code is created by Muhammad Fauzil Haqqi
 * You can use and modify this source code but
 * you are forbidden to change or remove this license
 * 
 * Nick  : Haqqi
 * YM    : xp_guitarist
 * Email : fauzil.haqqi@gmail.com
 * Blog  : http://fauzilhaqqi.blogspot.com
 */

package snakehq;

import java.awt.Point;

/**
 * Snake class, a representation of a snake
 *
 * @author Haqqi
 */
public class Snake {
  //*********************//
  //*** Variable area ***//
  //*********************//
  // coordinates of body
  private Point[] body;
  // facing
  private int face;

  // maximum snake's length
  private final int maxLength = 10;

  // orientation
  public static final int NORTH = 0;
  public static final int EAST = 1;
  public static final int SOUTH = 2;
  public static final int WEST = 3;

  // snake pixel size
  public static final int SNAKE_SIZE = 10;

  //************************//
  //*** Constructor area ***//
  //************************//
  public Snake() {
    body = new Point[maxLength];
    for(int i = 0; i < maxLength; i++) {
      body[i] = new Point(20 - i, 15);
    }
    face = EAST;
  }

  //*******************//
  //*** Method area ***//
  //*******************//
  public Point[] getBody() {
    return body;
  }

  public void moveEast() {
    if(face != WEST)
      face = EAST;
  }

  public void moveWest() {
    if(face != EAST)
      face = WEST;
  }

  public void moveNorth() {
    if(face != SOUTH)
      face = NORTH;
  }

  public void moveSouth() {
    if(face != NORTH)
      face = SOUTH;
  }

  public void update() {
    // update body
    for(int i = body.length - 1; i > 0; i--) {
      body[i].x = body[i-1].x;
      body[i].y = body[i-1].y;
    }
    // update head
    Point head = body[0];
    if(face == NORTH) {
      if(head.y <= 0)
        head.y = Panel.AREA_HEIGHT - 1;
      else
        head.y--;
    }
    else if(face == EAST) {
      if(head.x >= Panel.AREA_WIDTH - 1)
        head.x = 0;
      else
        head.x++;
    }
    else if(face == SOUTH) {
      if(head.y >= Panel.AREA_HEIGHT - 1)
        head.y = 0;
      else
        head.y++;
    }
    else if(face == WEST) {
      if(head.x <= 0)
        head.x = Panel.AREA_WIDTH - 1;
      else
        head.x--;
    }
  }
}

Pembuatan class Snake ini tidaklah sulit. Bagian terpenting dari game sederhana ini adalah kerangka game yang berupa panel. Berikut source code-nya.
/*
 * DO NOT REMOVE THIS COPYRIGHT
 * 
 * This source code is created by Muhammad Fauzil Haqqi
 * You can use and modify this source code but
 * you are forbidden to change or remove this license
 * 
 * Nick  : Haqqi
 * YM    : xp_guitarist
 * Email : fauzil.haqqi@gmail.com
 * Blog  : http://fauzilhaqqi.blogspot.com
 */

package snakehq;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

/**
 * Panel class, the skeleton of the game
 *
 * @author Haqqi
 */
public class Panel extends JPanel {
  //*********************//
  //*** Variable area ***//
  //*********************//
  private Snake snake;
  private Thread animation;

  public static final int PANEL_WIDTH = 400;
  public static final int PANEL_HEIGHT = 300;
  public static final int AREA_WIDTH =
      PANEL_WIDTH / Snake.SNAKE_SIZE;
  public static final int AREA_HEIGHT =
      PANEL_HEIGHT / Snake.SNAKE_SIZE;

  //************************//
  //*** Constructor area ***//
  //************************//
  public Panel() {
    setPreferredSize(new Dimension(
        PANEL_WIDTH, PANEL_HEIGHT));
    snake = new Snake();
    initThread();
    addKeyListener(new KeyManager());
    setFocusable(true);
    requestFocusInWindow();
    animation.start();
  }
  
  //*******************//
  //*** Method area ***//
  //*******************//
  @Override
  protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D) g;
    g2.addRenderingHints(new RenderingHints(
        RenderingHints.KEY_ANTIALIASING,
        RenderingHints.VALUE_ANTIALIAS_ON));
    drawSnake(g2);
  }

  // render the snake
  private void drawSnake(Graphics2D g2) {
    Point[] s = snake.getBody();
    int pixel = Snake.SNAKE_SIZE;
    // fill the head
    g2.fillOval(s[0].x * pixel, s[0].y * pixel,
        pixel,pixel);
    // draw body outline
    for(int i = 0; i < s.length; i++) {
      g2.drawOval(s[i].x * pixel, s[i].y * pixel,
          pixel, pixel);
    }
  }

  // initiate animation thread
  private void initThread() {
    animation = new Thread(new Runnable() {
      public void run() {
        while(true) {
          try {
            // sleep a while for animation
            Thread.sleep(300);
          } catch (InterruptedException ex) {}
          snake.update();
          SwingUtilities.invokeLater(
              new Runnable(){
            public void run() {
              repaint();
            }
          });
        }
      }
    });
  }

  // Keyboard handler of the game
  private class KeyManager extends KeyAdapter {
    @Override
    public void keyPressed(KeyEvent e) {
      super.keyPressed(e);
      int c = e.getKeyCode();
      switch(c) {
        case KeyEvent.VK_RIGHT:
          snake.moveEast();
          break;
        case KeyEvent.VK_LEFT:
          snake.moveWest();
          break;
        case KeyEvent.VK_UP:
          snake.moveNorth();
          break;
        case KeyEvent.VK_DOWN:
          snake.moveSouth();
          break;
      }
    }
  }

  /**
   * Main method that run firstly when the program starts
   * @param args the command line arguments
   */
  public static void main(String[] args) {
    // TODO code application logic here
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        JFrame f = new JFrame("Snake HQ");
        f.setDefaultCloseOperation(
            JFrame.EXIT_ON_CLOSE);
        f.add(new Panel());
        f.pack();
        f.setResizable(false);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
      }
    });
  }
}

Panel ini hanya mempunyai 2 atribut/object penting. Yang pertama, jelas adalah si ular. Yang kedua, adalah thread yang digunakan untuk mengatur animasi. Proses animasi itu sendiri diatur dalam method initThread(). Coba saja pelajari apa yang dilakukan program dalam thread tersebut. Bagian lain yang penting adalah private class KeyManager. Class ini digunakan untuk menangkap event yang terjadi pada keyboard.

1 komentar: