이제 자바 공부도 한지 몇개월정도 지난것 같습니다. 이제부터는 기초 공부와 겸해서 내가 원하는 것, 내가 하고 싶은 것을 좀 더 만들어보기로 하였습니다(지금까지도 그랬지만...ㅋㅋ)
그래서 생각한게 바로 따라하면서 공부하기 였습니다.
안타깝게도 아직은 Java 를 능숙하게 따라가지 못하고 있고, 각 라이브러리의 메서드나 그런 것들에 대해서 무지하다고 생각하였습니다. 그래도 하고 싶은게 많았으니...결국 다른분들이 만든 것들을 보고, 강의를 보고 열심히 따라하면서 배우고자 합니다
물론 무조건 따라하는 것은 아니고, 따라하면서도 제 나름대로 구현 목표를 갖고, 기본적인 기능 외 목표로한 부분을 구현하는 것을 목표로 달려갈 예정입니다.
사실 하나의 글에 정리하고 싶었는데...생각보다 많아져서 여러번에 걸쳐 정리하기로 했습니다.
포스팅 순서
1. 구현 기능, 목표 및 Main, Dynamic 클래스
2. Game 클래스
3. Track, Music, Beat 클래스
4. Note, KeyListener 클래스
목표 : 자바로 리듬게임 만들기
- 강의는 '동빈나' 선생님의자바 리듬게임 만들기를 참고하였습니다(좋은 강의 감사합니다)
https://www.youtube.com/playlist?list=PLRx0vPvlEmdDySO3wDqMYGKMVH4Qa4QhR
현재 구현된 기능
- 시작 화면에서 인트로 음악 재생
- 시작 화면에 시작하기, 종료하기 버튼
- 시작하기 버튼 클릭 시 게임 메인 화면으로 전환, 종료하기 버튼 클릭 시 게임 종료
- 게임 메인 화면에서 음악 선택하면 해당 음악의 하이라이트 부분 재생
- 왼쪽 오른쪽 버튼에 따라서 음악 선택 가능
- 음악에 맞춰 노트 내려오고 노트별 판정 출력
- 점수 및 콤보 시스템
- 노트 찍기 모드 : 노트 찍기 모드가 활성화 된 경우 readNote 경로 안에 곡이름_난이도.txt 로 파일이 생기고 해당 파일 안에 노트 찍은 시간과 어떤 키를 눌렀는지 표시됨. 이후 Game 안에 있는 dropNote 메소드를 통해 해당 파일을 읽어오고 노트가 출력
추가 구현 목표
- DB 와 연동해서 게임 시작 시 로그인 기능
- 내가 만들어둔 Web 과 연동해서 로그인 시 게임 실행 가능 : 추가로 해당 로그인 아이디로 highscore 와 combo 를 기억해두었다가 웹에서 출력, 확인
게임 플레이 영상
Git
- 전체 코드는 git 에 올려두었습니다.
- 제 git에는 본 음악게임에서 사용된 어떤 노래와 사진도 포함되어 있지 않습니다. 다만 간단한 버튼과 제가 직접 포토샵으로 만든!!! 글자 이미지는 포함되어 있습니다.
https://github.com/SeJonJ/DynamicMusic
클래스 UML 다이어그램
1. Main.class
- 메인 클래스는 단순 그 자체!!
- DynamicMusic 클래스에 start 라는 메서드를 생성 후 해당 메서드를 실행하는 것으로 전체 프로그램이 실행된다.
- 만약 DynamicMusic 클래스의 생성자에 시작하는 코드를 넣어두면 굳이 dynamicMusic.start() 할 필요는 없다.
public class Main {
// FINAL 은 한번 선언되면 변경X 변수 => 이런 상수들은 대문자로 정의
public static final int SCREEN_WIDTH = 1280;
public static final int SCREEN_HEIGHT = 720;
public static void main(String[] args){
DynamicMusic dynamicMusic = new DynamicMusic();
dynamicMusic.start();
System.out.println("실행 완료");
}
}
2. DynamicMusic.class - 게임의 전반적인 부분에 대한 정의
해당 파일의 코드가 길어서 크게 여러 부분으로 나누어 설명하도록 하겠습니다.
1-1) 전역 변수 정리
- Image 와 Grapics 는 GUI 화면에 이미지를 띄우고 그려주기 위한 클래스이다.
- 먼저 Image 클래스를 사용해서 이미지를 가져오고 JButtion 을 만들어서 해당 이미지를 버튼에 넣는다.
- 이때 getClass().getResource 로 파일을 가져오는데 이것은 추후 jar 혹은 exe 로 파일을 만들었을 때에도 오류없이 게임을 실행시키기 위함이다.
// 더블버퍼링 기술 사용
private Image screenImage;
private Graphics screenGraphic;
// ImageIcon 생성자를 이용해서 Main.class 에 있는 위치에서 리소스를 가져옴
// 이후 다시 getter 를 이용해서 해당 이미지를 IntroBackground에 넣어줌
// jar 파일로 만들때는 getClass.getResource 를 사용한다!
// Background 객체는 이후 아래에서 화면이 전환될때 이곳에 다른 사진을 넣어서 배경경 사진 바뀔 수 있도록 함
// 시작화면 background
private Image Background = new ImageIcon(getClass().getResource("/menu_images/intro_background.jpg")).getImage();
// memuBar 객체 안에 memuBar 이미지가 들어가게 됨
private JLabel menuBar = new JLabel(new ImageIcon(getClass().getResource("/menu_images/menuBar.png")));
// 오른쪽 위 eixtButton 의 기본 이미지와 버튼에 마우스를 올렸을때 이미지가 변하도록
private ImageIcon exitButtonImage = new ImageIcon(getClass().getResource("/menu_images/exit.png"));
private ImageIcon exitButtonEnteredImage = new ImageIcon(getClass().getResource("/menu_images/exit_entered.png"));
// Button 생성
private JButton exitButton = new JButton(exitButtonImage);
private JButton startButton = new JButton(startButtonBasic);
private JButton quitButton = new JButton(quitButtonBasic);
private JButton leftButton = new JButton(leftButtonBasic);
private JButton rightButton = new JButton(rightButtonBasic);
private JButton easyButton = new JButton(easyButtonBasic);
private JButton hardButton = new JButton(hardButtonBasic);
private JButton backButton = new JButton(backButtonBasic);
private JButton noteWriteButton = new JButton(noteWriteMod);
1-2) 코드를 위한 전역 변수 설정
- 이 부분은 코드 주석을 참고하자
- 제일 중요한 것은 ArrayList<Track> 부분인데 여기서 Track 객체를 배열로 갖는 trackList 를 생성하는 것을 확인할 수 있다. 이때 인덱스 번호는 nowSelected 변수로 대신한다.
- trackList 에는 Track 를 객체로 갖는다. 예를 들어 0 번째 인덱스에 Track 객체가 들어가고 Track 객체는 특정한 노래의 해당 곡 명 이미지, 메인 메뉴 음악, 메인 메뉴 배경 화면, 인게임 음악, 인게임 화면, 해당 곡 명 을 갖는다.
- 최종적으로는 nowSelected = 0 인 경우 index 0번째 Track 객체를 가져오고 해당 Track 객체가 갖고있는 해당 곡 명 이미지, 메인 메뉴 음악, 메인 메뉴 배경 화면, 인게임 음악, 인게임 화면, 해당 곡 명 불러오게 된다.
// 윈도우 창 위치를 메뉴바를 끌어서 옮길 수 있도록 마우스 좌표 int
private int MouseX, MouseY;
// 게임에 맞춰 화면을 표시하기 위한 변수
private boolean isMainScreen = false;
// Ingame 으로 넘어왔는지 확인하기 위한 변수수
private boolean isGameScreen = false;
// ArrayList 어떠한 변수를 담을 수 있는 이미 만들어진 배열? => 하나의 음악의 정보를 배열로 담음
ArrayList<Track> trackList = new ArrayList<Track>();
// trackList 안에 있는 값에 따라서 아래 변수들의 값이 달라짐
// nowSelected 값은 현재 선택된 트랙의 번호이자 arraylist 의 index 를 의미한다.
private int nowSelected = 0;
private Image selectedImage;
private Image titleImage;
private Music selectedMusic;
// 인트로 음악 정의
private Music Intromusic = new Music("Intro_Elektronomia_Energy.mp3", true, "menu");
// Game 인스턴스 생성 && 초기화 :
// 이때 game 변수는 단 하나의 게임만 진행가능하며 game 변수자체가 프로젝트 전체에서 사용되어야하기 때문에
// static 으로 만들어줌
public static Game game;
2) JFrame 설정 및 각 버튼별 이벤트 설정
- 윈도우 창의 타이틀 이름, 보이는 여부, 위치와 크기 등을 정해준다.
- addKeyListener 부분에는 따로 키보트 별 이벤트 설정을 위해 KeyListener 이라는 클래스를 만들어서 매개변수로 넣어준다.
- exitButton 에서 버튼을 눌렀을때 이벤트, 땠을 때 이벤트, 올렸을 때 이벤트 등을 설정해준다.
- startButton 은 해당 버튼을 눌렀을 때 game_menu() 메소드가 실행되는데 이 메소드는 게임 메뉴로 들어가는 메소드이다.
setUndecorated(true); // 기본 메뉴바 삭제
setTitle("Dynamic Music");
setSize(Main.SCREEN_WIDTH, Main.SCREEN_HEIGHT);
setResizable(false); // 한번 창이 생성되면 임의적으로 창 크기 변경 불가
setLocationRelativeTo(null); // 창이 정중앙에 위치
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 게임 창을 종료 시 프로그램 전체 종료
setVisible(true); // 창 보이는 여부 => 반드시 true
setBackground(new Color(0, 0, 0, 0)); // paintcomponent 했을때 배경이 회색이 아니라 휜색으로 됨
setLayout(null); // 버튼이나 JLabel 을 넣었을 때 그 위치 그대로 넣어짐
// add해서 KeyListener 에 내가 만든 KeyListen 인식
addKeyListener(new KeyListener());
// 게임 시작시 인트로 음악 재생
Intromusic.start();
// exitButton
exitButton.setBounds(1245, 0, 30, 30); // 왼쪽부터 x, y , 길이, 높이
exitButton.setBorderPainted(false);
exitButton.setContentAreaFilled(false);
exitButton.setFocusPainted(false);
// 아래처럼 추상 클래스, 인터페이스등을 상속, 구현하는 클래스를 직접 생성한는 것 대신
// { ~~~ } 를 통해 생성하는 것을 익명 클래스라고 함
// 즉 new MouseAdapter() 뒤에 부분은 익명클래스로 MouseAdapter() 를 구현한 클래스로 취급됨
exitButton.addMouseListener(new MouseAdapter() {
@Override // 버튼에 마무스 올렸을 때 이벤트
public void mouseEntered(MouseEvent e) {
exitButton.setIcon(exitButtonEnteredImage);
exitButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
}
@Override // 버튼에 마우스 뗐을 때 이벤트
public void mouseExited(MouseEvent e) {
exitButton.setIcon(exitButtonImage);
exitButton.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
@Override // 마우스 눌렀을 때 이벤트
public void mousePressed(MouseEvent e) {
System.exit(0);
}
});
// 게임 시작 버튼
startButton.setBounds(800, 200, 400, 100);
startButton.setBorderPainted(false);
startButton.setContentAreaFilled(false);
startButton.setFocusPainted(false);
startButton.addMouseListener(new MouseAdapter() {
@Override // 버튼에 마무스 올렸을 때 이벤트
public void mouseEntered(MouseEvent e) {
startButton.setIcon(startButtonEntered);
startButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
}
@Override // 버튼에 마우스 뗐을 때 이벤트
public void mouseExited(MouseEvent e) {
startButton.setIcon(startButtonBasic);
startButton.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
@Override // 마우스 눌렀을 때 이벤트 => 즉 게임 시작버튼 눌렀을 때의 이벤트
public void mousePressed(MouseEvent e) {
// 게임 메뉴 시작
game_menu();
}
});
3) 난이도 버튼
- 난이도 버튼에서는 버튼을 눌렀을 때 해당 난이도로 게임이 실행되도록 한다. 정확히는 gameStart 메소드에 현재 선택한 곡 - noewSelected - 과 해당 난이도 - Easy, Hard - 를 매개변수로 보내준다.
// easy 난이도 버튼
// 시작화면에서는 난이도버튼 보일 필요 없음
easyButton.setVisible(false);
easyButton.setBounds(375, 580, 250, 67);
easyButton.setBorderPainted(false);
easyButton.setContentAreaFilled(false);
easyButton.setFocusPainted(false);
easyButton.addMouseListener(new MouseAdapter() {
@Override // 버튼에 마무스 올렸을 때 이벤트
public void mouseEntered(MouseEvent e) {
easyButton.setIcon(easyButtonBasic);
easyButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
}
@Override // 버튼에 마우스 뗐을 때 이벤트
public void mouseExited(MouseEvent e) {
easyButton.setIcon(easyButtonEntered);
easyButton.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
@Override // 마우스 눌렀을 때 이벤트
public void mousePressed(MouseEvent e) {
// 쉬움 난이도 이벤트
gameStart(nowSelected, "Easy");
}
});
// hard 난이도 버튼
hardButton.setVisible(false);
hardButton.setBounds(655, 580, 250, 67);
// hardButton.setBounds(900, 350, 250, 67);
hardButton.setBorderPainted(false);
hardButton.setContentAreaFilled(false);
hardButton.setFocusPainted(false);
hardButton.addMouseListener(new MouseAdapter() {
@Override // 버튼에 마무스 올렸을 때 이벤트
public void mouseEntered(MouseEvent e) {
hardButton.setIcon(hardButtonBasic);
hardButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
}
@Override // 버튼에 마우스 뗐을 때 이벤트
public void mouseExited(MouseEvent e) {
hardButton.setIcon(hardButtonEntered);
hardButton.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
@Override // 마우스 눌렀을 때 이벤트
public void mousePressed(MouseEvent e) {
// 어려움 난이도 이벤트
gameStart(nowSelected, "Hard");
}
});
4) 화면을 그래픽을 표현해주는 paint 와 screenDraw 메소드
- 이 부분도 주석을 참고부탁드립니다. 내용이 많고..복잡해요ㅠㅠ
- 간단히 설명하자면 paint 메소드는 JFrame 에서 화면을 그릴때 실행되는 함수이다.
- 먼저 paint 메소드가 실행된다. 이 안에서 screenImage 인스턴스가 동작하면서 에 윈도우 화면 크기만큼 생성하고, 다시 이 image 를 screenGraphic 에 넣어서 동작지킨다. 이를 통해 그래픽 객체가 생성된다.
- 이후 screenDraw 함수에 screenGraphic 를 Graphic 2D 로 형변환 후 매개변수로 넣어준다. screenImage 는 다시 drawImage 라는 메소드에 넣어주는데 이 매소드는 이미지를 띄워주는 메소드이다.
- screenDraw 는 화면은 추가로 그려주기 위한 메소드이다. 이 안에서 게임 시작 시 기본 배경 화면, 메인 메뉴에서의 이미지를 그려준다.
- 중요한 것은 screenDraw 에서의 repaint() 메소드인데 이 메소드를 통해서 paint , 즉 화면에 그래픽을 그려주는 것을 계속 반복하게 된다. 즉 그래픽은 한번만 띄워주고 끝내는 것이 아닌 paint 와 repaint 를 통해서 게임이 실행되는 동안 반복적이고, 지속적으로 그래픽을 그려준다. 이를 더블 버퍼링 기법이라고 하며 버퍼에 이미지를 담아서 계속 갱신해주는 기법이다.
// paint 메서드는 JFrame 에서 상속받아서 화면을 그릴때 가장 먼저 실행되는 함수
// 즉 아래 순서대로 실행된다고 생각하면 됨
// 1. JFrame 를 실행하면 updated(Graphics g) 가 가장 먼저 실행됨
// 2. 다음으로 paint(Graphics g) 가 실행됨
// 3. 이때 paint 함수 안에서 repaint() 를 실행함으로써 paint() -> repaint() -> paint() 식으로 반복됨
// 실행시켜보면 실제로 a -> c -> d -> b 순서로 반복됨
// 이렇게 화면을 계속 띄워주는 이유는 한번만 화면을 띄워주게 되면 버퍼링 현상이 심해서 느려지는 문제가 있음
// -> 이에 paint 와 repaint 를 통해 계속해서 introbackground 이미지를 띄워주게 됨
// 이런 기법을 더블 버퍼링 기법!! 이라고 함 : 버퍼에 이미지를 담아서 계속해서 갱신해줌
public void paint(Graphics g) {
screenImage = createImage(Main.SCREEN_WIDTH, Main.SCREEN_HEIGHT); // 윈도우 화면 크기 만큼 생성
screenGraphic = screenImage.getGraphics(); // screenImage 를 이용해서 그래픽 객체를 얻어옴
// System.out.println("a");
// screenGraphic 에 그림을 그려주게됨 , 그래픽에 화면에 이미지를 그린다? 라는 느낌? => 이때 screenDraw 메서드를 통해 화면을 그림(Draw)
screenDraw((Graphics2D) screenGraphic); // 그래픽스 2D 로 형변환
// System.out.println("b");
// 0,0 인 이유는 이미 screenImage 가 이미 화면 크기 그대로 이기 때문에 0,0에 띄워주는 것
g.drawImage(screenImage, 0, 0, null); // 윈도우 창에 screenImage 를 뿌려줌
}
public void screenDraw(Graphics2D g) { // 매개변수를 Graphics 에서 Graphics2D 로 변경
// System.out.println("c");
// drawImage 메서드를 Introbackground 를 x, y 좌표에 그려줌
// g.drawImage 부분은 paintComponents 처럼 화면에 추가된 요소를 그려주는 것이 아닌 단순히
// 이미지를 그림 그리는 것
g.drawImage(Background, 0, 0, null);
// isMainScreen = true 면 selectedImage 를 보여줌
if (isMainScreen) {
g.drawImage(selectedImage, 350, 100, null);
g.drawImage(titleImage, 340, 85, null);
}
// isGameScreen = true 인게임 화면에서의 그래픽
// ingame 에 관한 그래픽 내용은 Game 클래스에서 관리
if(isGameScreen){
game.screeenDraw(g);
}
// paintComponents 는 이미지를 단순히 그려주는 것 이외에 JLabel 처럼 추가된 요소를 그리는 것
// 즉 JFrame 위에 button 이나 라벨처럼 add() 된 부분에 대한 것
paintComponents(g);
try{
Thread.sleep(5);
}catch(Exception e){
e.printStackTrace();
}
this.repaint();
// System.out.println("d");
}
5) 트랙 & 음악 선택 메소드
- selectTrack 메소드는 곡을 선택 후 해당 곡의 메인 배경 화면과 노래의 하이라이트를 들려주게 된다.
- 이때 trackList 를 사용하는데 이는 추후 Track 를 설명하면서 한번 더 설명하도록 하겠다.
- 참고로 selectMusic 의 true 는 loop 여부를 의미하며, game 부분은 해당 음악이 게임 음악인지 아니면 배경 음악인지를 확인하기 위한 매개변수이다.
- selectLeft는 왼쪽 버튼에 해당하는 메소드이다.
- 이때 nowSelect 가 0 일 때 즉 index 가 0 일때 즉 List의 첫번째일때는 왼쪽 버튼을 누르면 전체 trackList 의 전체 크기-1 번째 곡을 선택한다. ArrayList 에서 전체크기-1 이란 List의 마지막 index 를 의미하며 이는 즉 마지막 곡을 가져오는 것이다.
- 만약 index 가 0 이 아닌 경우 왼쪽 버튼을 누르면 인덱스-1 해서 하나 전 노래를 선택한다.
- selectRight 는 오른쪽 버튼에 해당하는 메소드이다.
- 사실 Left 메소드와 비슷하다. 다만 Right 버튼은 List-1 번째 인덱스, 즉 마지막 인덱스인 경우 오른쪽 버튼을 누르면 리스트의 첫번째인 0 으로 돌아간다.
- 만약 마지막 인덱스, 마지막 곡이 아닌 경우 현재 인덱스에서 +1 한다.
// 현재 선택된 곡의 번호를 넣어줌으로써 해당 곡이 선택됨을 알림
public void selectTrack(int nowSelected) {
// 선택한 곡이 null 이 아니면 , 즉 어떠한 곡이라도 하나가 실행되고 있다면 해당 음악을 종료
if (selectedMusic != null) {
selectedMusic.close();
}
// 현재 선택된 곡이 갖고 있는 noewSelected 번호를 갖고 아래의 각 정보를 가져옴
// 예를 들어서 arraylist 의 index 가 1이면 1에 해당하는 title, start, music 를 가져와서 뿌려줌
titleImage = new ImageIcon(getClass().getResource("/game_images/" +
trackList.get(nowSelected).getTitleImage())).getImage();
selectedImage = new ImageIcon(getClass().getResource("/game_images/" +
trackList.get(nowSelected).getMenuImage())).getImage();
selectedMusic = new Music(trackList.get(nowSelected).getStartMusic(), true, "game");
selectedMusic.start();
}
// 왼쪽 버튼 메서드
public void selectLelft() {
// 0번째 곡일때는 전체 trackList 크기에서 -1 한다.
// 이는 0번째 곡일때 왼쪽을 누르면 track 에 있는 마지막 곡이 나오게 됨
if (nowSelected == 0) {
nowSelected = trackList.size() - 1;
} else { // 가장 왼쪽 아닐때는 현재 nowSelected 에서 -1
nowSelected--;
}
selectTrack(nowSelected);
}
// 오른쪽 버튼 메서드
public void selectRight() {
// 현재 곡이 track 의 가장 오른쪽에, 즉 마지막에 있는 곡이라면
// 가장 처음으로 돌아가도록
if (nowSelected == trackList.size() - 1) {
nowSelected = 0;
} else { // 가장 오른쪽이 아닌 경우는 +1
nowSelected++;
}
selectTrack(nowSelected);
}
6) Game Start 메소드
- Game Start 메소드는 말 그대로 게임을 시작하는 메소드이다.
- 이 메소드 안에서 track.get 을 통해서 현재 index 번호에 맞는 titleName, 난이도 , gameMusic, IngameImage 를 가져온 후 game 객체를 생성한다. 이후 (Tread 를 상속받은)game 안에 있는 Tread 를 시작 - start - 하게 된다.
- 이때 isMainScreen 은 false, isGameScreen 은 true 로 두어 게임 메뉴에서 실제 게임 화면으로 전환을 확인해준다. 또한 게임 화면을 전환해두었기 때문에 left, right, easy, hard 버튼은 보이지 않게 해둔다. 또한 back 버튼 뒤로가기 버튼을 보이게 해둔다.
- 마지막으로 combo 와 score 를 0 으로 초기화해둔다.
public void gameStart(int nowSelected, String difficulty) {
// 현재 재생되고 있는 음악이 있다면 음악 종료
if (selectedMusic != null) {
selectedMusic.close();
}
// 메인 스크린을 false 로 => 이렇게되면 screenDraw 함수에서 isMainScreen 부분을 멈추게됨
isMainScreen = false;
// Ingame 전환 확인
isGameScreen = true;
// 게임 시작 시 해당 선택된 곡 이름과 난이도 가져옴
game = new Game(trackList.get(nowSelected).getTitleName(), difficulty, trackList.get(nowSelected).getGameMusic());
// game 인스턴스 안에 있는 run 함수 실행
game.start();
// 버튼 안보이게
leftButton.setVisible(false);
rightButton.setVisible(false);
easyButton.setVisible(false);
hardButton.setVisible(false);
// 뒤로 돌아가기 버튼
backButton.setVisible(true);
// 백그라운드 이미지가 ingame 이미지로 바뀌어야함
Background = new ImageIcon(getClass().getResource("/game_images/"+trackList.get(nowSelected).getIngameImage())).getImage();
// 노트 찍기 모드 일때는 해당 이미지 추가
// noteMaker = true 일 때만 버튼 보이게
if(Game.noteMaker) {
noteWriteButton.setVisible(true);
}
// 게임 시작 시 점수 & 콤보 초기화
Game.combo = 0;
Game.score = 0;
// 키보드 이벤트 동작을 위한 메서드
// 이는 Main 클래스에 포커스가 맞춰져있어야 키보드 이벤트가 정상적으로 동작하기 때문
setFocusable(true);
requestFocus();
}
7) game_menu 와 bakMain 메소드
- game menu 와 bakMain 메소드는 각각 시작하기 버튼을 눌렀을 때 즉 노래 선택 게임 화면으로 들어갔을 때 실행되는 기능과 뒤로가기 버튼을 눌렀을 때 노래 선택 게임 화면으로 왔을 때 실행되는 메소드이다.
- 그렇기 때문에 안에 있는 코드가 비슷한데 먼저 Background 를 통해 메뉴로 왔을 때 배경화면을 바뀌게 해준다. 또한 필요한 버튼을 보이게 하고, index 0 번째 노래를 선택한다.
- 중요한 부분은 game menu 로 왔을 때 intromusic.close 해서 - 인트로 음악을 종료 해주는 부분과 게임 도중 뒤로가기 버튼을 눌러서 뒤로 왔을 때 game.close 해서 게임을 종료해주는 부분이다.
public void game_menu(){
// 시작, 종료버튼 없애기
startButton.setVisible(false);
quitButton.setVisible(false);
// 여기는 게임 메인 화면에 들어갔을 때 배경화면
Background = new ImageIcon(getClass().getResource("/menu_images/main_Bakground.jpg")).getImage();
// 게임 시작을 누르면 isMainScreen 을 true 로
isMainScreen = true;
// left 와 right 버튼이 보이기
leftButton.setVisible(true);
rightButton.setVisible(true);
// 난이도 버튼 표시
easyButton.setVisible(true);
hardButton.setVisible(true);
// nowselected 번째 index 재생
selectTrack(0);
// 인트로 음악 종료
Intromusic.close();
}
public void bakMain(){
// 메인 화면일때는 isMainScreen 이 true, GameScreen 은 false
isMainScreen = true;
isGameScreen = false;
// 메인화면으로 돌아오면 다시 버튼 보이게
leftButton.setVisible(true);
rightButton.setVisible(true);
easyButton.setVisible(true);
hardButton.setVisible(true);
// 뒤로 돌아가기 버튼
backButton.setVisible(false);
// 노트 찍기 버튼
if(Game.noteMaker){
noteWriteButton.setVisible(false);
}
// 다시 트랙 선택
selectTrack(nowSelected);
// 백그라운드 이미지가 track 의 nowSelected 에 맞는 이미지로
Background = new ImageIcon(getClass().getResource("/menu_images/main_Bakground.jpg")).getImage();
// 메뉴로 돌아왔을 때 게임 종료
game.Close();
}
참고 사이트
- 저작권 없는 무료 배경 이미지
- 배경 이미지 제거
https://www.remove.bg/ko/upload
- mp3 음악 수정
'토이 프로젝트 > Spring&Java 갖고놀기' 카테고리의 다른 글
자바 리듬 게임 만들기(3) (0) | 2022.03.22 |
---|---|
자바 리듬 게임 만들기 (2) : Game(feat. 노트찍기모드) (0) | 2022.03.21 |
Spring - DB 구조 변경 및 회원가입 스크립트 수정 (0) | 2022.02.25 |
회원가입 시 아이디 중복 체크(feat. ajax, json) (0) | 2022.02.13 |
spring - DB + 메일 서버 + 웹페이지 연동하기(feat. 회원 가입 후 메일 계정 자동 생성) (0) | 2022.01.31 |
댓글