Obsługa biblioteki JBFMod: Różnice pomiędzy wersjami

Klikipedia - klikowa encyklopedia
Skocz do: nawigacji, wyszukiwarki
m
 
Linia 289: Linia 289:
 
[[Kategoria:Kursy i tutoriale]]
 
[[Kategoria:Kursy i tutoriale]]
 
[[Kategoria:Kursy i tutoriale dla użytkowników GM]]
 
[[Kategoria:Kursy i tutoriale dla użytkowników GM]]
[[Kategoria:Artykuły dla zaawasowanych]]
+
[[Kategoria:Artykuły dla zaawansowanych]]

Aktualna wersja na dzień 12:48, 12 lis 2006

Autor.jpg
Autorem tego artykułu jest
Jakim

Biblioteka JBFMod pozwala w Game Makerze na odtwarzanie modułów muzycznych - czyli modów, xmów i innych plików muzycznych w podobnym formacie. Zanim jednak przystąpimy do obsługi, dodam, że musimy najpierw zdobyć biblioteki jbfmod.dll i fbmod.dll, które są niezbędnę nam do działania. Dobrze, teraz już można zabrać się za kod.

Inicjalizacja

W głównym obiekcie na planszy, niech to będzie obj_mod musimy przywołać listę poleceń biblioteki w CREATE. Jest ich dosyć sporo, więc najlepiej przekopiować żywcem kod i nie robić sobie problemów z przepisaniem .

DLL='jbfmod.dll' //wywolujemy biblioteke 
tp=dll_cdecl  

//lista polecen 
JBFMODClose=external_define(DLL,'Close',tp,ty_real,0) 
JBFMODCloseSpectrum=external_define(DLL,'CloseSpectrum',tp,ty_real,0) 
JBFMODGetBPM=external_define(DLL,'GetBPM',tp,ty_real,0) 
JBFMODGetChannelsPlaying=external_define(DLL,'GetChannelsPlaying',tp,ty_real,0) 
JBFMODGetCPUUsage=external_define(DLL,'GetCPUUsage',tp,ty_real,0) 
JBFMODGetCurrentSong=external_define(DLL,'GetCurrentSong',tp,ty_real,0) 
JBFMODGetErrorCode=external_define(DLL,'GetErrorCode',tp,ty_real,0) 
JBFMODGetErrorMessage=external_define(DLL,'GetErrorMessage',tp,ty_string,0) 
JBFMODGetFrequency=external_define(DLL,'GetFrequency',tp,ty_real,1,ty_real) 
JBFMODGetJBInfo=external_define(DLL,'GetJBInfo',tp,ty_string,1,ty_real) 
JBFMODGetInstrumentPlayed=external_define(DLL,'GetInstrumentPlayed',tp,ty_real,1,ty_real) 
JBFMODGetInstrumentPlayedOnce=external_define(DLL,'GetInstrumentPlayedOnce',tp,ty_real,1,ty_real) 
JBFMODGetMasterVolume=external_define(DLL,'GetMasterVolume',tp,ty_real,0) 
JBFMODGetName=external_define(DLL,'GetName',tp,ty_string,1,ty_real) 
JBFMODGetNumChannels=external_define(DLL,'GetNumChannels',tp,ty_real,1,ty_real) 
JBFMODGetNumInstruments=external_define(DLL,'GetNumInstruments',tp,ty_real,1,ty_real) 
JBFMODGetNumOrders=external_define(DLL,'GetNumOrders',tp,ty_real,1,ty_real) 
JBFMODGetNumPatterns=external_define(DLL,'GetNumPatterns',tp,ty_real,1,ty_real) 
JBFMODGetNumSamples=external_define(DLL,'GetNumSamples',tp,ty_real,1,ty_real) 
JBFMODGetOrder=external_define(DLL,'GetOrder',tp,ty_real,0) 
JBFMODGetPackInfo=external_define(DLL,'GetPackInfo',tp,ty_string,0) 
JBFMODGetPattern=external_define(DLL,'GetPattern',tp,ty_real,0) 
JBFMODGetPatternLength=external_define(DLL,'GetPatternLength',tp,ty_real,0) 
JBFMODGetPaused=external_define(DLL,'GetPaused',tp,ty_real,0) 
JBFMODGetRow=external_define(DLL,'GetRow',tp,ty_real,0) 
JBFMODGetSongExists=external_define(DLL,'GetSongExists',tp,ty_real,1,ty_real) 
JBFMODGetSpectrum=external_define(DLL,'GetSpectrum',tp,ty_real,1,ty_real) 
JBFMODGetSpectrumMean=external_define(DLL,'GetSpectrum',tp,ty_real,2,ty_real,ty_real) 
JBFMODGetSpeed=external_define(DLL,'GetSpeed',tp,ty_real,0) 
JBFMODGetTime=external_define(DLL,'GetTime',tp,ty_real,0) 
JBFMODGetTimeFormat=external_define(DLL,'GetTimeFormat',tp,ty_string,0) 
JBFMODGetType=external_define(DLL,'GetType',tp,ty_real,1,ty_real) 
JBFMODGetZxx=external_define(DLL,'GetZxx',tp,ty_real,0) 
JBFMODGetZxxPlayed=external_define(DLL,'GetZxxPlayed',tp,ty_real,1,ty_real) 
JBFMODGetZxxPlayedOnce=external_define(DLL,'GetZxxPlayedOnce',tp,ty_real,1,ty_real) 
JBFMODGetZxxOnce=external_define(DLL,'GetZxxOnce',tp,ty_real,0) 
JBFMODInit=external_define(DLL,'Init',tp,ty_real,2,ty_real,ty_real) 
JBFMODInitSpectrum=external_define(DLL,'InitSpectrum',tp,ty_real,0) 
JBFMODIsFinished=external_define(DLL,'IsFinished',tp,ty_real,0) 
JBFMODIsPlaying=external_define(DLL,'IsPlaying',tp,ty_real,0) 
JBFMODLoadSong=external_define(DLL,'LoadSong',tp,ty_real,2,ty_real,ty_string) 
JBFMODLoadSongPack=external_define(DLL,'LoadSongPack',tp,ty_real,3,ty_real,ty_real,ty_string) 
JBFMODPlaySong=external_define(DLL,'PlaySong',tp,ty_real,1,ty_real) 
JBFMODSetLooping=external_define(DLL,'SetLooping',tp,ty_real,1,ty_real) 
JBFMODSetMasterVolume=external_define(DLL,'SetMasterVolume',tp,ty_real,1,ty_real) 
JBFMODSetOrder=external_define(DLL,'SetOrder',tp,ty_real,1,ty_real) 
JBFMODSetPanSeperation=external_define(DLL,'SetPanSeperation',tp,ty_real,1,ty_real) 
JBFMODSetPaused=external_define(DLL,'SetPaused',tp,ty_real,1,ty_real) 
JBFMODStopSong=external_define(DLL,'StopSong',tp,ty_real,0) 

