Ten artykuł został stworzony dla starszych wersji GameMakera i może nie być aktualny.

Zaawansowana obsługa sprite'ów

Sobota, 11 Września 2004, 23:06
Czas czytania 4 minuty, 22 sekundy
Zgodne z GM: gm5 gm6
Ten tutorial ukazuje fajny sposób wczytywania grafiki z osobnych plików, ale takich z utrudnionym odczytem dla zwykłego wyjadacza. ;)
Pewnego dnia, rozmyślając nad kolejnym projektem, zacząłem zastanawiać się nad wczytywaniem grafiki z osobnych plików, cel: osiągnięcie jak najmniejszego rozmiaru exe (tak by mieścił w sobie tylko interpreter gm'a, skrypty oraz parę podstawowych grafik), tak by nie było potem kłopotu z ewentualnym patch'owaniem. Po drugie chodziło o to by mając przykładowo animacje chodzenia ludzika w prawo, nie kopiować jej z "mirrorem", lecz aby podczas wczytywania gry skrypt sam utworzył odpowiednią animację w lewo. Najlepszym sposobem do osiągnięcia tego jest trzymanie grafiki w formie "strip'a" i to jako GIF z optymalną paletą kolorów. Taki plik naprawdę mało zajmuje.

Plany trzeba było wprowadzić w życie i ... udało się :). Opiszę kolejno fazy tworzenia specjalnej funkcji - skryptu oraz grafiki.

Przykładowy dwuklatkowy strip w formacie gif:
Grafika: upload/screens/articles/shyguy.gif

Taką grafikę jest łatwo przygotować. Wystarczy animację zapisać w formie stripa jako bmp, a następnie go wczytać jako jedna klatka i teraz zapisać jako gif. Trzeba jeszcze w innym edytorze graficznym zoptymalizować paletę kolorów w celu zmniejszenia wielkości pliku.

Zapisujemy tak przygotowanego stripa do katalogu z grą, a najlepiej utwórzmy katalog data i tam wrzućmy plik. Teraz czas utrudnić odczyt pliku przed wścipskimi osobami. W tym celu zmieniamy rozszerzenie z gif na gfx. To nie wszystko... zmienimy parę pierwszych bajtów pliku, by nie był on czytelny po zmianie rozszerzenia. Dla niedoinformowanych, w GM 5.3 zarejestrowanej wersji dostępne są funkcje do binarnej obsługi plików. Aby zmienić te bajty będziemy musieli napisać specjalny konwerter w GM lub użyć jakiegoś hex edytora. Polecam drugą opcję, osobiście korzystam z bardzo dobrego programu XVI32 i to na jego przykładzie opiszę zmianę bajtów. Otwieramy plik graficzny w tymże programie.

Widzimy:
Grafika: upload/screens/articles/xvi1.gif

Hmmm... Zamieńmy GIF89a na ISTRIP:
Grafika: upload/screens/articles/xvi2.gif

Teraz czas na napisanie funkcji. Tworzymy nowy skrypt o nazwie sc_LoadSprite:
kod/*
Advanced sprite loader by Ranma_man
arg0 - nazwa pliku (string)
arg1 - transparent (0 - nie , 1 - tak)
arg2 - liczba klatek animacji (liczba)
arg3 - pozycja startowa (liczba pominietych klatek)
arg4 - szerokosc pojedynczej klatki animacji
arg5 - wysokosc pojedynczej klatki animacji
arg6 - Przesuniecie poziomie (liczba pikseli)
arg7 - Przesuniecie pionowe (liczba pikseli)
arg8 - Inne opcje (1 - mirror, 2 - flip, 3 - mirror i flip)
arg9 - Obrot w stopniach (obrot calej animacji)
*/

var on,nn,fh,sh,i,spr; //Stworz tymczasowe zmienne


/* Rozpoznaj plik */
on = 'data' + argument0 + '.gfx';

/* Mmien na chwile rozszerzenie by GM mogl odczytac grafike */
nn = filename_change_ext( on , '.gif' );

/* Kopiuj plik tymczasowo, by nie operowac na oryginale */
file_copy( on , nn );

/* Zmien na plik na czytelny GIF zmieniajac ISTRIP na GIF */
fh = file_bin_open(nn,1);
file_bin_write_byte(fh,71);
file_bin_seek(fh,1);
file_bin_write_byte(fh,73);
file_bin_seek(fh,2);
file_bin_write_byte(fh,70);
file_bin_seek(fh,3);
file_bin_write_byte(fh,56);
file_bin_seek(fh,4);
file_bin_write_byte(fh,57);
file_bin_seek(fh,5);
file_bin_write_byte(fh,97);
file_bin_close(fh);

