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
Przejrzyste sterowanie klawiszami oraz rekonfiguracja.
autor: Ranma_man (5.01.05)
Witam wszystkich game makerowiczów. Dzisiaj na warsztat weźmiemy problem sterowania obiektami w grze za pomocą klawiatury. "Bułka z masłem" ktoś by powiedział, ale czy aby na pewno tak jest? Jeśli zechcemy zrobić opcję rekonfiguracji sterowania, to będziemy musieli operować na funkcjach a nie eventach do tego przeznaczonych (można oczywiście pójść inną drogą, a mianowicie "w locie" zmodyfikować eventy obiektu, ale to już temat na inny artykuł a i rozwiązanie jest niezbyt przejrzyste). Poza tym nazwy funkcji obsługi klawiszy takie krótkie nie są, co potem utrudnia czytelność kodu, a ciągłe ich wklepywanie jest czasochłonne, tak więc nie jest dobrze. :)

Zabieramy się do roboty, czyli jak ułatwić sobie życie. :)

Przykład poruszania się obiektu w 8 kierunkach ( powiedzmy o 7 pikseli ). Prawdopodobnie większość z was napisała by taki kod:
gml:
if ( keyboard_check( vk_up ) ) if ( place_free( x , y - 7 ) ) y = y - 7;
if ( keyboard_check( vk_down ) ) if ( place_free( x , y + 7) ) y = y + 7;
if ( keyboard_check( vk_left ) ) if ( place_free( x - 7 , y ) ) x = x - 7;
if ( keyboard_check( vk_right ) ) if ( place_free( x + 7 , y ) ) x = x + 7;

Wygląda nawet ładnie ... ale nie dla mnie. ;)
Po pierwsze jesli naciskamy kursor w górę, to automatycznie nie musimy sprawdzać kursora w dół, analogicznie jest z osią poziomą. Po drugie keyboard_check to zbyt długi wyraz. Po trzecie nie ma tu miejsca na rekonfigurację klawiszy.

Powyższy przykład zapiszmy inaczej:
gml:
if ( global.kl_up ) przesun(0,-7);
else if ( global.kl_down ) przesun(0,7);
if ( global.kl_left ) przesun(-7,0);
else if ( global.kl_right ) przesun(7,0);

I jak? Nie lepiej? :) Oczywiście funkcję "przesun" musicie sobie napisać sami. :P

Jak widać obraliśmy sobie 4 nowe zmienne globalne o dość łatwych nazwach do zapamietania. Jest to znacznie krótsza forma niż wcześniej, a i nie podajemy bezpośrednio klawiszy o które nam konkretnie chodzi, dzięki temu zostawiamy sobię "furtkę" do stworzenia opcji przedefiniowania sterowania. Owe globalne będą przyjomwały dwie wartości: true w przypadku wciśnięcia danego klawisza lub false.

Mamy już globalne, ale co z nimi zrobić? Sytuacja jest prosta, każda gra zazwyczaj posiada jeden globalny obiekt sterujący. Zróbmy sobie takowy o nazwie engine. Będzie on tworzony już w pierwszym roomie gry. Teraz czas na jego konfigurację, zaznaczamy mu opcję Persistent co oznacza, że obiekt będzie stworzony tylko raz w czasie gry i będzie przechodził pomiędzy room'ami. Dalej dodajemy mu event'a o nazwie Game Start. Tutaj będzie inicjalizacja sterowania, czyli odczyt klawiszy, o które nam chodzi. Je zaś zdefiniujemy w pliku config.ini. Jego źródło:
gml:
[STEROWANIE]
Gora=38
Dol=40
Lewo=37
Prawo=39

Prawda że proste? Te numery to kody liczbowe klawiszy (w tym wypadku kursorów), polecam przejrzeć tablicę ASCII (a jak ktoś nie ma ochoty, to niech w event step byle jakiego obiektu wklepie: "room_caption = string(keyboard_key)" i sam przetestuje). Kodami liczbowymi posługujemy się tak samo jak dyrektywami vk_space, vk_up itd. podając je jako argumenty w funkcji keyboard_check i innych.

