반응형
Java GUI 연습용 Rhythm Game 만들기
해당 게임 제작은 안경잡이 개발자 - 나동빈 님의 https://youtu.be/xs92kqU2YWg
자바 리듬게임 만들기 강의를 보고 만들었습니다.
사용되는 노래의 출처는
YuYoon 에게 있음을 밝힙니다. (사용 허가 받았으며 배포는 하지 않습니다.)
현재 main에서 실행할 RhythmGame class와 노래를 틀어주는 Music class를 만들었습니다.
RhythmGame class
package gui_rhythm_game;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
//JFrame: java에서 GUI기반의 프로그램을 만들기 위해서 상속받는 라이브러리
import javax.swing.JLabel;
public class RhythmGame extends JFrame {
/* 더블 버퍼링 기술을 위해서 전체 화면에 대해서 이미지를 담는 두 인스턴스 */
private Image screenImage;
private Graphics screenGraphic;
private ImageIcon exitMenuButton = new ImageIcon(Main.class.getResource("../images/menu/exit.png"));
private ImageIcon exitMenuButtonOn = new ImageIcon(Main.class.getResource("../images/menu/exitOn.png"));
private ImageIcon startbutton = new ImageIcon(Main.class.getResource("../images/buttens/startbutton.png"));
private ImageIcon startbuttonOn = new ImageIcon(Main.class.getResource("../images/buttens/startbuttonOn.png"));
private ImageIcon exitbutton = new ImageIcon(Main.class.getResource("../images/buttens/exitbutton.png"));
private ImageIcon exitbuttonOn = new ImageIcon(Main.class.getResource("../images/buttens/exitbuttonOn.png"));
private Image background; // 이미지를 담을 객체
private JLabel menubar = new JLabel(new ImageIcon(Main.class.getResource("../images/menu/menubar.jpg")));
private JButton exitMenubt = new JButton(exitMenuButton);
private JButton startbt = new JButton(startbutton);
private JButton exitbt = new JButton(exitbutton);
// 마우스 좌표를 담을 변수 생성
private int mouseX, mouseY;
// initialization/RhythmGame.java
public RhythmGame() {
setUndecorated(true);
setTitle("GUI_RhythmGame");
setSize(Main.SCREEN_WIDTH, Main.SCREEN_HEIGHT); // 화면 크기 설정
setResizable(false); // 사용자가 임의적으로 화면의 크기 변경 불가능
setLocationRelativeTo(null); // 실행시 게임창 중앙에 띄우기 위함
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 게임창 종료시 프로그램 전체 종료
// 만약 미설정시 프로그램이 계속 실행되고 창만 종료됨
setVisible(true); // 창 띄우기
setBackground(new Color(0, 0, 0, 0));
// button과 같은 이미지를 paintComponents로 그릴때 배경을 투명하게
setLayout(null);
exitMenubt.setBounds(1230, 0, 45, 30);
exitMenubt.setBorderPainted(false);
exitMenubt.setContentAreaFilled(false);
exitMenubt.setFocusPainted(false);
exitMenubt.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
exitMenubt.setIcon(exitMenuButtonOn);
exitMenubt.setCursor(new Cursor(Cursor.HAND_CURSOR));
Music buttonEnteredMusic = new Music("buttonEnteredMusic.mp3", false);
buttonEnteredMusic.start();
}
@Override
public void mouseExited(MouseEvent e) {
exitMenubt.setIcon(exitMenuButton);
exitMenubt.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
@Override
public void mousePressed(MouseEvent e) {
Music buttonEnteredMusic = new Music("buttonPressedMusic.mp3", false);
buttonEnteredMusic.start();
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
// TODO: handle exception
ex.printStackTrace();
}
System.exit(0);
}
});
add(exitMenubt);
menubar.setBounds(0, 0, 1280, 30);
menubar.addMouseListener(new MouseAdapter() {
//마우스 입력에서 마우스를 눌렀을때 이벤트 처리
@Override
public void mousePressed(MouseEvent e) {
mouseX = e.getX();
mouseY = e.getY();
}
});
menubar.addMouseMotionListener(new MouseMotionAdapter() {
//마우스 이동을 감지하고 마우스 드레그 이벤트 발생시 창을 이동시킨다.
@Override
public void mouseDragged(MouseEvent e) {
int x = e.getXOnScreen();
int y = e.getYOnScreen();
setLocation(x - mouseX, y - mouseY);
}
});
add(menubar);
// start button을 추가하고 해당 버튼의 기본 디자인 셋팅을 false로 한다.
startbt.setBounds(20, 300, 420, 120);
startbt.setBorderPainted(false);
startbt.setContentAreaFilled(false);
startbt.setFocusPainted(false);
startbt.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
startbt.setIcon(startbuttonOn);
startbt.setCursor(new Cursor(Cursor.HAND_CURSOR));
Music buttonEnteredMusic = new Music("buttonEnteredMusic.mp3", false);
buttonEnteredMusic.start();
}
@Override
public void mouseExited(MouseEvent e) {
startbt.setIcon(startbutton);
startbt.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
@Override
public void mousePressed(MouseEvent e) {
Music buttonEnteredMusic = new Music("buttonPressedMusic.mp3", false);
buttonEnteredMusic.start();
startbt.setVisible(false);
exitbt.setVisible(false);
background = new ImageIcon(Main.class.getResource("../images/inMenuBackground.jpg")).getImage();
}
});
add(startbt);
exitbt.setBounds(20, 430, 420, 120);
exitbt.setBorderPainted(false);
exitbt.setContentAreaFilled(false);
exitbt.setFocusPainted(false);
exitbt.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
exitbt.setIcon(exitbuttonOn);
exitbt.setCursor(new Cursor(Cursor.HAND_CURSOR));
Music buttonEnteredMusic = new Music("buttonEnteredMusic.mp3", false);
buttonEnteredMusic.start();
}
@Override
public void mouseExited(MouseEvent e) {
exitbt.setIcon(exitbutton);
exitbt.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
@Override
public void mousePressed(MouseEvent e) {
Music buttonEnteredMusic = new Music("buttonPressedMusic.mp3", false);
buttonEnteredMusic.start();
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
// TODO: handle exception
ex.printStackTrace();
}
System.exit(0);
}
});
add(exitbt);
background = new ImageIcon(Main.class.getResource("../images/mainbackground.jpg")).getImage();
// Main class의 위치를 기반으로 이미지파일을 인스턴스로 introbackground에 넣는다.
Music introMusic = new Music("Hawn(mainbgm).mp3", true);
introMusic.start();
}
/*
* paint method paint는 가장 처음으로 화면을 그려주는 메소드 screenDraw로 이미지를 그리고 다시 paint함수를 불러옴
* 매순간 마다 화면을 계속 다시 그려줌
*/
public void paint(Graphics g) {
screenImage = createImage(Main.SCREEN_WIDTH, Main.SCREEN_HEIGHT);
screenGraphic = screenImage.getGraphics();
screenDraw(screenGraphic);
g.drawImage(screenImage, 0, 0, null);
}
public void screenDraw(Graphics g) {
g.drawImage(background, 0, 0, null);
// 배경과 같은 간단이미지를 그리는 메소드
paintComponents(g);
// 따로 추가된 그림도 그려주는 메소드 호출 -> 항상 고정된 메뉴바 버튼은 해당 메소드로 구현
this.repaint();
}
}
Music class
package gui_rhythm_game;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import javazoom.jl.player.Player;
public class Music extends Thread {
private Player player; //javazoom 라이브러리 사용
private boolean isLoop;
private File file;
private FileInputStream fis;
private BufferedInputStream bis;
public Music(String name, boolean isLoop) {
// play할 음악 이름과 반복 여부를 받는다.
try {
this.isLoop = isLoop;
file = new File(Main.class.getResource("../music/"+ name).toURI());
fis = new FileInputStream(file);
bis = new BufferedInputStream(fis);
player = new Player(bis);
} catch (Exception e) {
// TODO: handle exception
System.out.println(e.getMessage());
}
}
public int getTime() {
//현재 플레이 음악이 어느 위치에서 플레이 되는지 반환 10초일경우 10,000 반환 0.001초 까지 분석 가능
if(player == null)
return 0;
return player.getPosition();
}
public void close() {
// 특정 이유로 곡을 중단할 경우 해당 곡을 안전하게 종료하기 위한 함수
isLoop = false;
player.close();
this.interrupt();
// 해당 쓰레드를 중지 상태로 만든다.
}
@Override
public void run() {
//Thread를 상속한경우 필수
try {
do {
//isLoop 가 true인경우 다시 재생
player.play();
fis = new FileInputStream(file);
bis = new BufferedInputStream(fis);
player = new Player(bis);
} while(isLoop);
} catch (Exception e) {
// TODO: handle exception
System.out.println(e.getMessage());
}
}
}
반응형
'개발로 기록하는 일상 > 프로젝트' 카테고리의 다른 글
[NUTEE] 구현방법 정리: 확장함수 loadFragment (0) | 2020.08.13 |
---|---|
[NUTEE] 구현 방법 메모 : Acticity와 Fragment 로직 위치 (0) | 2020.08.12 |
Java GUI practice - Rhythm Game - 2 개발일지 (0) | 2019.12.26 |