Fastbar
Powrót do strony głównej
Trzymaj pliki na gmclan.org!
Game Maker w pytaniach i odpowiedziach!
Polska dokumentacja
Tabela wyników ligi 24
Pobierz GM
Akademia GMCLANu
Kategorie bazy artykułów
Artykuły -> Game Maker -> Kursy GML
Treść artykułu
Inwentarz do gry RPG
autor: Pental (28.12.08)
Inwentarz do gry RPG

Z myślą o początkujących użytkownikach (tych w mniejszym stopniu oraz większym) postanowiłem napisać artykuł, w którym krok po kroku każdy może dowiedzieć się, jak wykonać solidny inwentarz do swojej gry przygodowej bądź RPG. Wymagalna jest minimalna wiedza na temat Game Makera oraz GML.

Pierwszy krok: stworzenie inwentarza

Do naszego inwentarza przedmioty będzie trzeba przenosić. Nie użyjemy żadnych funkcji (skryptów), ponieważ do tworzenia jednego plecaka takowej potrzeby nie ma. Nie znaczy to jednak, że na samym początku nie ustalimy jego parametrów. Stwórz obiekt "Inwentarz". Do wydarzenia Create możesz śmiało wsadzić mu kod:
gml:
iHor = 10; // x inwentarza
iVer = 10; // y inwentarza
iWidth = 5; // dlugosc
iHeight = 5; // szerokosc

iSprite = sKratka; // grafika przedstawiajaca slot w plecaku
iOff = -1; // odleglosc od kratek
iMax = 5; // maksymalna ilosc itemow w slocie

Zmienna iHor i iVer odpowiadają za współrzędne plecaka, zaś iWidth i iHeight za jego rozmiar. Zmienna iSprite to grafika kratki, a iOff oznacza odstęp od kratek. Zaraz, zaraz - dlaczego ma więc wartość ujemną? Podałem akurat takową, by złączyć ze sobą kratki. No i w końcu, ostatnia już z tego kodu zmienna - iMax, odpowiada za maksymalną ilość przedmiotów w jednym slocie (kratce).

Parametry już mamy, czas przejść do meritum sprawy - stworzenie plecaka. Użyjemy do tego tablic dwuwymiarowych, posiadających dwa indeksy. Dlaczego tablic? Ponieważ załóżmy, że nasz inwentarz będzie wyglądał tak:
slot1[x: 10, y: 10] slot2[x: 50, y: 10] slot3[x: 90, y: 10]...
slot6[x: 10, y: 50] ...
Zakładamy, że sloty to tablice, a ich indeksy to współrzędne, od których odjęliśmy współrzędne inwentarza, dodaliśmy odległość kratek (dodając w naszym wypadku -1 - odejmujemy 1) i podzieliliśmy przez ich rozmiar. Wtedy sprawa wygląda tak (i oraz j to indeksy):
slot1[i: 0, j: 0] slot2[i: 1, j: 0] slot3[i: 2, j: 0]...
slot6[i: 0, j: 1] ...
Natomiast wyświetlając sloty liczymy odwrotnie. Jaki to ma sens? W ten sposób będziemy mogli się odnosić do konkretnych slotów, by dodawać do nich przedmiot, usuwać lub przenosić. Do tablic dwuwymiarowych użyjemy, oczywiście, dwóch pętli krokowych for. Do kodu w evencie Create dodajmy więc:
gml:
var _i, _j, _x, _y, _t;

for( _i = 0; _i < iWidth; _i += 1; )
for( _j = 0; _j < iHeight; _j += 1; )
{
invObject[ _i, _j ] = -1;
invNumber[ _i, _j ] = -1;

_x = iHor + _i * ( sprite_get_width( iSprite ) + iOff );
_y = iVer + _j * ( sprite_get_height( iSprite ) + iOff );

_t = instance_create( _x, _y, Kratka );
_t.sprite_index = iSprite;
_t.i = _i;
_t.j = _j;
}