/* Wczytaj zasob graficzny do sprite_temp'a */
sprite_replace(spr_temp,'data'+argument0+'.gif',0,1,argument1,1,0,0,0);

/* Wczytaj 1 klatke animacji do sprite_temp'a 2 */
/* Wykonaj przesuniecie ustal wielkosc klatki animacji */
sprite_assign(spr_temp2,spr_temp);
sprite_shift(spr_temp2,argument3*argument4*-1+argument6,argument7);
sprite_resize(spr_temp2,argument4,argument5,4);

/* Sprawdz dodatkowe efekty */
switch(argument8)
{
case 1: sprite_mirror(spr_temp2); break;
case 2: sprite_flip(spr_temp2); break;
case 3: sprite_mirror(spr_temp2); sprite_flip(spr_temp2); break;
}

if (argument9>0)
{
sprite_rotate(spr_temp2,argument9,1);
}

/* Tworz nowy wlasciwy sprite */
spr = sprite_duplicate(spr_temp2);

i = 1;

/* wykonaj to samo co wyzej dla reszty klatek animacji */
while ( i < argument2 )
{
sprite_assign(spr_temp2,spr_temp);
sprite_shift(spr_temp2,(i+argument3)*argument4*-1,argument7);
sprite_resize(spr_temp2,argument4,argument5,4);
switch(argument8)
{
case 1: sprite_mirror(spr_temp2); break;
case 2: sprite_flip(spr_temp2); break;
case 3: sprite_mirror(spr_temp2); sprite_flip(spr_temp2); break;
}
if (argument9>0)
{
sprite_rotate(spr_temp2,argument9,1);
}

/* doklej kolejna klatke animacji do wlasciwego sprite'a */
sprite_merge(spr,spr_temp2);
i+=1;
}

/* Usun tymczasowy plik */
file_delete(nn);

return spr;

Musimy jeszcze stworzyć dwa sprite'y o nazwach spr_temp i spr_temp2, jest to ważne, gdyż bez tego skrypt nie zadziała. Są to tymczasowe sprite'y do przygotowywania animacji klatka po klatce.

Dalej tworzymy jakiś obiekt testowy. W create dajemy mu:
kodxxx = sc_LoadSprite('shyguy',1,2,0,32,32,0,0,0,0);
sprite_index = xxx;
I gotowe. Mamy teraz nową funkcję mojego autorstwa do odczytu plików graficznych i dodawania nowych sprite'ów w czasie gry.

Taka wygoda okupiona jest czasochłonnością (trzeba utworzyć specjalne pliki, operować w edytorze na obiektach bez sprite'ów) i długością wczytywania grafiki, tak więc nie szarżujcie z ich liczbą. Najlepiej grafikę tworzyć tylko raz podczas startu gry lub planszy. No i na koniec powiem, że każdy lepszy szperacz zasobów i tak odczyta grafikę. :]

A tutaj link do przykładu, by pokazać, że to działa :)
Plik
Komentarze (łącznie 15):
SLy (Nie., 12 Wrz. 04, 21:18)
#1

Łał tego mi było trzeba. Mam jedno pytanko: Podczas zmiany początkowych bajtów pliku zmieniasz je na 71 73 70 56 57 97. Czy są to numery bajtów odpowiedzialnych za literki??? W moim edytorze "GIF98a" wyglądało troche inaczej...

Ranma_man (Pon., 13 Wrz. 04, 10:08)
#2

Po pierwsze nie GIF98a lecz GIF89a. A te liczby to zapis tego wyrazu według tablicy ASCII, w formie dziesiętnej. Może miałeś zapis np. w hexach, wtedy u siebie widzisz tak:
47 49 46 38 39 61

P
~PrzemO (Sob., 30 Kwi. 05, 09:35)
#3

Ja nie mam zarejstrowanej wersji artkuł fajny ale nie urzyteczny

Marmot (Sob., 30 Kwi. 05, 14:01)
#4

Nie użyteczny? Napewno dla tych co nie mają zarejestrowanej wersji :P

Tymon (Wto., 03 Maj. 05, 13:51)
#5

