| | Temat wykladu: |
| | Python: Programowanie gier 2D (by Katharsis, 2007-07-09) @ wyklady.net |
| | Komentarze: http://forum.wyklady.net/index.php?topic=108 |
20:00 | Katharsis | czesc wszystkim ^^ |
| Mat-eeX | ;) |
| hawk | siem |
| adek05 | dobry |
| MiSHu | dżem dobry! |
| Mat-eeX | elo :) |
| Katharsis | i witam na wykladzie poswieconemu jezykowi programistycznemu Python |
| Katharsis | a konkretniej, programowaniu w nim gier 2D |
| hawk | ptyta fajny tongu |
| Mat-eeX | mozna sie dowiedziec kto go bedzie |
| mith | +m ;) |
| Mat-eeX | prowadzil?;d |
| MiSHu | łał |
| Mat-eeX | xD |
| Katharsis | jestem Katharsis, reprezentuje Polska grupe programistow Pythona, Polish Python Coders Group www.ppcg.eu.org) |
| Mat-eeX | nom to fajnie:) |
20:01 | Katharsis | ^^ |
| Katharsis | zanim jednak rozpoczne wyklad, zaintalujcie wymagany soft |
| adek05 | tj |
| adek05 | ? |
| Katharsis | interpreter Pythona 2.5.1 (http://www.python.org/ftp/python/2.5.1/) |
| Katharsis | interpreter Pythona dla uzytkownikow Windows http://www.activestate.com/Products/activepython/ |
20:02 | MiSHu | a jak mam juz w linuksie jak sprawdzic jaka wersja? :D |
| Katharsis | biblioteka PyGame 1.7.1 http://www.pygame.org/download.shtml |
| Katharsis | wywolaj python |
| darkjames | MiSHu, python -V |
| Zombiak | no tak, bedziemy skladac gry z klockow duplo ;d |
| MiSHu | ha! bede w logach! Pozdrawiam mame, tate i rodzicow! ;] |
| Katharsis | zakladam, ze wiekszosc z Was wie cos o Pythonie, znacie go i na pewno znacie programowanie :) |
| adek05 | dobra |
| Katharsis | odbylo sie tutaj juz kilka wykladow na temat Pythona |
| adek05 | jakie to pakiety w lInuksie beda ktos sie orientuje? |
| Katharsis | wiec techniki i zasady panujace w nim nie beda dla Was obve |
| hawk | ptyta fajny tongu |
20:03 | Katharsis | obce* |
| Katharsis | chcialbym rowniez dodac, ze bazuje na dokumentacji "About PyGame" |
| kawa131 | jest juz wyklad? |
| mith | daj +m, logi sie smiecą |
| Katharsis | wykladzie "Programowanie Gier pod Linuxem' |
| Katharsis | mith: dalem, ale w tedy sam nie moge pisac Oo' |
20:04 | Katharsis | na dzisiejszym wykladzie omowie podstawowe moduly i funkcje, dzieki ktorym uzyskujemy obraz, dzwiek, ruch/animacje |
| Katharsis | w Pythonie, dzieki bibliotece PyGame |
| Katharsis | na przykladzie prostego Arkanoida ^^ |
| Katharsis | efekt koncowy do jakiego postarmy sie dojsc w dzisiejszym wykladzie to |
| Katharsis | arkanoid_final.py ---> www.ppcg.eu.org/wyklad/arkanoid_final.tar.bz2 |
20:05 | Katharsis | odpalcie skrypt i spojrzcie w jego kod :] |
| Katharsis | niecale 100 linii kodu wystarcza do napisania Arkanoida w Pythonie :) |
| Katharsis | dobra... |
| Katharsis | zacznijmy od skryptu: |
| Katharsis | arkanoid_01.py ---> www.ppcg.eu.org/wyklad/arkanoid_01.tar.bz2 |
| Katharsis | by przygotowac Pythona i PyGame, importujemy bibliteki sys i pygame |
| Katharsis | import sys, pygame |
20:06 | Katharsis | nastepna opcja, to pygame.init() - pozwala ona nam zainicjowac wszystkie zmienne i przygotowac srodowisko |
| Katharsis | pygame.init() |
| Katharsis | kolejnym krokiem jest przygotowanie zmiennej - rozmiar_okna - po to, by zawrzec w niej |
| Katharsis | rozmiar ekranu, przypisujac do zmiennej zmienne szerokosci i wysokosc ekranu |
20:07 | Katharsis | tworzymy ekran o rozmiarze podanym wczesniej za pomoca pygame.display.set_mode(rozmiar_okna) |
| Katharsis | rozmiar_okna = width, height = 800, 600 |
| Katharsis | okno = pygame.display.set_mode(rozmiar_okna) |
| Katharsis | oraz wieczna petla, w ktorej (na razie) wszystko bedzie sie dzialo... |
| Katharsis | znajdujaca sie w niej konstrukcja for event in pygame.event.get() |
20:08 | Katharsis | tworzy liste wszystkich wydarzen wykonywanych w danym momencie np. ruch myszki, nacisniecie klawisza oraz zamkniecie okna Pythona, czyli w naszym wypadku funkcja sys.exit() |
| Katharsis | while 1: |
| Katharsis | for event in pygame.event.get(): |
| Katharsis | if event.type == pygame.QUIT: sys.exit() |
| Katharsis | wciecia sa bardzo wazne w pythonie |
| Katharsis | no i w ten sposob uzyskamy obszar naszej gry... |
20:09 | Katharsis | odpalcie i edytujcie skrypt arkanoid_02.py ---> www.ppcg.eu.org/wyklad/arkanoid_02.tar.bz2 |
| Katharsis | nowe linie kodu w skryptach bede zaznaczal pomiedzy takimi ciagami znakow (komentarze w Pythonie) |
| Katharsis | #------- |
| Katharsis | nowy kod |
| Katharsis | #------- |
| Katharsis | dla lepszego rozeznania. |
| Katharsis | co nowego w arkanoid_02.py |
20:10 | Katharsis | za pomoca funkcji pygame.image.load(), wczytujemy obrazek pilka.gif, umieszczajac go w zmiennej pilka |
| Katharsis | pilka = pygame.image.load("pilka.gif") |
| Katharsis | funkcja get_rect() tworzymy rect obrazka (czyli pobiera jego rozmiar i umiejscowienie na ekranied ) |
| Katharsis | pilkarect = pilka.get_rect() |
20:11 | Katharsis | nastepnie, za pomoca funkcji blit() umieszczamy obrazek na ekranie |
| Katharsis | w pozycji ustalonej wczesniej |
| Katharsis | okno.blit(pilka, pilkarect) |
| Katharsis | pygame.display.flip() |
| Katharsis | pygame wszystkie wczytane obrazki (na poczatku) umiszcza je w "pamieci obrazu", dlatego nalezy uzyc funkcji |
20:12 | Katharsis | pygame.display.flip() sluzacej do zamiany stron, jej użycie jest konieczne! |
| Katharsis | zamienia strony z pamiecia obrazu, w ktorej obrazek jest umiejscowiony |
| Katharsis | ze strona obrazka czekajaca na to, by dalej cos z nim robic |
| Katharsis | to tyle w tym przykladzie. |
| Katharsis | teraz: |
| Katharsis | arkanoid_03.py --> www.ppcg.eu.org/wyklad/arkanoid_03.tar.bz2 |
20:13 | Katharsis | obrazek sie poruszyl, a spowodowala to funkcja move() |
| ConSi | kurde |
| ConSi | spoznilem sie :( |
| Katharsis | porusza ona nasza pilke (zmieniajac jej rect), tak, jaka nam zmienna predkosc pokazuje |
| MiSHu | ConSi: napisz do mnei po wykladzie, dam ci loga |
| ConSi | mhm |
| Katharsis | czyli [2, 2], dwa w lewo i dwa w dol... |
| Katharsis | predkosc = [2, 2] |
| Katharsis | ... |
20:14 | Katharsis | pilkarect = pilkarect.move(predkosc) |
| Katharsis | na dodatek musimy uzyc funkcji fill()! |
| Katharsis | dlaczego? |
| Katharsis | na poczatek definiujmy sobie zmienna kolor, podajac barwe w RGB |
| Katharsis | nastepnie przed wyswietleniem pilki, zapelnijmy caly obrazek, w moim wypadku na czarno (zmienna kolor), uzywajac wlasnie funkcji fill() |
20:15 | Katharsis | gdybysmy tego nie zrobili, uzyskalibysmy nieciekawy efekt - sami sprawdzcie... tak jakby ktos pedzlem mazna :) |
| Katharsis | kolor = (000,000,000) |
| Katharsis | ... |
| Katharsis | okno.fill(kolor) |
| Katharsis | podsumowujac dzialanie naszej wiecznej petli while |
| Katharsis | - umiejscawiamy obrazek na czarnym tle |
| Wyklady_Guest | przepraszam - ile b0119dzie mniej wi0119cej trwa0142 wyk0142ad?? |
20:16 | Katharsis | - poruszamy obrazek |
| Katharsis | do 24 :) |
| Katharsis | - znowu zapelniamy ekran na czarno |
| Katharsis | - i umiejszamy pileczke przesuniata |
| Katharsis | kolejnosc jest bardzo istotna! |
| Katharsis | nastepny skrypt: |
| Katharsis | arkanoid_04.py --> www.ppcg.eu.org/wyklad/arkanoid_04.tar.bz2 |
20:17 | Katharsis | w tym skrypcie dopisalismy instrukcje warunkowa, ktora uniemozliwia wyjscie pileczki po za obszar ekranu, czyli kod: |
| Katharsis | if pilkarect.left < 0 or pilkarect.right > width: |
| Katharsis | predkosc[0] = -predkosc[0] |
| Katharsis | if pilkarect.top < 0 or pilkarect.bottom > height: |
| Katharsis | predkosc[1] = -predkosc[1] |
20:18 | Katharsis | na osi OX sprawdzamy czy lewa strona obrazka nie jest mniejsza od zera lub prawa nie jest większa od zmiennej width (800) |
| Katharsis | jesli tak to nastepuje zmiana pierwszego elemntu listy predkosc na ujemna wartosc, co powoduje odbicie pilki od granicy ekranu |
20:19 | Katharsis | i ta sama sytuacja wzgledem gornej czesci obrazka, jesli jest mniejsza od zera lub jej dol jest wiekszy od zmiennej height (600), nastepuje zmiana drugiego elementu listy - na ujemny |
| Katharsis | w efekcie koncowym uzyskujemy odbicie pilki od kazdej ze stron ekranuy |
| Katharsis | ekranu* |
| Katharsis | nowym elementem w skrypcie jest rowniez tapeta, ktora traktujemy jako kolejny obiekt graficzny |
| Katharsis | tapeta = pygame.image.load("tapeta.gif") |
| Katharsis | tapetarect = tapeta.get_rect() |
| Katharsis | ... |
| Katharsis | okno.blit(tapeta,tapetarect) |
20:20 | Katharsis | wczytujemy nowy obiekt tapeta.gif, pobieramy jego rect i umieszczamy go na obszarze gry |
| Katharsis | w moim wypadku tapeta ma rozmiar 800*600 dlatego tak wszystko ladnie pasuje :) |
| Katharsis | aha i jeszcze jedno |
| Katharsis | w momencie wczytania tapety, pozbywamy sie kodu |
| Katharsis | kolor = (000,000,000) |
20:21 | Katharsis | ... |
| Katharsis | okno.fill(kolor) |
| Katharsis | ktorego zadaniem jest zamalowywanie (w calej petli) tla gry na czarno |
| Katharsis | ta funkcje przejmuje nowy obiekt graficzny.. tapeta ;] |
| Katharsis | hm... skrypt 5 |
20:22 | Katharsis | arkanoid_05.py ---. www.ppcg.eu.org/wyklad/arkanoid_05.tar.bz2 |
| Katharsis | w tym skrypcie pojawia sie nowy element "paletka.gif" |
| Katharsis | ktora mozemy poruszac w lewo i prawo jak pewne zauwazyliscie, a moze i nie :P |
| Katharsis | na razie paletka ma kilka wad... |
| Katharsis | wychodzi po za obszar ekranu |
| Katharsis | no i przepuszcza pilke |
| Katharsis | tak wiec musimy temu zapobiedz, ale zanim... |
20:23 | Katharsis | paletka = pygame.image.load("paletka.gif") |
| Katharsis | paletkarect = paletka.get_rect() |
| Katharsis | paletkarect = paletkarect.move([350,500]) |
| Katharsis | predkosc_paletki = [0,0] |
| Katharsis | ... |
| Katharsis | okno.blit(paletka, paletkarect) |
20:24 | Katharsis | ten kod jest odpowiedzialny za wczytanie pliku paletka.gif, pobraniego jego recta oraz przesuniecie go na pozycje 350*500 |
| Katharsis | za pomoca funkcji move() |
| Katharsis | nadodatek ustalamy ze predkosc poczatkowa paletki jest rowna 0,0 no yo w tedy obiekt pozostaje w bezruchu |
| Katharsis | if event.type == pygame.KEYDOWN and event.key == pygame.K_LEFT: |
| Katharsis | predkosc_paletki[0] = -4 |
| Katharsis | if event.type == pygame.KEYDOWN and event.key == pygame.K_RIGHT: |
| Katharsis | predkosc_paletki[0] = 4 |
| Katharsis | if event.type == pygame.KEYUP and pygame.K_LEFT: |
| Katharsis | predkosc_paletki[0] = 0 |
| Katharsis | if event.type == pygame.KEYUP and pygame.K_RIGHT: |
| Katharsis | predkosc_paletki[0] = 0 |
| Katharsis | co robimy :) |
| Katharsis | bindujemy klawisz lewej i prawej strzalki |
20:25 | Katharsis | do listy event (odpowiedzialnej za zdarzenia) dopisujemy nowe zdarzenia |
| Katharsis | jesli wystapilo zdarzenie typu pygame.KEYDOWN, czyli przycisniecie klawisza i byl to klawisz lewy pygame.K_LEFT to predkosc paletki z 0 zmienia sie na 4 |
| Katharsis | znaczy -4 |
| Katharsis | 4 bedzie w prawej |
20:26 | Katharsis | analogicznie do klawisza prawego pygame.K_RIGHT, jesli przycisnieto klawisz prawy, jego predkosc z 0, znienia sie wlasnie na 4 |
| Katharsis | ostatnie dwa warunek sa odpowiedzialne za puszczenie klawisza, czyli nadanie mu predkosci 0,0, bo jak puszczamy to paletka nie rusza sie, logiczne... |
20:27 | Katharsis | warunki musza istniec, gdyz ich brak spowoduje "ucieczke paletki" po za obszar gry, a tego nie chcemy |
| Katharsis | po umiejscowieniu paleki i jej zbindowaniu przesuwamy ja za pomoca kodu: |
| Katharsis | paletkarect = paletkarect.move(predkosc_paletki) |
| Katharsis | znowu funkcja move() sie klania |
20:28 | Katharsis | teraz otworzcie i edytujcie arkanoid_06.py --> www.ppcg.eu.org/wyklad/arkanoid_06.tar.bz2 |
| Katharsis | co nowego |
| Katharsis | pozbylismy sie dwoch niedoskonalosci, ktore mialy miejsce w skrypcie arkanoid_05.py mianowicie, ograniczylismy ruch paletki do granic ekranu, ponizszy kod: |
| Katharsis | if paletkarect.left < 0 or paletkarect.right > width: |
| Katharsis | predkosc_paletki = [0,0] |
20:29 | Katharsis | oraz doprowadzilismy do tego, ze pileczka odbija sie od paletki, korzystajac z wbudowanej funkcji collidelistall(), ktora sprawdza czy dane obiekty na siebie nie nachodza (nie koliduja ze soba), czyli kod: |
| Katharsis | if pilkarect.collidelistall([paletkarect]): |
| Katharsis | predkosc[1] = -2 |
| Katharsis | jesli polozenie (rect) pilki kolidujee z polozeniem paletki, to predkosc pilki zmienia sie na -2 |
| Katharsis | to tyle w tym przykladzie, co raz blizej Arkanoida :) |
20:30 | Katharsis | tak wiec |
| Katharsis | arkanoid_07.py ---> www.ppcg.eu.org/wyklad/arkanoid_07.tar.bz2 |
| Katharsis | na pierwszy rzut, oka nic nowego, ale pozwolcie pilce spasc na dolna granice ekranu... |
| Katharsis | mamy fajny koniec gry :) |
| Katharsis | teraz zajmiemy sie pisaniem konca gry |
20:31 | Katharsis | przez pierwsze szesc skryptow wszystkie operacje wykonywane byly na wiecznej petli: |
| Katharsis | while 1: |
| Katharsis | zakonoczylismy wiecznosc petli :) podajac warunek: |
| Katharsis | while pilkarect.bottom <= height: |
| Katharsis | czyli... |
20:32 | Katharsis | dzialanie skryptu zakonczy sie (zakonczenie dzialania petli), jak dolny rect pilki znajdzie sie nizej nic ekran, skrypt konczy sie fajnym GAMEOVEREM, thx for Tanlin ;) |
| Katharsis | tak wiec, jak go zaimplementowac? |
| Katharsis | ten GameOver ofc. |
| Katharsis | piszemy koniec gry: |
| Katharsis | koniec_gry = pygame.image.load("gameover.gif") |
| Katharsis | koniec_gryrect = koniec_gry.get_rect() |
| Katharsis | okno.blit(koniec_gry, koniec_gryrect) |
| Katharsis | pygame.display.flip() |
| Katharsis | while 1: |
| Katharsis | for event in pygame.event.get(): |
| Katharsis | if event.type == pygame.KEYDOWN: |
| Katharsis | sys.exit() |
| Katharsis | nic nowego. wczytujemy nowy obrazek gameover.gif, pobieramy jego rect i umieszczamy go na ekranie |
20:33 | Katharsis | po zakonczeniu petli glownej, przechodzimy do petli drugiej (odpowiedzialnej za koniec gry), w ktorej jesli zostanie wcisniety jakis klawisz, skrypt zakonczy dzialanie sys.exit() |
20:34 | Katharsis | otworzcie i edytujcie arkanoid_08.py --> www.ppcg.eu.org/wyklad/arkanoid_08.tar.bz2 |
| Katharsis | tak na prawde nie wiele rzeczy sie pojawilo, glownie da sie zauwazyc nowe/y obiekt/y, deske/ki :) |
| Katharsis | na poczatku importujemy nowy modul random, ktory przyda sie pozniej :) |
| Katharsis | import sys, pygame, random |
| Katharsis | lista_desek = [(40,11),(40,61),(40,111),(40,161),(40,211),(40,261),(40,311),(40,361)] |
| Katharsis | lista_desek += [(191,11),(191,51),(191,101),(191,151),(191,201),(191,251),(191,301),(191,351)] |
| Katharsis | lista_desek += [(341,11),(341,51),(341,101),(341,151),(341,201),(341,251),(341,301),(341,351)] |
| Katharsis | lista_desek += [(491,11),(491,51),(491,101),(491,151),(491,201),(491,251),(491,301),(491,351)] |
| Katharsis | lista_desek += [(641,11),(641,51),(641,101),(641,151),(641,201),(641,251),(641,301),(641,351)] |
| Katharsis | lista = [] |
| Katharsis | ulala co to jest :) |
20:35 | Katharsis | tworzymy sobie liste lista_desek, w ktorej zawarte sa krotki z rectami (polozeniem) poszczegolnych desek ;] |
| Katharsis | nastepnie, w petli for musimy przeczytac te nasze deski i je umiescic na ekranie, przesuwajac je wzgledem podanych rectow^ |
| Katharsis | for i in lista_desek: |
| Katharsis | deska = pygame.image.load("deska.gif") |
| Katharsis | deska1 = deska.get_rect() |
| Katharsis | x1 = i[0] |
| Katharsis | y1 = i[1] |
| Katharsis | deska1 = deska1.move(x1,y1) |
| Katharsis | lista.insert(-1, (deska,deska1)) |
20:36 | Katharsis | co robimy... |
| Katharsis | wczytujemy nowy orazek deska.gif, pobieramy jego rect |
| Katharsis | oraz umiejscawiamy go (funkcja move()) w liscie - lista - wzgledem dwoch parametrow x1 i y1 |
| Katharsis | w efekcie koncowym uzyskujemy liste obiektow wszystkich deseczOF ;] |
20:37 | Katharsis | postac wyglada mniej wiecej tak [(rysunek, jego rect), (rysunek, jego rect), (rysunek, jego rect)] |
| Katharsis | kolejna sprawa, aby kolizja pileczki z deska doprowadzila do usuniecia deski z pola, musimy dopisac kolejny warunek do petli while |
| Katharsis | while pilkarect.bottom <= height and len(lista_desek) > 0: |
20:38 | Katharsis | i teraz sprawdzamy kolizje pilki z deska |
| Katharsis | for i in lista: |
| Katharsis | if pilkarect.collidelistall([i[1]]): |
| Katharsis | lista.remove(i) |
| Katharsis | predkosc[1] = -predkosc[1] |
| Katharsis | if random.randint(0, 1): |
| Katharsis | predkosc[0] = -predkosc[0] |
20:39 | Katharsis | co widzimy, jezeli dojdzie do kolizji (collidelistall()), deska zostanie usunieta z listy (remove()), oraz pilka zostanie odbita losowo dzieki funkcji random.randint, tak jest fajniej :) |
| Katharsis | no i blitujemy cala liste (obiekty ktore jeszcze pozostaly do zbicia) |
| Katharsis | for i in lista: |
| Katharsis | okno.blit(i[0],i[1]) |
| Katharsis | aha i jeszcze zmiana predkosci na 1,1 |
20:40 | Katharsis | w sumie to jest zbedne, po prostu przy 2,2 pilka za szybko skacze dla mnie :P |
| Katharsis | mozna wzgledem kolejnych leveli zwiekszac predkosc i liste desek np.. ale to juz chyba zalezy od inwencji tworcy :) |
| Katharsis | no i to by bylo (chyba) na tyle :) |
| Katharsis | ja ze swojej strony dziekuje, sa pytania odnosnie tych skryptow? |
20:41 | Katharsis | zdejmij pan m |
| adek05 | nie znam pythona, tylko C++ i wszystko czaje |
| adek05 | dobra robota |
| Katharsis | mozna jeszcze napisac MENU |
| Katharsis | ale mi sie nie chcialo :P |
20:42 | adek05 | teraz to juz kwestia pomyslu |
| Katharsis | gdyby ktos z Was potrzebowal skompilowac gre do postaci wykonalnej *.exe |
| adek05 | algorytm ciekawy |
| Logan | ta ? |
| Katharsis | to na ppcg.eu.org jest artykul, ktory 'mowi' jak to zrobic |
| m4c13x | o ktorej beda logi na wyklady.net? (bez partow/joinow etc) |
| MiSHu | log z calosci: |
| Katharsis | w tedy nie jest wymagany interpreter Pythona na maszynie |
| darkjames | Katharsis, a jak z wydajnoscia? ile fpsow? |
| MiSHu | www.mishu.pl/python.txt |
| Katharsis | to zalezy |
| Katharsis | osobiscie wszystko robie na gifach |
20:43 | Katharsis | uzywajac bmp ilosc fps spada |
| Katharsis | ale jest pewna opcja |
| Katharsis | funkcja convert() |
| Katharsis | ktora konwertuje obrazki do takiej postaci |
| Katharsis | by uzyskac jak najwydajnieszy efekt |
| Katharsis | a to odbija sie na FPSach |
20:44 | adek05 | a nie ma to duzego wplywu na szybkosv |
| Katharsis | ilosci przyznam nie mierzylem |
| Katharsis | w tym wypadku nie |
| adek05 | czyli im wiecej grafik tym bardziej to bedzie widac? |
| Katharsis | widac spadek fpsow? o tym mowisz ? |
20:45 | adek05 | mhm |
| adek05 | to logiczne :D |
| Katharsis | im wiecej grafiki bmp bez funkcj convert(), wg mnie tak |
| adek05 | aha ok |
| Katharsis | dlatego polcem stosowac cos takiego jak gif :) |
| adek05 | nie mam wiecej pytan |
| Katharsis | aha i jeszcze jedno |
| Katharsis | tak sobie przypomnialem |
| Katharsis | w finalnej versji |
| Katharsis | jak zauwazyliscie sa dzwieki |
20:46 | Logan | nom xD |
| Katharsis | def dzewiek(x): |
| Katharsis | if not pygame.mixer.music.get_busy(): |
| Katharsis | pygame.mixer.music.load(x) |
| Katharsis | pygame.mixer.music.play() |
| Katharsis | ta funkcja importuje z pygame mixer.music() |
| Katharsis | taka funkcja odpowiedzialna za odtwarzanie wav |
| dragon | Czesc |
20:47 | adek05 | if not pygame.mixer.music.get_busy(): |
| Katharsis | nastepnie wywolujac ja przy kolizji pileczki i paletki albo i deseczki otrzymujemy dzwiek |
| Katharsis | <code |
| Katharsis | dzewiek("stuk.wav") |
| Katharsis | oraz dzewiek("puk.wav") |
| Katharsis | dzwiek :P |
| Katharsis | lol |
| Katharsis | ale klaps ;] |
20:48 | adek05 | ;D |
| Katharsis | skoro nie ma pytan |