UWAGA! Aby biblioteka była dostępna dla wszystkich obiektów, przed każdym poleceniem należy dać przedrostek global, np.

global.JBFMODClose=external_define(DLL,'Close',tp,ty_real,0)

Nie będę omawiał szczegółów działania każdego tego polecenia, ponieważ zjadłoby mi to dużo miejsca, a wam - czasu.

Zaraz po tym kodzie musimy zainicjować JBFModa. Robimy to też w CREATE, zaraz po przywołaniu biblioteki.

result=external_call(JBFMODInit,3,512)  
return(external_call(JBFMODSetMasterVolume,100))

Używanie komend JMFModa będzie wyglądać mniej więcej tak:

external_call(nazwa komendy, parametr1, parametr2...) 

Część właściwa

Aby przetestować działanie bibloteki, musimy mieć dowolny mod. Niech będzie to muzyczka.xm (musi być w katalogu z grą. Jeżeli jej nie mamy - ściągnijcie jakąś ze strony z modami, np. http://www.modules.pl/, http://www.modulez.org/ lub http://www.modarchive.com/ i nazwijcię ją muzyczka.xm). Dodajmy ją do kodu, również w CREATE:

muzyczka[1]=working_directory+'\muzyczka.xm'

Jedynka w nawiasie oznacza numer muzyki. W przyszłości można dodawać też inne pozycje, np. muzyczka[2], muzyczka[3]... itd. I jeszcze jedno: skrypt ten trzeba umieścić na samym początku, inaczej zmienna się nie zainicjuje.

Okej. Teraz dodajmy skrypt odtwarzania. Niech będzie nazywać się play_song:

external_call(JBFMODLoadSong,argument0,muzyczka[argument0]) 
external_call(JBFMODStopSong) 
external_call(JBFMODPlaySong,argument0)

Co to jest ten argument? Już wyjaśniam: argument0 to numer muzyczki. Aby odtworzyć piosenkę możemy teraz wpisać tylko jedną linię kodu, a będzie nią:

play_song(tutaj numer muzyczki)

Proste? Mam nadzieję . Zróbmy, że po wciśnięciu klawisza X odtwarzana jest melodia. Nic prostszego. Kod dajemy już w STEPIE:

if keyboard_check(ord('X')) 
{ 
 play_song(1) //odtwarzamy muzyczke 1 
}

Tak mniej więcej odtwarza się piosenki. Teraz dodajmy możliwość pauzy. Stwórzmy skrypt pause:

external_call(JBFMODSetPaused,1-external_call(JBFMODGetPaused))

Pewnie się zastanawiacie, po co dałem 1-external_call(JBFMODGetPaused). Otóż pauza w bibliotece jest albo włączona (1), albo wyłączona (0). Jeżeli jest wyłączona, zgodnie z kodem pauza zostaje ustawiona na włączoną (1-0=1) i vice versa (1-1=0). Dlatego ten kod działa dwustronnie (pauzuje i odpauzowywuje).

Poruszanie się po playliście

Spróbujmy teraz czegoś trudniejszego. Niech po naciśnięciu klawisza Z piosenka przesuwa się o 1 pattern. Stwórzmy kolejny skrypt: next_order:

var order; //tworzymy zmienna 'order' 
order=external_call(JBFMODGetOrder) //ustawiamy order na aktualny pattern 

if external_call(JBFMODIsPlaying) 
{ 
  if order<external_call(JBFMODGetNumOrders,argument0) //jesli order nie jest ostatni w muzyczce 'x' 
  { 
    external_call(JBFMODSetOrder,order+1) //ustawiamy aktualny pattern na order+1 
  } 
}

Wywołujemy go klawiszem Z. Przechodzimy zatem do STEPU:

if keyboard_check_pressed(ord('Z')) 
{ 
  next_order(1) //dodajemy 1 do orderu w muzyczce 1 
} 

Możemy to samo zrobić z przesuwaniem do tyłu. Tworzymy więc następny skrypt, previous_order:

var order; //tworzymy zmienna 'order' 

order=external_call(JBFMODGetOrder) //ustawiamy order na aktualny pattern 

if external_call(JBFMODIsPlaying) 
{ 
  if order>0 //jesli order nie jest pierwszy w muzyczce 
  { 
    external_call(JBFMODSetOrder,order-1) //ustawiamy aktualny pattern na order-1 
  } 
}

Niech będzie wywoływany klawiszem C w STEPIE:

if keyboard_check_pressed(ord('C')) 
{ 
  previous_order(1) 
}

Piosenka po końcu się nie zapętla. Zmieńmy to. I znowu przechodzimy do STEPU, tym razem modyfikujemy kod z play_song. Po zmodyfikowaniu będzie wyglądać tak:

if keyboard_check_pressed(ord('X')) or external_call(JBFMODIsFinished,1) 
{ 
  play_song(1) 
}

Licznik procentowy

Jesteśmy wybredni i chcemy stworzyć liczik procentowy . Robimy to, pobierając wartości z modułu w DRAW. Musimy też zainicjować zmienną bar w CREATE na samym początku,.

if external_call(JBFMODIsPlaying) //jesli mod jest odtwarzany 
{ 
  bar=external_call(JBFMODGetOrder)/external_call(JBFMODGetNumOrders,1) /*bar 

wynosi L/O, gdzie L to jest aktualny pattern, a O - calkowita liczba patternow*/

} 

draw_text(12,12,string(100*bar)+'%') //rysujemy tekst: wartość licznika*100 + "%"

Jak sami widzimy, licznik ten nie jest dokładny - chodzi skokowo. Musimy więc zmodyfikować nasz skrypt. Będzie to trochę skomplikowane:

if external_call(JBFMODIsPlaying) //jesli mod jest odtwarzany 
{ 
  bar=external_call(JBFMODGetOrder)/external_call(JBFMODGetNumOrders,1) 
  bar+=external_call(JBFMODGetRow)/(external_call(JBFMODGetPatternLength)*external_call(JBFMODGetNumOrders,1)) 
/*zmienna bar wynosi L/O, gdzie L to jest aktualny pattern, a O - calkowita liczba patternow. 
Pozniej dodawany jest iloraz aktualnego rowa przez iloczyn dlugosci patternu i ogolnej ilosci patternow*/ 
} 

draw_text(12,12,string(100*bar)+'%') //rysujemy tekst: wartość licznika*100 + "%"

Ten licznik też nie jest idealny (przy niektórych utworach może się cofać lub pomijać niektóre procenty, czasami może też chodzić szybciej - ale to już zależy od utworu, nie ode mnie ), ale jest dokładniejszy od poprzedniego, bo uwzględnia także pozycję pojedynczego rowa.

Na razie to tyle. Na końcu dajemy wyjście w STEPIE:

if keyboard_check(vk_escape) 
{ 
  external_call(JBFMODStopSong) //zatrzymaj piosenke 
  external_call(JBFMODClose) //wylacz biblioteke 
  game_end(); 
}

Jeżeli chcemy mieć wyjście za pomocą klawisza, w preferencjach musimy zatem wyłączyć wychodzenie z gry ESCAPE'em.

Zakończenie

To już koniec tego artykułu. Mam nadzieję, że umiesz już częściowo obsługę JBFModa. Nie przerażaj się innymi komendami - są one jasne i klarowne (przynajmniej jeśli znasz angielski ). Doświadczeni użytkownicy potrafią zrobić dodatkowo proste wizualizacje dzięki JBFModzie, ale nie będę na razie straszyć zaawansowanymi funkcjami . Aby poznać więcej możliwości tej biblioteki, odsyłam was na stronę www.gamemaker.nl - w dziale "Resources" znajduje się odtwarzacz zrobiony na podstawie tej biblioteki, którego warto przestudiować.

Jeszcze tylko przypomnę, co powinno się znaleźć w CREATE:

muzyczka[1]=working_directory+'\muzyczka.xm' 
bar=0 
DLL='jbfmod.dll' //wywolujemy biblioteke 
tp=dll_cdecl 

//lista polecen 
JBFMODClose=external_define(DLL,'Close',tp,ty_real,0) 
JBFMODCloseSpectrum=external_define(DLL,'CloseSpectrum',tp,ty_real,0) 
JBFMODGetBPM=external_define(DLL,'GetBPM',tp,ty_real,0) 
JBFMODGetChannelsPlaying=external_define(DLL,'GetChannelsPlaying',tp,ty_real,0) 
JBFMODGetCPUUsage=external_define(DLL,'GetCPUUsage',tp,ty_real,0) 
JBFMODGetCurrentSong=external_define(DLL,'GetCurrentSong',tp,ty_real,0) 
JBFMODGetErrorCode=external_define(DLL,'GetErrorCode',tp,ty_real,0) 
JBFMODGetErrorMessage=external_define(DLL,'GetErrorMessage',tp,ty_string,0) 
JBFMODGetFrequency=external_define(DLL,'GetFrequency',tp,ty_real,1,ty_real) 
JBFMODGetJBInfo=external_define(DLL,'GetJBInfo',tp,ty_string,1,ty_real) 
JBFMODGetInstrumentPlayed=external_define(DLL,'GetInstrumentPlayed',tp,ty_real,1,ty_real) 
JBFMODGetInstrumentPlayedOnce=external_define(DLL,'GetInstrumentPlayedOnce',tp,ty_real,1,ty_real) 
JBFMODGetMasterVolume=external_define(DLL,'GetMasterVolume',tp,ty_real,0) 
JBFMODGetName=external_define(DLL,'GetName',tp,ty_string,1,ty_real) 
JBFMODGetNumChannels=external_define(DLL,'GetNumChannels',tp,ty_real,1,ty_real) 
JBFMODGetNumInstruments=external_define(DLL,'GetNumInstruments',tp,ty_real,1,ty_real) 
JBFMODGetNumOrders=external_define(DLL,'GetNumOrders',tp,ty_real,1,ty_real) 
JBFMODGetNumPatterns=external_define(DLL,'GetNumPatterns',tp,ty_real,1,ty_real) 
JBFMODGetNumSamples=external_define(DLL,'GetNumSamples',tp,ty_real,1,ty_real) 
JBFMODGetOrder=external_define(DLL,'GetOrder',tp,ty_real,0) 
JBFMODGetPackInfo=external_define(DLL,'GetPackInfo',tp,ty_string,0) 
JBFMODGetPattern=external_define(DLL,'GetPattern',tp,ty_real,0) 
JBFMODGetPatternLength=external_define(DLL,'GetPatternLength',tp,ty_real,0) 
JBFMODGetPaused=external_define(DLL,'GetPaused',tp,ty_real,0) 
JBFMODGetRow=external_define(DLL,'GetRow',tp,ty_real,0) 
JBFMODGetSongExists=external_define(DLL,'GetSongExists',tp,ty_real,1,ty_real) 
JBFMODGetSpectrum=external_define(DLL,'GetSpectrum',tp,ty_real,1,ty_real) 
JBFMODGetSpectrumMean=external_define(DLL,'GetSpectrum',tp,ty_real,2,ty_real,ty_real) 
JBFMODGetSpeed=external_define(DLL,'GetSpeed',tp,ty_real,0) 
JBFMODGetTime=external_define(DLL,'GetTime',tp,ty_real,0) 
JBFMODGetTimeFormat=external_define(DLL,'GetTimeFormat',tp,ty_string,0) 
JBFMODGetType=external_define(DLL,'GetType',tp,ty_real,1,ty_real) 
JBFMODGetZxx=external_define(DLL,'GetZxx',tp,ty_real,0) 
JBFMODGetZxxPlayed=external_define(DLL,'GetZxxPlayed',tp,ty_real,1,ty_real) 
JBFMODGetZxxPlayedOnce=external_define(DLL,'GetZxxPlayedOnce',tp,ty_real,1,ty_real) 
JBFMODGetZxxOnce=external_define(DLL,'GetZxxOnce',tp,ty_real,0) 
JBFMODInit=external_define(DLL,'Init',tp,ty_real,2,ty_real,ty_real) 
JBFMODInitSpectrum=external_define(DLL,'InitSpectrum',tp,ty_real,0) 
JBFMODIsFinished=external_define(DLL,'IsFinished',tp,ty_real,0) 
JBFMODIsPlaying=external_define(DLL,'IsPlaying',tp,ty_real,0) 
JBFMODLoadSong=external_define(DLL,'LoadSong',tp,ty_real,2,ty_real,ty_string) 
JBFMODLoadSongPack=external_define(DLL,'LoadSongPack',tp,ty_real,3,ty_real,ty_real,ty_string) 
JBFMODPlaySong=external_define(DLL,'PlaySong',tp,ty_real,1,ty_real) 
JBFMODSetLooping=external_define(DLL,'SetLooping',tp,ty_real,1,ty_real) 
JBFMODSetMasterVolume=external_define(DLL,'SetMasterVolume',tp,ty_real,1,ty_real) 
JBFMODSetOrder=external_define(DLL,'SetOrder',tp,ty_real,1,ty_real) 
JBFMODSetPanSeperation=external_define(DLL,'SetPanSeperation',tp,ty_real,1,ty_real) 
JBFMODSetPaused=external_define(DLL,'SetPaused',tp,ty_real,1,ty_real) 
JBFMODStopSong=external_define(DLL,'StopSong',tp,ty_real,0)  

result=external_call(JBFMODInit,3,512) 
return(external_call(JBFMODSetMasterVolume,100))

W STEPIE:

if keyboard_check_pressed(ord('X')) or external_call(JBFMODIsFinished,1) 
{ 
  play_song(1) 
} 

if keyboard_check_pressed(ord('S')) 
{ 
  pause() 
} 

if keyboard_check_pressed(ord('Z')) 
{ 
  next_order(1) 
} 

if keyboard_check_pressed(ord('C')) 
{ 
  previous_order(1) 
}

DRAW:

if external_call(JBFMODIsPlaying) //jesli mod jest odtwarzany 
{ 
  bar=external_call(JBFMODGetOrder)/external_call(JBFMODGetNumOrders,1) 
  bar+=external_call(JBFMODGetRow)/(external_call(JBFMODGetPatternLength)*external_call(JBFMODGetNumOrders,1)) 
/*zmienna bar wynosi L/O, gdzie L to jest aktualny pattern, a O - calkowita liczba patternow. 
Pozniej dodawany jest iloraz aktualnego rowa przez iloczyn dlugosci patternu i ogolnej ilosci patternow*/ 
} 

draw_text(12,12,string(100*bar)+'%') //rysujemy tekst: wartość licznika*100 + "%"

W skrypcie play_song:

external_call(JBFMODLoadSong,argument0,muzyczka[argument0]) 
external_call(JBFMODStopSong) 
external_call(JBFMODPlaySong,argument0)

W skrypcie pause:

external_call(JBFMODSetPaused,1-external_call(JBFMODGetPaused))

I w skrypcie next_order:

var order; //tworzymy zmienna 'order'  

order=external_call(JBFMODGetOrder) //ustawiamy order na aktualny pattern 

if external_call(JBFMODIsPlaying) 
{ 
  if order<external_call(JBFMODGetNumOrders,argument0) //jesli order nie jest ostatni w muzyczce 'x' 
  { 
    external_call(JBFMODSetOrder,order+1) //ustawiamy aktualny pattern na order+1 
  } 
}

Następnie w skrypcie previous_order:

var order; //tworzymy zmienna 'order'  

order=external_call(JBFMODGetOrder) //ustawiamy order na aktualny pattern  

if external_call(JBFMODIsPlaying) 
{ 
  if order>0 //jesli order nie jest pierwszy w muzyczce 
  { 
    external_call(JBFMODSetOrder,order-1) //ustawiamy aktualny pattern na order-1 
  } 
} 

Pozdrawiam i życzę miłej obsługi nowo poznanej biblioteki .