정보기술, IT/IT source

Thread를 이용한 경주게임

100sk 2013. 4. 5. 11:57

- 예제를 이용한 java programming -

Thread를 이용한 애니매이션 경주 게임

이번 포스트에서는 Java의 Thread를 이용하여 애니매이션 효과를 주는 동시에 게임형식으로 프로그램을 코딩할 것이다.

먼저 해당하는 객체를 나누는 작업을 UML로 작성한 후 프로그램 코딩을 들어가면 한결 수월해 질 것이다.

예제를 이용한 화면은 아래와 같다. 프레임을 활용하며 버튼을 이용해 게임을 만들 것이다.

1) 경주중인 모습

2) 도착후 그 결과를 보여준다.


먼저 MyFrame 클래스를 MyHorse 클래스로 나누어 코딩을 할 것이다.

MyFrame 클래스는 프레임 객체를 생성하는 클래스 이므로 프레임에 해당하는 너비, 높이와, 필요한 버튼과 결과창을 보여줄 텍스트뷰.

그리고 쓰레드 클래스의 인터페이스인 Runnable을 이용하여 run 함수에 이미지가 반복적으로 그려지게 할 것이다.


>> 프레임 생성자함수에는 크기에 대한 값과 필요한 함수들을 선언해 줄 것이다.

 public MyFrame() {
  setVisible(true);
  setSize(FRAME_WIDTH, FRAME_HEIGHT);
  makeHorse();
  makeUi();
  Thread t = new Thread(this);
  t.start();
 }


>> synchronized를 이용하여 서로 다른 쓰레드에서 함수를 호출할 때 두 메소드가 동시에 일어나지 않도록 하는 함수이다. 

그럼 배열에 MyHorse 클래스에서 생성한 객체를 담아 주도록 한다. (버튼 생성에 대한 내용은 생략하도록 하겠다.)

 private synchronized void makeHorse() {
  for (int i = 0; i < HORSE_SIZE; i++) {
   arr[i] = new MyHorse();

  }

 }


>> 해당 버튼이 클릭되었을 때 Action이 수행 될 수 있도록 내부클래스를 선언하여 알맞은 코딩을 다루게 한다.

 class MyHanler implements ActionListener {


>> 게임시작 버튼 클릭시에 배열이 담긴 쓰레드 클래스를 start()함수로 호출하고 rrepaint되면서 계속 새로운 그림이 그려질 수 있도록 한다.

     종료 버튼 클릭시에는 프레임 창이 종료된다.

  @Override
  public void actionPerformed(ActionEvent e) {
   if (e.getSource() == btn_start) {
    for (int i = 0; i < HORSE_SIZE; i++) {
     (new Thread(arr[i])).start();
     repaint();

    }
   } else if (e.getSource() == btn_close) {
    dispose();
    System.exit(0);
   }
  }

 }


>>  그림이 담긴 배열을 while 반복문을 통해 계속 돌아가게 하는 코딩이다. 경기가 종료될때 등수를 찍어내도록 한다.

 @Override
 public void run() {
  boolean temp = false;
  int count = 0;
  while (!temp) {
   for (int i = 0; i < arr.length; i++) {
    if (arr[i].state) {
     txta.append(arr[i].getMy_score() + "등 : " + arr[i].getNum()
       + "번 말!! \n");
     arr[i].state = false;


>> 해당 포스트에는 그림을 4개만 사용하였기 때문에 count가 5가 되면 다시 처음부터 그림을 돌릴 수 있도록 하는 부분이다.
     if (count == 5) {
      temp = true;
     } else {
      count++;
     }// end if
    }// end if
   }// end for
  }// end while
 }// end run

};

 

 

 

// ---------------------------------------- MyHorse 클래스

 

public class MyHorse extends Canvas implements Runnable {

 public static final int HORSE_SIZE = 50;
 private static int score;
 private int my_score = 0;
 private String[] ImgAddr = new String[4];

 private Image img;

 private int x = 10;
 private int speed = 1;
 public static int num_plus = 1;
 private int num;
 private int ImgCount = 0;

 // 추가 코드
 public boolean state = false;

 public MyHorse() {
  num = num_plus++;
  imgAddr();

 }

 public void imgAddr() {
  ImgAddr[0] = "tt1.png";
  ImgAddr[1] = "tt2.png";
  ImgAddr[2] = "tt3.png";
  ImgAddr[3] = "tt4.png";
 }

 @Override
 public void paint(Graphics g) { // 페인트가 불릴때 캔버스 싸이즈가 결정된다.
  setSize(this.getWidth(), 100);
  setBackground(Color.black);
  g.setColor(Color.orange);
  g.drawString(num + "번", x + 15,
    (getHeight() / 2 - (HORSE_SIZE) / 2) - 5);
  g.drawImage(img, x, getHeight() / 2 - (HORSE_SIZE) / 2, HORSE_SIZE,
    HORSE_SIZE, this);
  // g.drawImage(t1, x, y, observer);

  if (ImgCount == 4) {
   ImgCount = 0;
  } else {
   img = Toolkit.getDefaultToolkit().getImage(ImgAddr[ImgCount]);
   ImgCount++;
  }

 }

 public void animation() {

 }

 @Override
 public void run() {
  while (true) {
   if (x < MyFrame.FRAME_WIDTH - 70) {
    speed = (int) (Math.random() * 10) + 9;
    x += speed;
    repaint();

    try {
     Thread.sleep(100);
    } catch (InterruptedException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }

   } else {
    x = MyFrame.FRAME_WIDTH - 60;
    my_score = ++score;
    state = true;
    System.out.println("번 말" + ", " + "등수 :" + my_score);
    repaint();
    break;
   }

  }

 }

 public void getImage() {

 }

 public int getMy_score() {
  return my_score;
 }// end getMy_score

 public int getNum() {
  return num;
 }// end getNum

};