Hej, a podobno gdy wszystkie sprity, dźwięki itd. ładuje sie z osobnych plików do gry to gra chodzi szybciej. Prawda ?

Marmot (Wto., 03 Maj. 05, 15:16)
#6

Raczej tak, bo wtedy plik EXE jest mniejszy.

Ranma_man (śro., 04 Maj. 05, 11:05)
#7

Gra nie chodzi szybciej tylko szybciej ładuje się na początku. :)

S
Simon (Wto., 03 Sty. 06, 20:33)
#8

a jak zrobić tak samo z muzyką

Cekol (Pon., 22 Maj. 06, 13:39)
#9

A czy jest podobny skrypt ale pod gm 6.1??

BP Ultimate (Pon., 22 Maj. 06, 17:36)
#10

To powinno działać pod 6.1

Cekol (Wto., 23 Maj. 06, 08:26)
#11

mi niedziała mówi : Unknown funtion or script: sprite_shift

Ranmus (śro., 24 Maj. 06, 15:44)
#12

Bo w GM6 nie ma takiej funkcji. Ten poradnik jest niestety tylko do GM5. Jak uda mi się nagiąć jeszcze trochę czasu to może uaktualnię do GM6.

G
G@C3K (Nie., 13 Sie. 06, 21:02)
#13

CO TRZEBA NAPISAĆ W SKRYPCIE

p
pilar36 (Nie., 26 Lis. 06, 11:32)
#14

mam nadzieje ze szybko nagniesz ten czas, bo mi jest zajebiscie potrzebny

Ranmus (Nie., 26 Lis. 06, 14:11)
#15

To mam złe wieści. Najpierw poczekam do GM7, a potem sprawdzę funkcje, które są tu użyte. Niestety w GM6 jest inny silnik graficzny niż w GM5 i dużo funkcji zostało niestety wywalonych, w tym te, które użyłem w tym przykładzie.

Najnowsze wersje GameMakera:

Stabilna
2024.2.0.132 • 2024.2.0.163
wydana 24 dni temu
LTS
2022.0.2.51 • 2022.0.2.49
wydana 163 dni temu
Beta
2024.400.0.526 • 2024.400.0.547
wydana  wczoraj
= IDE, = Runtime
Użytkownicy online
1 użytkownik aktywny:
gości: 1,
(~ostatnie 15 minut)
Discord
44 użytkownicy online na discordzie:
MKP, s..., Alice, Carl-bot, GibkiKaktus, Grela, Wielki Druid, p..., Add92, 21Lancz, Filyps, fervi, YoungKrystian, Sevitaus, Radek Ignatów, Kalor, PhysX ᴺⱽᴵᴰᴵᴬ, r..., antek, 🧁Cupcake🧁, Uzjel, Pako, Arrekin, yazaa, Dyno, 🆅🅸🆃🅾74🅼, Korodzik, ZYGZAK, debil debilowski, Miłosz, LeD, Ulti, m..., LadyLush, bagno, Tidżi, Mtax, g..., l..., Alkapivo, moeglich, Krzysiek1250, Shockah, Kandif
Shoutbox
I am Lord (19:15, 17.03.24)
6h mam na to hmmm
I am Lord (19:06, 17.03.24)
Ale temat fajny
gnysek (01:33, 13.03.24)
Powinno działać, jest w kodzie sortowanie wg. najbliższego startu :)
Uzjel (21:59, 11.03.24)
Nie, ale za pierwszym razem zrobiłem fuckup, że było "Tura testowa" X_X
I am Lord (16:58, 11.03.24)
A co Uzjel już masz nawymyślane 100 tematów? 😅
Uzjel (20:08, 10.03.24)
@gnysek a jak bym dodał kilka lig na raz to walnie?
Uzjel (20:08, 10.03.24)
Liga będzie zawsze od piątku 16:00 do poniedziałku 23:59, zawsze w środku miesiąca.
gnysek (08:48, 10.03.24)
Tak, to też jest do poprawy X_X
Adriann (18:22, 09.03.24)
Tylko myślę czy nie leiej gdyby mówiło że zostało tyle i tyle dni i ileś godzin a nie tylko w godzinach ;d Albo konkretna data obok, byłoby czytelniej
I am Lord (15:08, 08.03.24)
o super z tą ligą :)
Starsze wpisy znajdziesz w Archiwum.
Ankieta
Ile zarobiłeś do tej pory na grach stworzonych w GM?