본문 바로가기

개인프로젝트/DJ Technician

DJ_Technician 자바 리듬게임 만들기 근황

메트로놈을 만드는데 성공했다.


bpm과 bms등을 공부하면서 게임제작과정이 애초에 잘못했다는 것을 깨달았다..

곡의 리듬에 맞게 정확하게 노트나 박자를 세면서 아래로 스크롤하는 것이 핵심이자 어려운 과제였다.


단순히 노트를 떨구는 것이 아니라 박자에 맞게 정해진 타이밍에 판정바에 도달하도록 거리를 조정해야 후에

배속조절 등이 가능해진다. 우선 곡의 bpm에 대한 정보를 얻으면 정확한 박자를 체크하는 것 부터 다시시작했는데

생각보다 쉽지않았다.


DJMAX게임의 SIN 이라는 곡(어릴적 즐겨 플레이 했던곡이다..)

곡의 bpm은 190으로 1분당 190번의 비트를 뜻한다.



즉 60 / 190 을 해주면 대략 0.315789473... 초에 한번씩 비트를 잡아야한다.

간단할줄 알았으나 곡이 진행되면서 소수점 계산오차들이 누적되니 무시할 수 없는 수준으로 

비트가 곡보다 빨라지거나 느려졌다. 


처음에 0.31578...초가 누적될때마다 비트를 표시하는 방법을 썼는데 이는 소수점 계산오차역시 누적되게된다.


----해결방법----

targetTime = ( 60.0 / bpm) * 1000;          // 목표시간(315.789473....) double

countTarget = 1;                               // 비트누적카운터

음악재생 bgm.start();

startTimer = System.nanoTime();

while(반복){

// 0.001초 이하 단위는 버리고 curTimer로 시작후에 끊임없이 진행시간 누적.

curTimer = (System.nanoTime() - startTimer) / 1000000;


// 핵심코드 : 현재 진행시간(curTimer)에 맞춰서 (targetTime*countTarget) 으로 나눠준다.

getTime = (int)( curTimer / (targetTime * countTarget) ) ;

/*

즉 targetTime 은 315.789473.... 으로 일정하고

비트가 연주되면서 목표시간은

631.57894...

947.368421052...

1263.15789473....

1578.947368421...

으로 계속 갱신된다. 그리고 현재시간으로 갱신된 시간으로 나눠주면서

그 몫이 1이되는 최초 타이밍이 발생할때 if(getTime == 1) 일때 비트가 발동되고

다음 목표시간을 늘린다.


이방법은 현재 곡의 진행시각에 비례해서 연주타이밍을 끊임없이 곱셈 계산하므로 곡이

진행되어도 소수점과 루프가 진행되면서 발생하는 계산시간에 의해 발생하는 차이가 누적되지 않고

연주가 끝날때까지 동일한 비트로 진행된다.


*/



// 

if(getTime == 1){

drumbeat.start(); //드럼소리 연주 등등 비트표시

drumbeat = new Bgm("drum.mp3", false);

countTarget++;   //이번 비트를 연주했으면 타겟카운트를올려서 다음 연주시간을 측정

}



}

---------------



테스트하면서 이제 찾은 방법이라 좀더 다듬으면 세부적인 계산도 더 정밀하게 가능할 것 같다.

우선 javazoom.JLayer 를 통해 mp3를 재생하고 있는데 곡의 시작시간과 타이머의 시작시간에

미세한 오차가 있다. JLayer 내부 Player 클래스에 별도로 Player.getPosition() 메서드로 곡의 진행시간을

구할 수가 있는데(영상에서 제밀 밑에 숫자) 타이머의 시작시간대신 getPosition()함수를

위의 curTimer 대신 넣었더니 getPosition 이 제대로 작동을 안하는 문제가 있다.


영상기준 아래에서 3번째 숫자가 타이머 진행시간인데 밑 밑에숫자인 getPosition으로 구한 곡의 시작시간과

미세한 차이가 있음을 알 수 있다. curTimer대신 쓰면 될거라생각했는데 getPosition을 다른 계산식 안에

넣어서 활용하면 함수가 제대로 작동안하고 0만 출력한다... 이부분만 해결하면 곡의 시작타이밍과 일치하게

박자를 정확히 카운트할 수 있을 듯.



추후 이 박자를 기반으로해서 마디가 내려오는 위치값을 구하고 마디위치를 기준으로 노트 위치계산식을

만들 수 있을 것같다.