Teraz zabierzemy się za wczytanie tych danych. W obiekcie engine event'a Game Start wpisujemy:
gml:
ini_open('config.ini');
global.key[0] = ini_read_real('STEROWANIE','Gora',38);
global.key[1] = ini_read_real('STEROWANIE','Dol',40);
global.key[2] = ini_read_real('STEROWANIE','Lewo',37);
global.key[3] = ini_read_real('STEROWANIE','Prawo',39);
ini_close();

Jak widać INI jest bardzo łatwe w obsłudze. Opis funkcji ini_read_real:
argument0 - Sekcja danych w pliku ini.
argument1 - Nazwa zmiennej do pobrania z danej sekcji.
argument2 - Wartość domyślna zmiennej gdy wczytywanie zakończy się niepowodzeniem.

Mamy już wczytane kody klawiszy do tablicy global.key. Teraz pora napisać skrypt odpowiednio ustawiający wcześniej zdefiniowane zmienne globalne. Event Step obiektu Engine:
gml:
if ( keyboard_check ( global.key[0] ) ) global.kl_up = true; else global.kl_up = false;
if ( keyboard_check ( global.key[1] ) ) global.kl_down = true; else global.kl_down = false;
if ( keyboard_check ( global.key[2] ) ) global.kl_left = true; else global.kl_left = false;
if ( keyboard_check ( global.key[3] ) ) global.kl_right = true; else global.kl_right = false;

I gotowe. Tego skryptu już nie musimy potem ruszać. Teraz czas na redefiniowanie klawiszy. Podam mniej więcej jak to zrobić. Tworzymy obiekt o nazwie menu. Tworzymy:

Create:
gml:
pozycja = 0; // Aktualna pozycja kursora w menu
pauza = false; // Pauza do oczekiwania na wcisniecie klawisza.
draw_set_color(c_white); // Kolor czcionki

menus[0] = "Chodzenie w gore: ";
menus[1] = "Chodzenie w dol: ";
menus[2] = "Chodzenie w lewo: ";
menus[3] = "Chodzenie w prawo: ";
menus[4] = "Wyjscie z menu";

Step:
gml:
if ( pauza ) // Jezeli jest pauza
{
     if ( keyboard_check ( vk_anykey ) ) // Jezeli jakis klawisz zostal nacisniety
     {
          pauza = false; // Wylaczamy pauze
          global.key[pozycja] = keyboard_key; // Zapisujemy numer klawisza do danej pozycji
          io_clear(); // Resetujemy aktualny stan klawiszy
     }
}
else // Jezeli pauzy nie ma, to pozwalamy kursorowi zmieniac pozycje w menu
{
     if ( keyboard_check ( vk_up ) )
     {
          if ( pozycja > 0 )
          {
               pozycja -= 1;
               io_clear(); // Resetujemy stan klawiszy
          }
     }
     else if ( keyboard_check ( vk_down ) )
     {
          if ( pozycja < 4 )
          {
               pozycja += 1;
               io_clear();
          }
     }
}

if ( keyboard_check ( vk_enter ) ) // Jezeli naciskamy enter - wybieramy jakas pozycje z menu
{
     if ( pozycja == 4 ) // Pozycja czwarta bedzie oznaczac wyjscie z menu
     {
          room_goto_next(); // Wychodzimy z menu

          ini_open('config.ini'); // Zapis sterowania do pliku
          ini_write_string('STEROWANIE','Gora',string(global.key[0]));
          ini_write_string('STEROWANIE','Dol',string(global.key[1]));
          ini_write_string('STEROWANIE','Lewo',string(global.key[2]));
          ini_write_string('STEROWANIE','Prawo',string(global.key[3]));
          ini_close();
     }
     else // Jezeli to pozycja gdzie jest redefinicja jednego z 4 klawiszy
     {
          if ( !pauza ) // Jezeli pauzy nie ma
          {
               pauza = true; // Wlaczamy pauze
               global.key[pozycja] = 999; // Ustawiamy specjalny kod... Objaśnienie na końcu arta
               io_clear(); // Resetujemy stan klawiatury
          }
     }
}

