아바타와 괴물이 등장하고 괴물은 터미네이터처럼 끊임없이 아바타를 따라다니는 게임을 만들어보자. 아바타는 15x15 크기의 "@" 문자열 레이블로 만들고, 괴물 역시 "M" 문자열 레이블로 만든다. 아바타는 상하좌우 키를 이용하여 패널상에서 움직이면서 도망가고, 괴물은 자동으로 아바타를 추적하여 따라다닌다. 아바타가 도망치는 속도가 떨어지면 괴물에게 잡히게 된다. 이 게임은 점수를 관리하지 않는다. 오직 'q' 키를 입력해야 게임은 종료된다. 아바타는 한 번의 키 입력에 따라 10픽셀씩 이동하며, 괴물은 상하좌우대각선 방향으로 움직일 수 있고 200ms마다 한 번 이동하고 그 거리는 5픽셀이다.
GamePanel
을 만들고 이곳에서 아바타 레이블과 괴물 레이블이 자유롭게 위치할 수 있도록 배치관리자를 삭제한다.KeyListener
를 구현하여 GamePanel
에 등록한다. keyPressed()
메소드를 작성하고 먼저 KeyEvent.getKeyChar()
메소드를 호출하여 'q' 키가 입력되었는지 비교하고 그렇다면 System.exit(0)
을 호출하여 프로그램을 종료한다. 다시 KeyEvent.getKeyCode()
메소드를 호출하여 상하좌우 키의 가상 키 값과 비교한다.GamePanel
이 키 입력을 받을 수 있도록 포커스를 주는 것을 잊지 말라.Thread
를 상속받은 MonsterThread
스레드를 작성하고 run()
메소드에서 4가지 경우를 판단한다. 아바타가 괴물의 왼쪽에 있는지, 오른쪽에 있는지, 위쪽에 있는지, 아래쪽에 있는지 판단하고 그에 따라 괴물의 위치를 조정한다. 괴물의 위치가 변경되면 곧장 GamePanel
을 다시 그려야 한다. 예를 들어 괴물 레이블이 monster이면 moster.getParent().repaint()
를 호출한다.import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class GamePanel extends JPanel {
private JLabel avatar = new JLabel("@");
private JLabel monster = new JLabel("M");
int avatarX = 100;
int avatarY = 100;
int monsterX = 200;
int monsterY = 200;
public GamePanel() {
setLayout(null); //배치관리자 삭제
avatar.setForeground(Color.RED);
this.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
//방향키
int key = e.getKeyCode();
if(key == KeyEvent.VK_UP) {//상
avatarY -= 10;
} else if (key == KeyEvent.VK_DOWN) {//하
avatarY += 10;
} else if (key == KeyEvent.VK_LEFT) {//좌
avatarX -= 10;
} else {//우
avatarX += 10;
}
int keyChar = e.getKeyChar();
if(keyChar == 'q')
System.exit(0);
repaint();
}
});
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
avatar.setSize(15,15);
avatar.setLocation(avatarX,avatarY);
add(avatar);
monster.setSize(15,15);
monster.setLocation(monsterX,monsterY);
add(monster);
}
}
class MonsterThread extends Thread {
private GamePanel p;
public MonsterThread(GamePanel panel) {
p = panel;
}
public void run() {
while (true) {
if(p.avatarX < p.monsterX) { //아바타가 왼쪽에 있으면
p.monsterX -= 5;
} else if (p.avatarX > p.monsterX) {//아바타가 오른쪽에 있으면
p.monsterX += 5;
}
if (p.avatarY < p.monsterY) {//아바타가 위쪽에 있으면
p.monsterY -= 5;
} else if (p.avatarY > p.monsterY) {//아바타가 아래쪽에 있으면
p.monsterY += 5;
}
p.repaint(); //몬스터 움직임
try {
sleep(200);
} catch (InterruptedException e) {
return;
}
}
}
}
public class AvatarAndMonsterGame extends JFrame{
public AvatarAndMonsterGame() {
setTitle("아바타와 괴물 게임");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GamePanel panel = new GamePanel();
setContentPane(panel);
panel.setFocusable(true);
panel.requestFocus(); //GamePanel이 키 입력을 받을 수 있도록 포커스 주기
setSize(300,300);
setVisible(true);
MonsterThread th = new MonsterThread(panel);
th.start();
}
public static void main(String[] args) {
new AvatarAndMonsterGame();
}
}