Posts from 2007

I ty zostaniesz transportowcem

2007-08-24 20:55

Gry, które są dobre, potrafią przykuć uwagę przeciętnego gracza na kilka czy kilkanaście miesięcy. Gry wyjątkowe są pamiętane nawet po kilku latach i ciągle mają zagorzałych zwolenników. Ale tylko nieliczne produkcje obrastają taką legendą, że po jakimś pojawiają się serwisy podobne do Diablo Evolution. Można tam obejrzeć w szczegółach, jak wyglądały kolejne stadia (alfa, beta, itd.) powstawania kultowego cRPG Diablo. Jeśli ktoś pamięta, jaka nowatorska była w swoim czasie ta gra, nie powinien być zdziwiony, że jej maniacy tworzą podobne strony.

Screen z gry OpenTTDSamo wspominanie przeszłości mało jednak wnosi i dlatego o wiele bardziej odpowiadają mi inicjatywy reanimacji starych gier. Taka operacja może być tylko dostosowaniem jej do uruchamiania na aktualnym sprzęcie i we współczesnych systemach operacyjnych – czego przykładem jest choćby emulator DOSa DOSBox. Niekiedy jednak fani mogą pokusić się o coś więcej…
Screen z gry OpenTTDŚwietnym przykładem takiej udanej reanimacji jest OpenTTD – remake doskonałej gry ekonomicznej Transport Tycoon Deluxe sprzed, bagatelka, 12 lat. Muszę przyznać, że mam do niej ogromną słabość, gdyż TT było jedną z pierwszych ‘prawdziwych’ gier (czyli żadnych tam platformówek), w którą miałem okazję grać. Ahh, stare dobre czasy ;]

Screen z gry OpenTTDW obecnych czasach oryginalna wersja Transport Tycoon Deluxe zdecydowanie trąciłaby już myszką (bynajmniej nie tą z rolką i przyciskami), lecz jej open source’owa wersja – OpenTTD jest jak najbardziej do przyjęcia. Zmian w stosunku do oryginału jest sporo i obejmują też te techniczne, jak choćby możliwość gry w znacznie wyższych rozdzielczościach niż oryginalne 640×480. Pewnym modyfikacjom uległ też gameplay, ale są one na tyle przemyślane, że absolutnie nie zabijają pierwotnego ducha gry. Aż dziw, że taka subtelność uchowała się w programie rozwijanym jako open source ;P
Screen z gry OpenTTDJeżeli więc też pamiętasz oryginalny Transport Tycoon, albo po prostu lubisz tego rodzaju starsze produkcje, OpenTTD powinien przypaść ci do gustu. Aby się o tym przekonać, musisz zrobić dwie rzeczy:

  1. Zaopatrzyć się w pierwotną wersję gry, czyli Transport Tycoon Deluxe. Możesz ją ściągnać np. z serwisu StareGry.pl, jako że posiada ona status abandonware.
  2. Ściągnąć i zainstalować OpenTTD, podając w trakcie instalacji katalog z TTD.
Tags: ,
Author: Xion, posted under Games » 3 comments

Piaskownica dla programistów

2007-08-23 14:08

Zdarza się, że chcemy napisać coś “na szybko”. Możliwe na przykład, że znaleźliśmy przepis na ciekawy efekt graficzny i chcemy go od razu wypróbować. Albo natrafiliśmy na nietypowy algorytm rozwiązujący jakiś problem i mamy ochotę go wypróbować w akcji. Zależnie od tego, jak bardzo lubimy eksperymentować, takie sytuacje mogą się zdarzać się z różną częstotliwością.

Tradycyjne środowiska programistyczne nie są w tym celu zbyt pomocne, gdyż stworzenie w nich nawet prostego programu wymaga ustawienia przynajmniej kilku opcji, stworzenia katalogu na kilkanaście wygenerowanych przy okazji plików – i tak dalej. Zamiast sedna musimy więc skupić się na nieistotnych szczegółach.
Kiedyś pomyślałem sobie, że dobrze byłoby mieć takie proste środowisko, w którym można by było oszczędzić sobie całego tego zachodu. Gdzie nie trzeba przejmować się takimi sprawami, jak kompilacja, wejście od użytkownika, ustawienie trybu graficznego , właściwa konstrukcja głównej pętli aplikacji, itp.