Na początku dajemy dla Game Makera do zrozumienia, że tworzymy tymczasowe zmienne na potrzeby kodu w tym evencie, które na końcu mają zostać usunięte. Jak już wspominałem, użyjemy tablic dwuwymiarowych. Pętla for nam tworzy tablice invObject oraz invNumber. Ta pierwsza określa obiekt (nie, nie instancję obiektu / klasy), zaś druga ilość przedmiotów o określonej klasie w slocie. Używamy tymczasowych zmiennych _x i _y, by określić pozycję slota, który aktualnie tworzymy, zaś zmiennej _t, by ustalić id tworzonego slota i nadawania mu zmiennej i oraz j. Posłużą nam one później, by z punktu widzenia slota, można było określać samego siebie i na odwrót. Jest to najwygodniejszy sposób. Dodatkowo można już zadeklarować w Create zmienne:
gml:
inEq = false;
inEqI = 0;
inEqJ = 0;

_x = 0;
_y = 0;
obj = -1;

O tym, do czego one służą - później.

Krok drugi: wyświetlanie

W poprzednim kodzie znajdowało się wyrażenie tworzące instancje klasy "Kratka". Najpierw jednak powinniśmy ją stworzyć, tak więc do dzieła. Przedtem jednak, przydałaby się czcionka, którą wyświetlane by były liczby danych obiektów w slocie. Stwórz więc nowy font. Czcionkę ustaw na Verdanę, zaznacz "digits" (cyfry), po czym ustaw rozmiar na 8 i pogrubienie (bold). Teraz już możemy do obiektu kratka dać kod:
gml:
draw_set_font( _font );
draw_set_color( c_white );
draw_sprite( sprite_index, 0, x, y );
if ( Inwentarz.invObject[ i, j ] != -1 )
{
draw_sprite( object_get_sprite( Inwentarz.invObject[ i, j ] ), 0, x, y );
if ( Inwentarz.invNumber[ i, j ] > 1 )
draw_text( x + 23, y + 20, string( Inwentarz.invNumber[ i, j ] ) );
}

Dużo tłumaczyć nie ma potrzeby. Kod ustawia biały kolor, czcionkę wcześniej przez nas stworzoną (nazwałem ją "_font"), rysuje grafikę slota oraz, jeśli takowy jest w tym slocie, wyświetla sprite obiektu znajdującego się w kratce. Co za tym idzie, jeśli jest potrzeba, wyświetla ilość instancji tu się znajdujących.

Warto zauważyć, że obiekty będziemy przenosić myszką - przenoszone obiekty warto wyświetlać pod kursorem. Pierw jednak trzeba pod uwagę wziąć fakt, że najwygodniej jest, aby w inwentarzu instancje ginęły, zamiast tego, wiadoma będzie nam ich klasa. Ma to znaczenia zarówno podczas przesuwania przedmiotów jak i ich wyświetlania pod kursorem. W drugim przypadku jest to ważne dlatego, że jeśli jest instancja, to wystarczy odnieść się do jej grafiki za pomocą kropki i zmiennej sprite_index, gdy jednak jest to obiekt (np. podczas wyrzucania rzeczy z plecaka), trzeba odnieść się do sprita za pomocą funkcji object_get_sprite(). Czas na ostatnią uwagę - jeśli sprite będzie wyświetlany w pozycji (mouse_x, mouse_y), to zmieni swą pozycję o tyle, o ile była różnica pomiędzy pozycją myszki a nim podczas podnoszenia go. Aby uniknąć tego problemu wystarczy obliczyć różnicę. Dla mnie wygodniej jest obliczyć różnicę na minusie, a później ją dodać do współrzędnym myszki. Jak wiadomo, dodawanie liczby ujemnej daje odejmowanie liczby dodatniej. Dajmy więc inwentarzowi kod w evencie Draw:
gml:
if ( obj != -1 )
{
var _sprite;

if ( inEq )
_sprite = object_get_sprite( obj );
else
_sprite = obj.sprite_index;
draw_sprite( _sprite, 0, mouse_x + _x, mouse_y + _y );
}

Nie ma raczej wiele do tłumaczenia - sprawdzamy, czy zmienna obj, która ma wartość instancji bądź obiektu (zależy czy podnosimy z inwentarza, czy nie) nie ma wartości -1, oznaczającej, że nic nie podnosimy. Tworzymy tymczasową zmienną _sprite, która będzie miała id sprita jakiego wyświetlimy. Przedtem jednak, sprawdzamy za pomocą zmiennej inEq, czy przedmiot był w inwentarzu, czy nie i na podstawie tego rysujemy gotowego już sprita.

Krok trzeci: przygotowanie inwentarza do użytku