Draw:
gml:
for ( i = 0 ; i < 4 ; i += 1 )
{
     if ( i == pozycja )
     {
          draw_set_color(c_red);

          if ( i == 4 )
               draw_text(x, y+i*30, menus[i] );
          else
               draw_text(x, y+i*30, menus[i] + klawisz_string( global.key[i] ) );

          draw_set_color(c_white);
     }
     else
     {
          if ( i == 4 )
               draw_text(x, y+i*30, menus[i] );
          else
               draw_text(x, y+i*30, menus[i] + klawisz_string( global.key[i] ) );
     }
}

Niestety nie będę tutaj objaśniał powyższych skryptów, ponieważ tworzenie menu nie jest tematem tego artykułu. Ważne jest tylko to, że po to ustaliliśmy globalną tablicę do trzymania kodów klawiszy, aby potem można było je łatwo wyświetlić jako listę. Funkcja io_clear() resetuje stan wszystkich klawiszy, czyli jak był wciśnięty, to już nie jest.

Ważne jest by przy wyjściu z takiego menu zapisać dane do pliku ini. Służy nam do tego funkcja write_ini_string:

argument0 - Sekcja danych pliku ini
argument1 - Nazwa zmiennej, która będzie zapisana w podanej sekcji
argument2 - Wartość zmiennej jako tekst.

Teraz czas na opis funkcji klawisz_string, którą musimy dodatkowo utworzyć. Otóż jeśli znamy numer ASCII znaku, to najłatwiejszym sposobem jego wyświetlenia jest użycie funkcji chr(wartosc), gdzie za argument podajemy numer kodowy z tablicy ASCII. Jest jednak jedno "ale", tym sposobem wyświetlimy jedynie część znaków klawiszy, głównie liczby i alfabet. Co zatem z takimi klawiszami jak "Insert", "Escape" itd.? Wyświetli nam się na pewno nie to czego oczekiwaliśmy. Po to właśnie będzie nam potrzebna funkcja klawisz_string. Będzie ona zwracała nazwę klawisza w postaci tekstu o dowolnej długości a nie tylko jednego znaku. Taką funkcję łatwo napisać, wystarczy użyć strukturę typu switch i zależnie od numeru znaku klawisza zwracać inny tekst. Teraz trzeba wypisać wszystkie znaki. Na całe szczęście ciało funkcji napisałem już wcześniej (z rok temu):
gml:
var k;

switch (argument0)
{
case 33: k='PAGE UP'; break;
case 34: k='PAGE DOWN'; break;
case 35: k='END'; break;
case 36: k='HOME'; break;
case 37: k='LEFT ARROW'; break;
case 38: k='UP ARROW'; break;
case 39: k='RIGHT ARROW'; break;
case 40: k='DOWN ARROW'; break;
case 45: k='INSERT'; break;
case 46: k='DELETE'; break;
case 96: k='NUMPAD 0'; break;
case 97: k='NUMPAD 1'; break;
case 98: k='NUMPAD 2'; break;
case 99: k='NUMPAD 3'; break;
case 100: k='NUMPAD 4'; break;
case 101: k='NUMPAD 5'; break;
case 102: k='NUMPAD 6'; break;
case 103: k='NUMPAD 7'; break;
case 104: k='NUMPAD 8'; break;
case 105: k='NUMPAD 9'; break;
case 106: k='NUMPAD *'; break;
case 107: k='NUMPAD +'; break;
case 109: k='NUMPAD -'; break;
case 110: k='NUMPAD DEL'; break;
case 111: k='NUMPAD /'; break;
case 13: k='ENTER'; break;
case 8: k='BACKSPACE'; break;
case 16: k='SHIFT'; break;
case 17: k='CONTROL'; break;
case 18: k='ALT'; break;
case 32: k='SPACE'; break;
case 20: k='CAPS LOCK'; break;
case 192: k='TILDE'; break;
case 92: k='MENU'; break;
case 93: k='WINDOWS'; break;
case 144: k='NUMLOCK'; break;
case 187: k='+'; break;
case 188: k=','; break;
case 189: k='='; break;
case 190: k='.'; break;
case 191: k='/'; break;
case 220: k=''; break;
case 186: k=';'; break;
case 222: k="'"; break;
case 219: k='
['; break;
case 221: k='
]'; break;
case 999: k='
Nacisnij jakis klawisz'; break;
default: k=chr(argument0); break;
}