Screen z przykładu Processing: falujący tekstW zamierzchłych i na szczęście dawno minionych czasach namiastką czegoś takiego było środowisko dla “języka” LOGO, którym to niekiedy zamęczano biedne dzieci w gimnazjach :) W czasach nieco bliższych powstały interpretowane języki programowania z linią poleceń – jak na przykład Python – mogące służyć do wspomnianej ‘niezobowiązującej zabawy’. Fachowo nazywa się ją prototypowaniem.
Screen z przykładu Processing: obracający się sześcianOstatnio zaś znalazłem (za sprawą noogi z kanału #warsztat) coś, co wydaje się o wiele bliższe ideałowi. To open source’owe środowisko o ambitnej nazwie Processing, mające nieporównywalnie większe możliwości niż te wspomniane wyżej. Język programowania w nim zawarty jest bardzo przyjemny i ma “normalną” składnię z wyodrębnionymi blokami kodu – jak C(++/#), PHP czy Java – i możliwości zbliżone do ww. języków. Programy napisane w oparciu o Processing są krótkie i zwięzłe, bowiem większość potrzebnych narzędzi, takich jak inicjalizacja grafiki (opartej o OpenGL) czy podpięcie wejścia klawiatury i myszy, zostało już zintegrowanych. Naszym zadaniem jest tylko wypełnienie treścią dość oczywistych funkcji jak draw, setup czy mousepressed; niekoniecznie zresztą wszystkich.

Screen z przykładu Processing: kule z oświetleniem kierunkowymOd strony technicznej Processing też prezentuje się całkiem znośnie. Jego IDE ma aczkolwiek jeden bolesny mankament: jest napisane w Javie i wszyscy wiemy, co to oznacza dla szybkości jego uruchamiania :) Cały system jest zresztą oparty właśnie o Javę, ale to staje się akurat bardziej zaletą niż wadą. Jedną z nich jest ładny język programowania, a inną to choćby możliwość bezbolesnego eksportu napisanych programów do postaci zwykłych plików wykonywalnych dla różnych systemów operacyjnych. Można też tworzyć z nich aplety do umieszczenia na stronach WWW, co pokazuje choćby ten atraktor Lorenza.

Aplikacje wygenerowane w ten sposób na pewno nie zastąpią tych pisanych z użyciem prawdziwych kompilatorów, ale podejrzewam, że nie taki jest cel. Chodzi przede wszystkim o tę ‘piaskownicę’, w której można bezboleśnie wypróbowywać nowe idee.

Tags:
Author: Xion, posted under Programming » Comments Off on Piaskownica dla programistów

Cztery metody debugowania

2007-08-22 11:55

Nikt nie jest nieomylny – zwłaszcza jeżeli chodzi o programistów. Błędy w kodzie zawsze były, są i będą się pojawiały z mniejszą lub większą regularnością. Najważniejsze więc to umieć sobie z nimi radzić. Według mnie jest to tak samo ważna umiejętność jak posługiwanie się jakimś językiem programowania czy biblioteką graficzną. Tyle że jest ona o wiele przydatniejsza, bo znacznie bardziej uniwersalna.

Często – przede wszystkim w firmach tworzących oprogramowanie – usuwaniem błędów zajmują się wyspecjalizowane osoby, czyli testerzy. Jak wiadomo w każdym programie jest przynajmniej jeszcze jeden błąd, a przy użyciu odpowiednich technik można wyłapać przynajmniej te, z którymi miałaby szansę zetknąć się przynajmniej pewna część końcowych użytkowników.
Tego rodzaju błędy muszą być zwykle specjalnie wyszukiwane, jednak na co dzień koderzy spotykają się z takimi, które same ‘znajdują’ programistów. Mówiać wprost, często (o wiele za często) zdarza się, że po prostu coś nie działa – albo nie działa tak, jak powinno.