Dobra wiadomość jest taka, że całą teorię napisałem już w poprzednim punkcie, teraz zobaczymy, jak to wygląda w praktyce. Zostało już tylko przesuwanie przedmiotów na różne możliwe sposoby, choć kodu będzie znacznie więcej, to, jak już wspomniałem, teorię znamy ;) . Zacznijmy od stworzenia obiektu "Rodzic" (ang. parent). Wszystkie przedmioty, które będziemy przenosić, będą dziedziczyły po nim jedną cechę - możliwość przenoszenia. Kod w evencie Left Pressed wygląda następująco:
gml:
// nie ma obrazka - do widzenia :)

if ( my_sprite == -1 )
exit;

// instancja ktora chcemy wsadzic do inwentarza

Inwentarz._x = x - mouse_x;
Inwentarz._y = y - mouse_y;
Inwentarz.obj = id;
Inwentarz.inEq = false;

Każde dziecko obiektu Rodzic będzie musiało mieć zadeklarowaną zmienną my_sprite, której wartość to grafika instancji w inwentarzu. Jeśli wynosi -1, to nie ma sensu takiego przedmiotu podnosić. Później obliczamy różnicę, ustalamy, że my jesteśmy obiektem noszonym i dajemy wartość 0 (false) zmiennej inEq, ponieważ przedmiot jest podnoszony nie z inwentarza.

Podobny kod możemy dać dla obiektu Kratka w tym evencie:
gml:
Inwentarz._x = x - mouse_x;
Inwentarz._y = y - mouse_y;
Inwentarz.obj = Inwentarz.invObject[ i, j ];
Inwentarz.inEq = true;
Inwentarz.inEqI = i;
Inwentarz.inEqJ = j;

Zasada taka sama jak w poprzednim przypadku. Teraz najtrudniejsza część - to, co się stanie jak upuścimy przedmiot. Zakładając, że był w inwentarzu, możliwe są akcje: wyrzucamy z inwentarza, przenosimy do innego slotu, w ostateczności nic nie robimy i nie odejmujemy ilości instancji w slocie. Wiedząc to, taki kod w evencie Globar Left Released Inwentarza nie powinien cię dziwić:
gml:
if ( obj == -1 )
exit;

if ( inEq )
{
var _n, _can;

_can = false;
_n = instance_nearest( mouse_x + _x, mouse_y + _y, Kratka );
if ( point_distance( mouse_x + _x, mouse_y + _y, _n.x, _n.y ) <= 37 )
{
if ( invObject[ _n.i, _n.j ] == -1 )
{
invObject[ _n.i, _n.j ] = obj;
invNumber[ _n.i, _n.j ] = 1;
_can = true;
}
else if ( invObject[ _n.i, _n.j ] == obj )
{
if ( iMax > invNumber[ _n.i, _n.j ] )
{
invNumber[ _n.i, _n.j ] += 1;
_can = true;
}
}
}
else
{
instance_create( mouse_x + _x, mouse_y + _y, obj );
_can = true;
}

if ( _can )
{
invNumber[ inEqI, inEqJ ] -= 1;
if ( !invNumber[ inEqI, inEqJ ] )
{
invNumber[ inEqI, inEqJ ] = -1;
invObject[ inEqI, inEqJ ] = -1;
}
}
}

Wszystkie możliwe akcje opisałem, tak więc tłumaczenie jest bez sensu. Pierwsza linijka sprawia, że jeśli zmienna obj jest równa -1, to kończy się event (dalsze akcje nie są wykonywane). Ale co, jeśli przedmiot nie był w inwentarzu? Wtedy możliwe jest, że albo się go uda dodać, albo nie. Zapomnieliśmy także nadać na końcu zmiennej obj wartość -1. Dalszy kod to:
gml:
else
{
var _n;

_n = instance_nearest( mouse_x + _x, mouse_y + _y, Kratka );
if ( point_distance( mouse_x + _x, mouse_y + _y, _n.x, _n.y ) <= 37 )
{
if ( invObject[ _n.i, _n.j ] == -1 )
{
invObject[ _n.i, _n.j ] = obj.object_index;
invNumber[ _n.i, _n.j ] = 1;
with( obj )
instance_destroy();
}
else if ( invObject[ _n.i, _n.j ] == obj.object_index )
{
if ( iMax > invNumber[ _n.i, _n.j ] )
{
invNumber[ _n.i, _n.j ] += 1;
with( obj )
instance_destroy();
}
}
}
}