return k;

Dyrektywa default oznacza standardowo zwracany tekst, gdy żaden case nie pasuje. Są to właśnie znaki, które można wyświetlić za pomocą funkcji chr (alfabet,cyfry...). Kolejnym plusem tego rozwiązania jest to, że jeśli do wyświetlenia menu używamy nietypowej czcionki, która nie posiada wszystkich znaków, to... w funkcji klawisz_string możemy zamienić ten znak na jakiś opis tekstowy. ;)

Zauważcie jeszcze "case 999". Taka wartość jest oczywiście nieprawidłowa, a służy nam tylko do tymczasowego wyświetlenia prośby o wciśnięcie jakiegoś klawisza. ;)

To wszystko na dzisiaj. Do artykułu zamieszczam jeszcze przykład w formacie .gm6:

Sterowanie_art.zip

głosów: 4 | ocena: 6.00 oceń zasób | dodał: Ranmus
Komentarze
stron: 1

1


av

Firemark (17:56, 7.01.2005)

moze bede wcibski,ale czy idzie dac....na joystick?

av

Ranmus (20:50, 7.01.2005)

Idzie, a jakze. Jak napisalem w arcie, funkcja do zwracania odpowiedniego tekstu byla zrobiona rok temu, a wtedy to robilem sterowanie dla kuzyna, joystick tez byl. Ale teraz od strony kodu to troche skopane. Jak bede mial czas i checi, to dopisze.

~Kaytek (16:48, 16.01.2005)

Wścibski? Czemu "wścibski"?

~firemark-bez_log (21:12, 24.01.2005)

A no bo tak ;D

~PrzemO (9:36, 30.04.2005)

Jestes wścipski {zart} Ja z tego nic nie kapuje k****

av

bigshark (10:48, 30.04.2005)

ejhhh to nie chodzi o to ze onjest wscibski dlatego ze sie zapytal o dzojstik, on jest poprostu wscibski w swojej wscibskosci. I dlatego tez jest wscibski, juz kapujesz?

av

Tymon (13:53, 3.05.2005)

Nic nie kapuje, pozatym na takie rozmówki to zapraszam na GMchat lub na GG

~Pablo (14:09, 12.02.2006)

eh... link do przykladu nie dziala :/

av

Tymon (14:21, 12.02.2006)

Ranma albo BWO musi zmienić Ja nie mam pełnego dostępu.

gmclan.org/index.php?plik=64

av

pablo1517 (13:42, 30.09.2006)

no to dopisz jak dać na pada! xD

av

pablo1517 (19:02, 22.10.2007)

Ranma miał tu coś dopisać

av

blackmaul (13:59, 23.10.2007)

Upomnij się za rok, Ranmus jest zajęty.

av

XivroX (18:26, 4.11.2008)

heh, minął rok...

av

Anubarak (17:32, 18.02.2009)

i następny rok...

av

Anubarak (17:36, 18.02.2009)

oprócz kilku miesięcy

av

Mosiek (16:00, 13.08.2009)

YY a jak to tego kodu
if ( global.kl_up ) przesun(0,-7);
else if ( global.kl_down ) przesun(0,7);
if ( global.kl_left ) przesun(-7,0);
else if ( global.kl_right ) przesun(7,0);
dopisać że jak idzie to zmienia sprite a jak się zatrzymam to się włącza sprite stojącego typka Nie wiem w ogóle jak się za to zabrać ;/

av

kt1117 (8:41, 7.11.2010)

Dodaj do skryptu przesun.

stron: 1

1



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