Co wtedy zrobić? Osobiście stosuję poniższe metody. Uszeregowałem je w kolejności od najmniej do najbardziej drastycznej, a jednocześnie od najmniej do najbardziej skutecznej. Kryteriami rosnącymi w dół listy jest także czasochłonność oraz stopień desperacji programisty :) A rzeczone sposoby są następujące:

  1. Po owocach ich poznacie. Przyczynę błędu można często znaleźć, patrząc na to, co tak naprawdę się psuje. Najłatwiej jest rzecz jasna wtedy, gdy program kończy się krzykiem komunikatu w rodzaju wyjątku ochrony pamięci czy przekroczenia zakresu tablicy. Trudniej jest, jeśli aplikacja działa stabilnie, lecz produkuje błędne rezultaty. Wówczas wymagana jest dogłębna znajomość własnego kodu oraz pewna doza intuicji, a czasami zdolności profetycznych ;]
  2. Śledzenie kodu – czyli praca krokowa, oferowana przez każde sensowne środowisko programistyczne – to dość skuteczna metoda. Dokładne przyjrzenie się przebiegowi programu oraz rezultatom pośrednim często pomaga zidentyfikować problem. Przy okazji pracy krokowej mamy też większe szanse na znalezienie wrednych literówek, jak np. napisanie x zamiast y.
  3. Pluszowy miś, niezrównany w znajdowaniu błędówPrzegląd kodu bez asysty debuggera wydaje się krokiem wstecz, lecz tak naprawdę jest on bardziej skuteczny (i jednocześnie bardziej czasochłonny). To sposób znany też jako ‘metoda pluszowego misia’. Polega na on wytłumaczeniu wspomnianemu misiowi działania naszego kodu – linijka po linijce – a miś znajdzie błąd. Oczywiście prawdziwą przyczyną rozwiązania problemu będzie fakt, że zastanawiając się ponownie nad działaniem napisanego kodu mamy znacznie większe szanse na dostrzeżenie popełnionym w nim gaf. Podobno mistrzowie tej techniki debugowania potrafią nawet obywać się bez misia :)
  4. Komentowanie fragmentów kodu to najcięższe działo, jakie można wytoczyć. Wyłączając wpierw sporą partię wychodzimy od czegoś, co wprawdzie działa, ale nie robi wszystkiego, co było przewidziane. Następnie zmniejszamy ilość wykomentowanego kodu i patrzymy, kiedy wszystko się zepsuje. Gdy tak się stanie, obszar potrzebujący intensywnej inspekcji będzie już znacznie zawężony. Niestety, czasem może się okazać, że w końcu ponownie włączymy do kompilacji cały kod, a wtedy błąd po prostu… zniknie. Wówczas wbrew pozorom nie ma się z czego cieszyć, gdyż najpewniej oznacza to, że natrafiliśmy na wyjątkowo wredny rodzaj błędów znanych jako heisenbugs.

Jeżeli wszystko zawodzi, pozostaje jeszcze ostatnia deska ratunku, czyli szukanie pomocy z innych źródeł, np. na forach. Z praktyki widać jednak, że często preferowana kolejność postępowania jest dokładnie odwrotna. A to na dłuższą metę nie jest to rozsądne, ponieważ osobą najlepiej przygotowaną do znalezienia błędu w kodzie jest sam jego autor.
Świat były aczkolwiek o wiele piękniejszy, gdyby konieczność takich poszukiwań nie zdarzała się zbyt często :)

Tags:
Author: Xion, posted under Programming » 6 comments

System GUI #4 – Przycisk

2007-08-21 14:48

Co można powiedzieć o czymś tak prozaicznym, jak zwykły przycisk? Ano to, że przycisk jest po to, aby go wciskać :) Od strony użytkownika wygląda to więc bardzo prosto – może nawet zbyt prosto, co czasami kończy się źle, jeśli nie czytamy komunikatów przed pochopnym wciśnięciem OK.
Kwestia oprogramowania takiego tworu jak przycisk, aby zachowywał się zgodnie z oczekiwaniami, jest już jednak trochę trudniejsza.

Przy okazji przycisku wychodzi bowiem kwestia tak zwanego mouse capture, które to pojęcie nie ma dobrego tłumaczenia na język polski. Pozwala ono użytkownikowi rozmyślić się i nie dokonać kliknięcia nawet wtedy, gdy zdążył już wcisnąć przycisk myszki. Wystarczy, że – nie puszczając go – odjedzie kursorem poza obszar kontrolki i tam puści przycisk myszy. Wówczas zarówno zdarzenie wciśnięcia, jak i puszczenia przycisku myszy będzie zarejestrowane, lecz to najważniejsze – kliknięcia – już nie.
Ten dość abstrakcyjny byt mouse capture może być przez kontrolkę posiadany lub nie. Jeżeli kontrolka go posiada, wtedy otrzyma ona informacje o zdarzeniach myszy nawet gdy kursor znajduje się poza jej obszarem. Dzięki temu kontrolka przycisku może być poinformowana o tym, że użytkownik zrezygnował z jej wciśnięcia.

