친구 숙제로 만들었는데 생각보다 잘 만든것 같아서 박제함
자바 첨해보는데 씨샾 2중대 같다.
//MainForm.java
package test;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Random;
public class MainForm extends JFrame {
/// 사용할 이미지 로드 /////////////////////////////////////////////////////////////////////
BufferedImage backimage1 = ImageIO.read(new File("src/image/image1.png"));//메인 패널 이미지 1
BufferedImage backimage2 = ImageIO.read(new File("src/image/image2.png"));//메인 패널 이미지 2
BufferedImage leftimage = ImageIO.read(new File("src/image/left.png"));// 왼쪽 화살표
BufferedImage upimage = ImageIO.read(new File("src/image/up.png"));// 위쪽 화살표
BufferedImage rightimage = ImageIO.read(new File("src/image/right.png"));//오른쪽 화살표
BufferedImage downimage = ImageIO.read(new File("src/image/down.png"));//아래쪽 화살표
BufferedImage correctimage = ImageIO.read(new File("src/image/yourock.png"));//정답 이미지
BufferedImage wrongimage = ImageIO.read(new File("src/image/yousuck.png"));//오답 이미지
////////////////////////////////////////////////////////////////////////////////////////
/// 게임 처리에 사용할 변수 목록 //////////////////////////////////////////////////////////////
static int Currentp[] = new int[4];//로드할 이미지 목록을 저장할 배열
static int CurrentIndex = 0;//현재 몇번째 화살표를 맞추지 저장할 변수
static int TotalScore = 0;//전체 점수
static int timelimit = 30;//남은 시간
static InfoPanel directionimage[] = new InfoPanel[4];//화살표 이미지를 출력할 JPanel 변형 클래스 배열
static Timer timer = null;//매 초마다 남은 시간을 계산할 타이머
private JLabel leftTimeLabel = new JLabel(String.format("You have %d seconds to play!! Press key to start!!", timelimit));// 게임 화면 상단에 표시할 남은 시간 및 점수용 JLabel
////////////////////////////////////////////////////////////////////////////////////////
/// Event //////////////////////////////////////////////////////////////////////////////
public MainForm() throws Exception {
setTitle("Rythme Game");//게임 제목 표시
Container c = getContentPane();//JPanel들을 묶어서 출력하기 위한 컨테이너 선언
setLayout(null);
leftTimeLabel.setForeground(Color.RED);//게임 화면 상단 문자열 글자색 지정
leftTimeLabel.setHorizontalAlignment(JLabel.CENTER);//게임 화면 상단 문자열 표시 위치
leftTimeLabel.setFont(new Font("Verdana", Font.BOLD, 15));//게임 상단 화면 문자열 글씨체 및 글씨 크기
ImagePanel background = new ImagePanel(backimage1, backimage2);//근육맨 이미지 2개가 번갈아 표시될 ImagePanel 클래스 객체 초기화
background.setLocation(0, 0);//ImagePanel 위치 지정
background.setPreferredSize(new Dimension(800, 500));//ImagepPanel 크기 지정
background.setLayout(new FlowLayout());
c.add(background);//컨테이너에 ImagePanel 추가
background.add(leftTimeLabel);//ImagePanel 위에 점수 및 남은 시간을 표시
for(int i=0;i<4;i++) {
directionimage[i] = new InfoPanel(i);//각각의 화살표를 출력하기 위한 InfoPanel 객체 초기화
directionimage[i].setLocation(i * 150 + 100, 550);//InfoPanel 위치 지정
directionimage[i].setPreferredSize(new Dimension(100, 100));//InfoPanel 크기 지정
directionimage[i].setBounds(i * 150 + 100, 550, 100, 100);//InfoPanel 크기 지정
c.add(directionimage[i]);//컨테이너에 InfoPanel 추가
}
/// 키보드 이벤트 처리 //////////////////////////////////////////////////////////////
addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
if(timer.isRunning() == false) {// 게임 타이머가 시작되지 않은 경우,
timer.start();//게임 타이머를 시작한다
}
leftTimeLabel.setText(String.format("Left Time : %d Your Score : %d", timelimit, TotalScore));//새로운 키를 눌렀을 경우, 점수 문자열 초기화
System.out.println(e.getKeyCode());
if(Currentp[CurrentIndex] == e.getKeyCode()) {//정답 키를 입력한 경우
directionimage[CurrentIndex].SetCorrect();//현재 InfoPanel에 정답 이미지를 출력하게 하고
TotalScore += 10;//점수 추가
}
else {//오답 키를 입력한 경우
directionimage[CurrentIndex].SetWrong();//현재 InfoPanel에 오답 이미지를 출력하게 하고
TotalScore -= 5;//점수 제거
}
CurrentIndex++;//다음 입력은 다음 InfoPanel이 받을 수 있도록 CurrentIndex + 1
if(CurrentIndex == 4) {//만약 현재 이미지가 마지막 이미지 였을 경우
new Thread() {
@Override
public void run() {
try {
sleep(150);//150ms 대기 후 ( 바로 넘어갈 경우, 마지막 이미지의 정답 여부를 볼 수 없음 )
} catch (InterruptedException e) {
e.printStackTrace();
}
CurrentIndex = 0;//CurrentIndex 초기화하고
resetDirectionPanel();//새로운 화살표 배당받기
}
}.start();//별도의 쓰레드에서 실행하는 이유는 UI 쓰레드에서 Thread.sleep()을 실행할 경우, UI 쓰레드의 작동자체가 멈추기 때문에 이미지가 바뀌지 않는다. ( 이 부분은 window programming 관련 지식이 필요하므로, 그냥 대충 스킵하는게 좋을 것 같음. 필요 시 문의 )
}
}
});
/////////////////////////////////////////////////////////////////////////////////////
/// 타이머 초기화 //////////////////////////////////////////////////////////////////////
timer = new Timer (1000, new ActionListener() {// 1000ms (1초) 마다 동작하는 타이머 초기화
public void actionPerformed(ActionEvent e) {
timelimit--;//남은 시간 - 1
leftTimeLabel.setText(String.format("Left Time : %d Your Score : %d", timelimit, TotalScore));//점수 및 잔여 시간 문자열 출력
if(timelimit == 0) {//게임이 끝난 경우
JOptionPane.showMessageDialog(null, String.format("your score : %d!!", TotalScore), "GAME OVER!!", JOptionPane.OK_OPTION);//점수를 알려주는 메세지 박스 출력
TotalScore = 0;//점수 초기화
timelimit = 30;//잔여시간 초기화
leftTimeLabel.setText(String.format("Left Time : %d Your Score : %d", timelimit, TotalScore));//점수 및 잔여 시간 문자열 초기화
timer.stop();//게임 타이머 중지. 다음 키보드 입력 시 새로운 게임 시작
resetDirectionPanel();//새로운 화살표 할당
}
}
});
/////////////////////////////////////////////////////////////////////////////////////
setSize(800,700);//창 전체 사이즈 지정
setPreferredSize(new Dimension(800, 700));//창 전체 사이즈 지정
setLocationByPlatform(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setVisible(true);
}
/// 메인 함수 ////////////////////////////////////////////////////////////////////////
public static void main(String[] args) {
try {
MainForm handle = new MainForm();
resetDirectionPanel();
} catch (Exception e) {
e.printStackTrace();
}
}
////////////////////////////////////////////////////////////////////////////////////
/// 새로운 화살표 할당 함수 /////////////////////////////////////////////////////////////
public static void resetDirectionPanel() {
Random random = new Random();
random.setSeed(System.currentTimeMillis());//현재 시간 (ms)를 랜덤 시드로 설정
for(int i=0;i<4;i++) {
Currentp[i] = random.nextInt(4) + 0x25; // 화살표 키 KeyCode에 해당하는 값 ( 0x25~0x28 ) 을 배열에 무작위로 저장
directionimage[i].SetState();//화살표 이미지 초기화
}
}
////////////////////////////////////////////////////////////////////////////////////
/// 화살표 이미지 출력 클래스 ////////////////////////////////////////////////////////////
class InfoPanel extends JPanel {
private int index = -1;//현재 화살표 이미지가 몇번째 화살표 이미지인지 저장
private Image image = null;//이미지 변수
public InfoPanel(int idx) {
index = idx;
image = correctimage;
repaint(0, 0, 100, 100);
}
// 현재 이미지를 정답 이미지로 설정
public void SetCorrect() {
image = correctimage;
repaint(0, 0, 100, 100);
}
// 현재 이미지를 오답 이미지로 설정
public void SetWrong() {
image = wrongimage;
repaint(0, 0, 100, 100);
}
// 현재 이미지를 화살표 이미지로 설정
public void SetState() {
int s = Currentp[index];
switch(s) {
case 0x25:
image = leftimage;
break;
case 0x26:
image = upimage;
break;
case 0x27:
image = rightimage;
break;
case 0x28:
image = downimage;
break;
}
repaint(0, 0, 100, 100);
}
@Override
protected void paintComponent(Graphics g) {//이미지 초기화 함수 오버라이드
super.paintComponent(g);
g.drawImage(image, 0, 0, 100, 100, this);
}
}
//////////////////////////////////////////////////////////////////////////////////
/// 근육맨 이미지를 표시할 JPanel 클래스 /////////////////////////////////////////////////////////
class ImagePanel extends JPanel {
private Image pimage1 = null, pimage2 = null, image;//image : 실제 표시할 이미지 pimage1,2 : 표시할 1번 2번 이미지를 미리 클래스 안에 저장해둠
private int currentp = 1;//1번째 이미지, 2번째 이미지 중 뭘 표시할 건지 결정하는 변수
private int height = 500, width = 800;//이미지 크기 지정
Timer timer = null;//이미지가 1초마다 바뀔 수 있도록 타이머 선언
public ImagePanel(Image image1, Image image2) {
this.image = image1;
this.pimage1 = image1;
this.pimage2 = image2;
/// 이미지 변경 타이머 /////////////////////////////////////////////////////////
timer = new Timer (1000, new ActionListener() {//1초마다 실행되는 타이머 선언
public void actionPerformed(ActionEvent e) {
if(currentp == 1) {
image = pimage1;
}
else {
image = pimage2;
}
currentp = 1 - currentp;//currentp 가 1인 경우 0이되고 0인 경우 1이 되는 로직
repaint(0, 0, width, height);// 이미지 초기화
}
});
////////////////////////////////////////////////////////////////////////////
timer.start();
setSize(800, 500);
}
@Override
protected void paintComponent(Graphics g) {//이미지 변경 함수 오버라이드
super.paintComponent(g);
g.drawImage(image, 0, 0, width, height, this);
}
}
///////////////////////////////////////////////////////////////////////////////////////////
}
황철순 키우기 (리겜)