Obsługa biblioteki JBFMod: Różnice pomiędzy wersjami
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 | + | [[Kategoria:Artykuły dla zaawansowanych]] |
Aktualna wersja na dzień 12:48, 12 lis 2006
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.
Spis treści
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 .