Wciśnięcie przycisku i odjechanie kursorem

Pozostaje jeszcze drobna kwestia graficzna. Otóż w Windows kontrolka przycisku “wyciska się”, jeżeli odjedziemy kursorem poza jej obszar (oczywiście cały czas trzymając wciśnięty przycisk myszki). Kiedy znów wrócimy, wciśnie się ponownie, i tak dalej (ciekawym zalecam własnoręczne eksperymenty ;]). Osobiście nie sądzę, żeby takie zachowanie było bardzo intuicyjne, bo chyba bardziej by mi odpowiadało, gdyby kontrolka pozostała cały czas wciśnięta.
Niestety, nie ja ustanawiam standardy interfejsu, więc postanowiłem się dostosować i zaimplementować windowsowe rozwiązanie :)

Tags: , ,
Author: Xion, posted under Programming » 4 comments

Referencje do klas w Delphi

2007-08-20 11:30

W ramach kontynuacji przeglądu nietypowych konstrukcji językowych – który to nieopatrznie rozpocząłem, zajmując się pętlami w Pythonie – obejrzymy sobie jeden z elementów języka Object Pascal. Są to referencje do klas, zwane też czasem metaklasami.

Ten dziwny twór działa jak odwołanie wskazujące na klasę jako typ, a nie na jej konkretny obiekt. Deklaruje się go mniej więcej w taki sposób:
[delphi]type TClass = class of TObject;[/delphi]
Zmienne należące do tak zdefiniowanego typu TClass mogą pokazywać na wszystkie klasy dziedziczące po TObject. Innymi słowy, takie zmienne są swego rodzaju dynamicznymi aliasami na nazwy klas; używając ich, nie musimy nawet wiedzieć, z jakiego typu klasą konkretną mamy do czynienia. Przypomina to oczywiście normalny dynamiczny polimorfizm obiektów, osiągany przy pomocy funkcji wirtualnych. Tutaj jest to niejako dynamiczny polimorfizm samych klas.

Użycie takiego typu referencyjnego może wyglądać choćby tak:
[delphi]type TFoo = class(TObject) // klasa dziedzicząca po TObject
// …
end;

var
AnyClass : TClass; // zmienna będąca referencją do klasy
AnyObject : TObject; // zwykłe odwołanie do obiektu
begin
AnyClass := TFoo; // referencja pokazuje na klasę TFoo
AnyObject := AnyClass.Create; // tworzy obiekt klas TFoo przy pomocy referencji
end;[/delphi]
Ten przykład pokazuje, że w Delphi przy pomocy referencji do klas możliwe jest łatwe zrealizowanie wzorca wirtualnego konstruktora. Nie musimy bowiem wiedzieć, na jaką klasę wskazuje referencja, a utworzony obiekt możemy “odebrać” posługując się zmienną typu bazowego (tutaj TObject).

Co na to C++? Nie ma tam naturalnie podobnej konstrukcji. Zbliżone do niej – w sensie możliwości korzystania z jakiegoś typu bez wiedzy, czym on naprawdę jest – są parametry szablonów. Podstawowa różnica polega jednak na tym, że szablony są rozwijane w trakcie kompilacji i “wartości” tych parametrów są niezmienne.
Nie wiem, czy można w jakiś sposób zaimplementować w C++ metaklasy o funkcjonalności zbliżonej do powyższej. Znając możliwości C++, to całkiem prawdopodobne :) Ich ewentualny brak nie były jednak jakoś szczególnie dotkliwy, gdyż większość ich zastosowań z powodzeniem daje się zastąpić szablonami lub zwykłymi funkcjami wirtualnymi.

Tags: , ,
Author: Xion, posted under Programming » 4 comments

Wyjście = format + ujście

2007-08-19 11:58