Dodam tylko, aby do powyższego kodu nie było wątpliwości, funkcja instance_nearest() szuka najbliższej instancji określonej klasy od podanej pozycji. W naszym wypadku jest to kratka i pozycja kursora. Należy sprawdzić także, czy ta odległość nie jest za duża. Dałem 37, zamiast 40, ze względu na estetyczność. Później już raczej tłumaczyć nie trzeba, odpowiednie akcje, dla odpowiedniego przypadku :) . Teraz kiedy chcemy dodać jakiś przedmiot, który można przenosić, wystarczy nadać mu w okienku parent obiekt "Rodzic" i ustalić wartość zmiennej my_sprite.

Gratulacje!

Właśnie udało ci się stworzyć swój własny inwentarz! Oczywiście, możesz go modyfikować, jak ci się tylko podoba, np. dla nauki.

Przykład znajduje się tu: Przykład Inventory
głosów: 13 | ocena: 8.85 oceń zasób | dodał: PsichiX
Komentarze
stron: 21

2


av

Dawidds (11:12, 25.04.2010)

No to 1. opcja

av

Mentoss (12:06, 25.04.2010)

1. próbowałem wcześniej i nie działało... ale teraz, jak zacząłem myśleć, a nie bezmyślnie gapić sie w kod, to mi się udało...

w międzyczasie fajny efek mi wyszedł... kratki sie zaczęły na skos układać

av

karolo320 (15:53, 4.02.2011)

Dawidds, ja tam nie widze draw(5,5)

av

DANDATI (18:20, 14.05.2011)

Mam taki błąd mam wszystko tak jak w tym poradniku nazwy pozmieniałem na swoje i wyskakuje mi taki błąd...
ERROR in
action number 1
of Draw Event
for object Kratka:

Error in code at line 4:
if ( Inwentarz.invObject[ i, j ] != -1 )
^
at position 28: Unknown variable i


Chcę jeszcze dodać, że ten inwetarz to tak jakby inny room tak??...no właśnie i jak ja sobie gram podnoszę jabłko i chce wlaczyc ekwipunek zeby je zjesc i jak klikam I (przycisk ustawilem sobie przy postaci) to wyskakuje mi taki blad właśnie prosze o pomoc.

av

gnysek (14:09, 15.05.2011)

Zmienna i jest niezdefiniowana.

av

karolo320 (18:31, 17.05.2011)

moze i=0 w create pomoże

av

Mentoss (18:55, 17.05.2011)

razem z całą pętlą...