Nie masz konta? Zarejestruj się
Użytkownicy on-line
4 użytkownik(ów) aktywny(ch) przez ostatnie 15 minut:
gości: 1, userów: 3, ukrytych: 0
Deusald (Adamentium), Chell, I am vader
Użytkownicy na czacie discord
Wojo (10:29, 20.04.18):
Jeśli chodzi o reklamy to odpowiadają mi takie co są na gmclanie teraz niż zamienianie połowy gmclanu na reklamę podpasek czy czegoś podobnego
Wojo (10:27, 20.04.18):
Tylko, że 10% zużycia słabego komputera nie równa się 10% zużyciu dobrego komputera
Wojo (10:27, 20.04.18):
Tylko, że 10% zużycia kom
MaxGaming (1:00, 20.04.18):
Wiesz wirusy też są mimo tego że nie powinny, ale jakoś radzimy sobie z tym
MaxGaming (1:00, 20.04.18):
Mi mniej przeszkadza kopanie bitcoinów w tle niż npnatarczywe reklamy. Wolałbym natomiast aby takie strony mogły się do tego przyznać i nie były linczowane
MaxGaming (0:59, 20.04.18):
przeciwko oszustą byłby fakt braku ograniczeń. Strona musiałaby tylko informować, a czy wkorzysta 90% to jej sprawa. BYleby użytkownik wiedział sam na co się pisze
MaxGaming (0:58, 20.04.18):
Ale o to chodzi z procentami. Dzięki temu nawet jak mamy wolny komputer odczujemy tak samo. Co do innego prawa. Na każdej stronie jakoś jest informacja np. o plikach cookies. Dałoby to sięogarnąć, tym bardziej gdyby powstałą organizacja sprawdzająca takie informacje i byłaby np na jej stronie lista nieuczuciwych stron które należy unikać. Możnaby wprowadzić także w przeglądarkach żeby takie strony nie otwierały się, albo wymagały wyraźnego potwierdzenia użytkownika. Myślę że głównym argumentem
Wojo (23:08, 19.04.18):
tak samo bodajże w szwecji partia piratów chciała założyć własne małe państwo gdzie piractwo byłoby legalne dzięki czemu niektóre strony mogłyby obejść prawo w taki lub inny sposób
Wojo (23:06, 19.04.18):
a żeby mieć jakiś faktyczny zysk z takich koparek bitcoinów to musiałbyś je ustawić na jakiejś popularnej stronie bo np na takim gmclanie zbyt wiele nie wydobędziesz
Wojo (23:05, 19.04.18):
Ale to brzmi abstrakcyjnie Stronę zawsze można założyć w innym państwie gdzie takie prawo nie obowiązuje, 10% mocy obliczeniowej komputera przecież się różni w zależności od tego jak mocny mamy komputer
MaxGaming (21:08, 19.04.18):
Według mnie jeśliby ustanowić prawnie że strona która twierdzi że pobierze np. 10% mocy obliczeniowej naszego komputera na prawdę musi tyle pobierać pod groźbą kary to np kopanie bitcoin w tle jest fajną alternatywą dla reklam
Wojo (10:33, 19.04.18):
Jak dla mnie to sprytne rozwiązanie ktoś wymyślił
I am vader (0:53, 19.04.18):
Nie pamietam jak ten program sie nazywal ale za jaja bym powiesil skurczybyka ktory to zrobil.
I am vader (0:52, 19.04.18):
Odmowilem, nic wielkiego, ale potem przed pobraniem programu kazano mi kopac conajmniej jakastam chwile, tu juz sie podniosly czerwone flagi. Wiec sprawdzilem ten program pod katem wirusow i okazalo sie ze wygenerowane exeki instaluja koparki na kompach uzytkownikow.
I am vader (0:52, 19.04.18):
Znalazlem taki program ktory zamienia pliki bat w exe poniewaz powody, ale na stronie zostalem zapytany czy uzycze komputera na mineowanie kryptowalut podczas przegladania strony zeby wspomoc tworce.
I am Lord (23:59, 18.04.18):
może flash coś dodaje?
Wojo (23:06, 18.04.18):
Nawet pobrałem sobie ADW cleanera i nic nie wykrył
Wojo (22:38, 18.04.18):
No ale co mi po tym, że ktoś ma ip z Gdańska i jest zainteresowany zabawkami dla psów co jest bezużytecznymi danymi nawet dla hakera
Wojo (22:36, 18.04.18):
W sumie jak tak siedzę i się zastanawiam to może wydobyć pliki cookies, przechwycić naciśnięte klawisze
Wojo (22:33, 18.04.18):
Ale co ma śledzić? Lokalizację na podstawie ip? Bo nie rozumiem za bardzo
PsichiX (21:38, 18.04.18):
mowie o skrypcie js-agent.newrelic.com, ktory rozpoznawany jest jako narzedzie sledzace.
PsichiX (21:36, 18.04.18):
prowo?
Wojo (19:40, 18.04.18):
To tak zwane "prowo", które było nieudolną próbą "prowo" yxa
I am Lord (16:59, 18.04.18):
Aż tak ci się zacina to?
Wojo (16:11, 18.04.18):
Pół biedy ze śledzeniem ale denerwuje mnie kopanie BitCoinów przez ten link Nie ma to jak napychać portfel komuś kogo nie znam
I am Lord (0:04, 18.04.18):
Nic o tym nie wiem, a co to za skrypt?
PsichiX (23:56, 17.04.18):
a ten skrypt śledzący to Ty wrzucałeś, czy twórcy scratcha są na tyle ułomni, że coś takiego od siebie dodają? ;>
I am Lord (22:56, 17.04.18):
gnysek (9:35, 12.04.18):
No ja raz miałem nieważną z winy sekretariatu i też chyba musiałem 10zł zapłacić.
Wojo (12:34, 11.04.18):
A wszyscy co chcieli rzucić gimnazjum to po prostu strzelali kible do oporu i ich przenosili do ohp
Wojo (12:08, 11.04.18):
Nie mam jak się zapytać gdyż nie posiadam żadnych znajomych
Gibki Kaktus (10:15, 11.04.18):
To powiedz, że ich popierdoliło xD
MaxGaming (19:39, 10.04.18):
Ustawowa opłata za duplikat to właśnie 9zl. Przeczytajcie jeszcze raz o czym ja mówię :/
Gibki Kaktus (17:11, 10.04.18):
Ja jak zgubiłem to płaciłem 9 czy tam 10 zł xD
MaxGaming (23:07, 9.04.18):
Opłata 9zł to co innego, Nie bardzo, bo kolega z innej szkoły miał podobne doświadczenia...
Chell (22:59, 9.04.18):
albo uisc oplate, jeszcze nie slyszalem o darmowych duplikatach dokumentow
Ignatus (22:20, 9.04.18):
Chyba po prostu Cię nie lubią i robią sobie jaja.Przysłuchaj się przy drzwiach od sekretariatu czy nie kwiczą ze śmiechu zaraz po Twoim wyjsciu
MaxGaming (21:29, 9.04.18):
Szukam na necie i nigdzie nie widzę że jest taki przepis. I wątpie że jeśli jest to muszą to być drogie i nie czytane przez nikogo anonse. Wie ktoś coś?
MaxGaming (21:28, 9.04.18):
Ma ktoś pojęcie na jakiej podstawie szkoła może ode mnie żądać płatnego(i to słono jak za taką usługę) ogłoszenia w anonsach jeśli zgubiłem legitymacje? Twierdzą że nie mogą mi wyrobić nowej bez potwierdzenia zamieszczenia ogłoszenia w anonsach i uiszczenia opłaty...
Wojo (21:11, 9.04.18):
Nie ogarnalem ze jest tylko 48h ,myslalem ze z tydzien ;p
Ignatus (21:04, 7.04.18):
Nie ogarnalem ze jest tylko 24h ,myslalem ze z tydzien ;p
I am vader (19:00, 7.04.18):
Troche pozno zaalarmowales
Ignatus (18:25, 7.04.18):
Nieważne już ,zabrakło kilku głosów,przepadło
Ignatus (16:36, 7.04.18):
Moja żona robi charytatywnie lalki dla chorych i niepełnosprawnych dzieci.Mogę prosić o "wykop" ? www.wykop.pl/li...epelnosprawnych
PsichiX (0:04, 6.04.18):
uuu, antyleniwizm!
I am Lord (23:43, 5.04.18):
Ale kierowniczka widziała że sam ładuję to mu da popalić
I am Lord (23:42, 5.04.18):
zacząłem ładować przed 22 i gość miał mi pomóc a dał nogę
I am Lord (23:41, 5.04.18):
dla każdego
PsichiX (23:35, 5.04.18):
a czy zmiana konczyla sie dla niego o 22:00?
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.
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.03846 sekund ] [ Liczba zapytań MySQL: 13 ]