Dla odmiany zająłem się ostatnio czymś nieco prostszym niż GUI, a mianowicie systemem logującym. To zdecydowanie niezbędne narzędzie, które docenia się zwłaszcza wtedy, kiedy coś innego psuje. Jak dotąd aczkolwiek nic poważnego nie zdążyło się jeszcze, ale w programowaniu jest to, jak wiadomo, tylko kwestią czasu ;)

Do logowania istnieje mnóstwo podejść, które różnią się głównie tym, gdzie i jak zapisujemy nasze informacje. Bo jeśli o to, co mamy logować, to odpowiedź jest prosta: wszystko albo jak najwięcej.
Dość obszerny przegląd możliwych wyjść loggera przedstawił TeMPOraL w jednej swoich notek. Jakkolwiek długa ta lista by nie była, pewne jest jedno: na pewno nie może być ona zapisana “na sztywno” w kodzie głównej klasy systemu logującego. Same ‘wyjścia’ należy bowiem opakować w osobne klasy, wywodzące się ze wspólnej bazy i wykorzystać zalety polimorfizmu. W ten sposób można kierować komunikaty zarówno na konsolę, do zwykłego pliku tekstowego, jak i do funkcji OutputDebugString.

Pomyślałem jednak nad rozszerzeniem tego pomysłu, który wyraża się w tytułowym równaniu: wyjście = format + ujście. Postanowiłem oto podzielić wyjście logowania na dwie części:

  • format odpowiadający za wygląd pojedynczego wpisu. W zależności od rodzaju obiekt ten przerabia komunikat logowania na zwykły tekst, XHTML, XML albo inny, dowolnie wybrany format danych.
  • ujście (drain), zajmujące się zapisaniem sformatowanego komunikatu w określonym miejscu. Tym miejscem może być standardowe wyjście diagnostyczne (czyli zwykle konsola), lokalny plik czy nawet plik na zdalnym serwerze.

Schemat systemu logującego

Nie jest to oczywiście żadna rewolucja. Czasami też obie części muszą być do siebie ściśle dopasowane, aby osiągnąć pożądany efekt (np. wypisywanie kolorowych komunikatów w asynchronicznej konsoli Windows). Zwykle jednak można je zestawiać dowolnie i otrzymywać ciekawe rozwiązania. Najważniejsze, że tą dodatkową elastyczność da się osiągnąć małym kosztem.

Tags: , ,
Author: Xion, posted under Programming » Comments Off on Wyjście = format + ujście

Uparte menu kontekstowe

2007-08-18 14:36

Menu kontekstowe programu mIRCProgramy rezydujące w zasobniku systemowym (system tray) są zawsze wyposażone w menu kontekstowe. Zwykle pojawia się ono po kliknięciu prawym przyciskiem myszy na ikonkę aplikacji i zawiera najczęściej używane opcje programu – co czasem oznacza też “wszystkie opcje programu” :)
Czasami jednak to menu jest uparte i jeśli nie zdecydujemy się na wybranie żadnej pozycji, ono pozostaje otwarte nawet mimo tego, że już dawno zajęliśmy się czymś innym. Zupełnie jakby Windows “zagapił się” i przeoczył moment, gdy menu utraciło fokus (wtedy właśnie powinno było zniknąć). Bywa to o tyle denerwujące, że takie osierocone menu przykrywa wszystkie inne okna w systemie.

Niekiedy pomaga wtedy ponowne kliknięcie w ikonkę programu. Jeżeli jednak to nie działa, trzeba jakoś przywrócić feralnemu menu utracony fokus, aby mogło go ponownie stracić – i, miejmy nadzieję, zniknąć na dobre. Jak to zrobić bez uaktywniania żadnej pozycji menu? Są co najmniej dwa sposoby:

  • można kliknąć w separator, czyli poziomą linię oddzielającą od siebie niektóre opcje
  • można kliknąć prawym przyciskiem myszy w dowolne miejsce menu

Kiedy następnie klikniemy w jakiekolwiek miejsce poza menu, oporna lista powinna się w końcu schować.

Tags: , ,
Author: Xion, posted under Programming » Comments Off on Uparte menu kontekstowe
 


© 2023 Karol Kuczmarski "Xion". Layout by Urszulka. Powered by WordPress with QuickLaTeX.com.