var i, j;
for(i=0;i<= i tak dalej.

stron: 21

2



Dodaj komentarz:
Treść:
Menu
Panel użytkownika
Jesteś niezalogowany!

Nie masz konta? Zarejestruj się
Użytkownicy on-line
1 użytkownik(ów) aktywny(ch) przez ostatnie 15 minut:
gości: 1, userów: 0, ukrytych: 0
Użytkownicy na czacie discord
Wojo (19:16, 22.06.18):
A gothic 17 lat temu... Jest prawie tak samo stary jak gmclan
MaxGaming (23:11, 21.06.18):
okej restart pomógł xd
MaxGaming (22:50, 21.06.18):
Jak otworzyć ten Splash Screen w android studio? Ten co wyskauje od razu po instalacji?
MaxGaming (22:49, 21.06.18):
a VC 16 lat temu
MaxGaming (22:46, 21.06.18):
ej co jeśli zainstalowałem andoid studio i studio64.exe nie chce się otworzuć? Po prostu nic się nie dzieje chociaż w procesach jest uruchomione
Wojo (21:41, 21.06.18):
A GTA 5 5 lat temu
Wojo (21:40, 21.06.18):
GTA 4 wyszło 10 lat temu
exp (20:45, 21.06.18):
a vice city to według mnie słaba gra. chociaż spędziłem z nią mnóstwo czasu
exp (20:44, 21.06.18):
nie byłem nigdy wielkim fanem tej serii, według mnie najlepsze było gta4
MaxGaming (19:37, 21.06.18):
SA znowu ceniłem za ten klimat, Nie rozumiem czemu gangsterzy mająbyć biali przecież wiadomo że nie było nigdy prawdziwego gangu białych tylko mafie i innego typu grupy przestępcze. Ta historia o wydostawaniu się z getto idealnie zgrała się z modą na gangsta rap
MaxGaming (19:36, 21.06.18):
Wydaje mi się że VC i IV to inny profil po prostu niż SA i V
MaxGaming (19:36, 21.06.18):
nie podoba mi się na nowo uproszczenie GTA i wszystkiego co z nim związane w GTA V. Za to dostajemy ogromną mapę i dużo funkcji które w sumie nie koniecznie są ciekawe typoow dla gry ale już dla zabawy poza fabularnej takq
MaxGaming (19:35, 21.06.18):
No i fabuła była genialna. GTA IV to gra która pod względem fabuły, postaci i ogólnie wykreowanego świata jest w mojej osobistej topce jeśli chodzi o gry w które kiedykolwiek zagrałem
MaxGaming (19:34, 21.06.18):
w GTA IV wyrzucono zbędne funkcje z SA które były błędem. Dodatkowo to miasto, ten NY na prawdę żył! To było coś pięknego
MaxGaming (19:34, 21.06.18):
GTA VC i 4 to kompletne gry, które mniej stawiająna sandboc a bardziej na grywalność
MaxGaming (19:33, 21.06.18):
GTA SA i V to gry żeby pobawić się, mało kto gra w to dla fabuły
MaxGaming (19:33, 21.06.18):
Natomiast GTA IV moim zdaniem jest najbardziej udaną grą z serii i szkoda że GTA V zboczyło z tego kursu
MaxGaming (19:33, 21.06.18):
fabuła, to jak ona wpływała na otoczenie(nie tak na siłę jak w SA) no i te dodatkowe funkcje były super. Na przykład każdego wieczoru zależnie od dnia tygodnia na stadionie można było wziąć udział w różnych zawodach. Kupowanie tych biznesów i zarabianie na nich. No i zdobywanie dzięki temu terenów. I ta fabuła była krótka ale dzięki temu genialna. Zdobywanie willi na przykład to jest coś fajnego. Ogólnie misji było mniej ale były ciekawsze i było mniej zapychaczy
MaxGaming (19:31, 21.06.18):
Ten klimat jest genialny. Do dziś często pykam w VC
MaxGaming (19:31, 21.06.18):
Mówiąc o VC to uargumentuje. Po pierwsze SA było za duże jakby. Mam na myśli że było niezorganizowane, dodano mnóstwo funkcji w ogóle nie związanych ze sobą. I tak trzeba było non stop dbać o siłkę itp żeby nie spadła forma. Ogólnie SA fabularnie jest zajebiste i kliamtycznie ale trochę twórcy za dużo nawtykali takich bezsensownych funkcji. GTA VC podobało mi się bo było bardziej kompletne. Wszystko do siebie pasowało. Brakowało paru funkcji żeby było jak na swoje cza
I am vader (19:30, 21.06.18):
A jesli ktos powie ze midzy gta V a IV jest za duzy okres czasu zeby je nazwac "w tym samym czasie" to moze miec racje, ale tego samego argumentu nie mozna uzyc do sa i vc bo wyszly z 2-letnia roznica
I am vader (19:10, 21.06.18):
bo gta V jest dziesiatki razy wieksze od SA, ale kazdy jest tworem swoich czasow i moim zdaniem w swoim czasie SA bylo milion razy lepsze od VC, a GTA V od GTA IV.
I am vader (19:10, 21.06.18):
GTA:SA natomaist to wooo, śmiem twierdzić że GTA:SA = GTA V > GTA 4 > GTA III=GTA VC
I am vader (19:09, 21.06.18):
Nie rozumiem fendomenu gta 4 i VC. VC chyba jedzie na samej nostalgi bo wiele w tej grze nie bylo, nawet fabula byla krotka.
MaxGaming (19:00, 21.06.18):
Według mnie najlepsze 3 części serii to kolejno GTA 4>GTA VC>GTA SA
Wojo (18:38, 21.06.18):
nieźle się typeczek postarał
Wojo (18:37, 21.06.18):
szkoda bo gta 5 to jest mistrzostwo
I am Lord (18:35, 21.06.18):
ostatnie gta jakie grałem było gta 2
Wojo (16:11, 21.06.18):
I tak najlepiej grać w GTA 5
I am Lord (15:01, 21.06.18):
i.imgur.com/VBDH84H.png suwak jest w połowie, poniżej gierki "10000000" już są gry których nie uruchamiałem
I am Lord (15:00, 21.06.18):
Chociaz u mnie nie jest aż tak źle bo 50% ograne ze 100 gierek
I am Lord (14:58, 21.06.18):
prawda :d
MaxGaming (14:08, 21.06.18):
Ja też bym tyle miał gdyby nie to że już dwa lata temu ogarnąłem że mam 300+ gier na Steam z czego 80%+ nigdy nie uruchomiłem xd nie oszukujmy się, żaden z nas nie gra w te gry
exp (12:22, 21.06.18):
kupilem wiecej gier wideo jestem kimś rozumiesz
gnysek (11:47, 21.06.18):
Retaili mam z 40-50.
I am vader (11:43, 21.06.18):
Oj jakbym mial dodac retaile mialbym pewnie tyle samo.
gnysek (9:45, 21.06.18):
wyśmiewam wasze 600 gier na steam. Mam 850 oryginalnych gier na PS2/3/4/Vita.
MaxGaming (2:41, 21.06.18):
Często naprawiam lapki jakieś, od nowa stawiam systemy i to jest problem bo ISO ostanie które miałem usnałem jakiś czas temu przez przypadek xd
MaxGaming (2:41, 21.06.18):
Ale mi bardziej chodzi o serwisowanie
MaxGaming (2:41, 21.06.18):
Ja czytałem że od dawna w unii są przepisy które pozwalają legalnie korzystać z OEM a prawo > licencja producenta. Z tego co wiem to jest to samo co z mac os na pc - niby licencja zakazuje ale jest legalne ze względu na przepisy prawa
MaxGaming (2:39, 21.06.18):
Wojo mam 356 gier na Steam kupionych xd nie trafiłeś xd
I am vader (23:28, 20.06.18):
@Wojo prawda, ale mowisz do goscia ktory ma 594 gry na steam
exp (23:08, 20.06.18):
a i np. mogę sobie jednym kliknięciem zmienić język gry wraz z dubbingiem zamiast błąkać się po internecie
exp (23:07, 20.06.18):
jak gierka kosztuje 20zł i mogę mieć je wszystkie na zawsze w jednym miejscu no to fajna opcja. zwłaszcza, że nie jestem jakimś zapalonym graczem, bo steama mam dwa lata, a gier chyba siedem
exp (23:06, 20.06.18):
ja mam na steamie gierki, które kupiłem legalnie po 999 latach albo nawet miałem kiedyś fizyczne kopie
Wojo (22:03, 20.06.18):
no ale jak masz kupiony oryginał i z różnych powodów nie możesz go uruchomić to moim zdaniem na miejscu jest pobranie sobie wersji z neta zamiast kupować to samo raz jeszcze
I am vader (22:01, 20.06.18):
ja po 123123 lat kupilem Hitmana 2. Kupilem tez Gothic 1/2/3 bo nie wlozylm stacji CD/DVD do komputera i nie mialem jak zainstalowac z plytki
Wojo (21:42, 20.06.18):
no wiadomo ze legalne gry, programy warto mieć bo to też jest szacunek dla twórców no ale bez przesady
Wojo (21:42, 20.06.18):
jak dla mnie to jest durnota, kupować grę, którą się już ma, albo kupowanie gierki ktora ma juz 100 lat bo trzeba byc legalnym
I am vader (21:37, 20.06.18):
Do ISO Win7 masz prawo tylko z kluczem nie-OEM. Jesli masz OEM to technicznie nei otrzymales prawa do legalnego pobrania ISO.
Ankieta
» Jakie kursy najchętniej widziałbyś na stronie ?
GM Studio
GM Studio 2
Godot
Construct

GMCLAN to serwis o programie Game Maker i nie tylko.
[ Polityka prywatności ]
Copyright © 2002-2018. GMCLAN.ORG
Wszelkie prawa zastrzeżone. Kopiowanie materiałów bez zgody redakcji zabronione!
© 2002-2017 Ranmus (ranmus.pl), © 2017-2018 {=|=} fable_inside();

[ Czas generowania strony: 0.05406 sekund ] [ Liczba zapytań MySQL: 13 ]