Przemysł gier na początku dekady

2011-01-01 11:46

W ramach obowiązkowych corocznych spojrzeń w przeszłość i przyszłość rzucę okiem na dziedzinę, którą osobiście nieco ostatnio zaniedbałem. To oczywiście błąd, bo gry komputerowe – a o nich właśnie mówię – to rzecz każdemu człowiekowi do życia bardzo potrzebna :) W ostatnich latach zaszły na tym polu spore zmiany, które nie były tylko natury technicznej. Można powiedzieć, że przemysł gier dojrzał i uległ dość wyraźnej specjalizacji, a ledwie zarysowany parę lat temu podział został już całkiem dobrze ugruntowany.

Z jednej strony mamy segment core, obejmujący wysokobudżetowe produkcje pochodzące z wielkich studiów developerskich, nad którymi pracują dziesiątki lub setki ludzi. Dominującą platformą stały się tutaj next-genowe konsole (aktualnie XBox 360 i PS3), ale komputery PC trzymają się dobrze w przypadku specyficznych gatunków jak RTS-y czy RPG-i. W tym obszarze dokonuje się największy postęp w dziedzinie “czysto” technologicznej, co obejmuje zarówno szczegółowość i efektowność grafiki, jak również innowacyjność na innych polach. Jednym z nich jest chociażby sterowanie, czego chyba najbardziej znanymi przykładami są Wii Remote i bardzo świeży Microsoft Kinect.

Druga strona, zupełnie już porównywalna rozmiarami z pierwszą i niedającą się już zbywać wzruszeniem ramion to segment gier typu casual. Obecnie to ogromny rynek obejmujący setki milionów graczy na wielu różnych, technologicznie bardzo odmiennych platformach. Wydaje się, że spośród nich najważniejsze są w tej chwili dwie: bardziej zaawansowane telefony komórkowe oraz przeglądarki internetowe. Różnią się one nieco szczegółami – jak choćby tym, co jest źródłem zysku ich twórców – ale w obu przypadkach założeniem jest prostota (i często wtórność) rozgrywki, mały (a często żaden) poziom trudności i przynajmniej teoretyczny brak konieczności poświęcenia długiego czasu na grę. O te zasady oparta jest także sławetna najpopularniejsza gra na świecie.

Gdzieś pomiędzy tymi dwoma wielkimi obszarami rozciąga się też małe poletko indie, czyli gier określanych jako ‘niezależne’. Nakłada się ono częściowo na pozostałe sektory, nierzadko czerpiąc z nich to, co najlepsze. Zwykle są one bowiem proste koncepcyjnie i niezbyt wymagające czasowo – tak jak gry casual. Jednocześnie często charakteryzują się innowacyjnością, a czasem też zadziwiająco dobrą oprawą graficzno-dźwiękową. To właśnie z obszaru indie wywodzi się chociażby hit ostatnich miesięcy, czyli sieciowa gra 3D w układanie sześcianów.

Czy bazując na historii i stanie obecnym da się dokonać jakiejś prawdopodobnych prognoz odnośnie przyszłości przemysłu gier?… Jeśli tak, to chyba najrozsądniejsze wydaje się przypuszczenie, że zarysowany wyżej podział nie ulegnie w najbliższym czasie jakimś gwałtownym zmianom. Czasami tylko słyszę pesymistyczne prognozy zwolenników tworzenia gier core, wieszczących rychły koniec tego segmentu rynku. Zapominają oni jednak o tym, że między nim a sektorem casual nie toczy się wcale gra o sumie zerowej, grupy docelowe obydwu nie mają dużej części wspólnej, a każdy z nich celuje w odmienne gusta i potrzeby graczy.
Moja prognoza jest więc optymistyczna: szansa na to, że wszyscy skończymy pisząc pluginy do FarmVille jest zgoła niewielka :)

Tags: , ,
Author: Xion, posted under Games, Thoughts » 3 comments

Nieoficjalne debugowanie na Androidzie

2010-12-22 22:00

System Android, jak powszechnie wiadomo, jest licencjonowany kategorią open source, więc istnieje możliwość w miarę łatwego umieszczenia go na urządzeniach mobilnych bez konieczności współpracy z Google. Wykorzystują to producenci różnego rodzaju mniej lub bardziej “nieoficjalnego” sprzętu, działającego pod kontrolą tego systemu. Mogą to być produkty, które trudno klasyfikować inaczej niż jako tanie imitacje, ale także sprzęt produkowany przez (u)znane firmy – jak choćby tablet stworzony przez Creative. Ich wspólną cechą jest domyślny brak wsparcia przez narzędzia wspomagające pisanie aplikacji dostępne w ramach SDK Androida – przede wszystkim Android Debug Bridge (adb), czyli usługę umożliwiającą między innymi debugowanie aplikacji bezpośrednio na urządzeniu. Dla zwykłego użytkownika to oczywiście żadna wada, ale co mają zrobić biedni programiści?…
Okazuje się jednak, że przeszkodę tę da się pokonać. Dzisiaj udała mi się ta sztuka ze wspomnianym tabletem Creative’a i dlatego czuję się upoważniony podzielić się swoim rozwiązaniem :) Wydaje się ono przy tym na tyle ogólne, że powinno stosować do dowolnego urządzenia.

Tags: , , , , ,
Author: Xion, posted under Programming » Add comment

Kiedy kod jest przejrzysty

2010-12-21 22:44

Pisanie kodu to czasami niewdzięczne zajęcie, ale tylko z rzadka. Nieprzyjemnych wrażeń o wiele częściej, jak sądzę, dostarcza czytanie kodu. Jest tak po części pewnie dlatego, że statystycznie programista przeznacza na to zajęcie znacznie więcej czasu (wystarczy policzyć chociażby debugowanie). Innym powodem może być też to, że dokładne zdefiniowanie takiego określenia jak przejrzysty kod okazuje się zaskakująco trudno, bo kategoria ta wydaje się w dużym stopniu subiektywna.

Weźmy na przykład komentarze. Potoczna koderska mądrość mówi nam, że łatwy do zrozumienia kod zapewne posiada dużo komentarzy, bo w końcu jak inaczej opisać zawiłości konstrukcji językowych i bibliotecznych, które się w nim znajdują?… Może to i przekonująca logika, ale ja mam lepszą. Można by przecież liczbę tych zawiłości minimalizować jeśli nie eliminować zupełnie. Kod przejrzysty powinien dokumentować się w zasadzie sam. Wyjątki istnieją, oczywiście, bo zawsze znajdą się jakieś kruczki, haki i inne triki, które można opatrzyć jedynie napisem // Magic. Do not touch. (o ile nie chcemy opisywać ich działania w elaboracie na piętnaście linii). Jeśli jednak większość kodu wygląda “magicznie”, to jego autora należy czym prędzej przeszkolić w bardziej mugolskich technikach programowania :)

Trochę odrębnie od przygodnych komentarzy traktuję wstawki mające służyć na dokumentację do poszczególnych elementów kodu. Tworzenie jej w pełnej formie, z opisem każdego pola, metody i parametru jest nie tylko czasochłonne, ale i w dużej części niezbyt sensowne. Z drugiej jednak strony brak chociaż słowa wzmianki nt. tego, co dana klasa czy metoda w zasadzie robi to zbrodnia popełniona na nieszczęśnikach, którzy potem muszą przedzierać się przez taką terra incognita. Można obyć się bez wiedzy, jak dany element działa, ale informacja o tym, do czego służy lub co ma w założeniu robić jest po prostu niezbędna.

Komentarze, według mnie, to jednak w ostatecznym rozrachunku sprawa drugorzędna. Znacznie ważniejsza – być może nawet pierwszorzędna – zdaje mi się bowiem odpowiednia organizacja na każdym poziomie projektu. Zaczyna się ona od rozmieszczenia funkcjonalności w klasach, modułach i pakietach, a kończy na układzie samych deklaracji w plikach. Ogólna zasada jest tu bardzo prosta: chodzi o to, by elementy podobne i odpowiedzialne za zbliżone zadania były fizycznie blisko siebie. Regułę tę można łamać w przypadkach uzasadnionych i chęć podziału kodu na warstwy (np. logiki i interfejsu) jest na pewno jednym z nich. Często nie da się tego jednak powiedzieć np. o grupowaniu ze sobą w klasie metod o tej samej widoczności zamiast podobnej i/lub zależnej funkcjonalności

Wreszcie, o przejrzystości kodu decydują też wrażenia wzrokowe otrzymywane w czasie jego oglądania. Wpatrywanie się w długie, gęsto zapełnione znakami wiersze o znikomej ilości pustych przestrzeni jest zajęciem męczącym i dlatego powinniśmy oszczędzać go sobie i innym. Stosujmy więc białe znaki, i to rozrzutnie. Spacje, podziały wiersza oraz puste wiersze (a czasami i wcięcia, jeśli język na to pozwala) używane w przemyślany sposób poprawiają wizualny odbiór listingów i jednocześnie poprawiają wspomnianą wcześniej organizację – tym razem na poziomie mikro.

Tags: , ,
Author: Xion, posted under Programming, Thoughts » 2 comments

Podstawowa wielowątkowość w Javie

2010-12-17 22:57

W Javie nietrudno natrafić na metody z klasy Object, bo pojawiają się one w kontekście dowolnego obiektu, do którego się odwołujemy. Wśród tych metod można zauważyć kilka, których przeznaczenie nie jest zrazu oczywiste; są to wait, notify i notifyAll. Lektura dokumentacji może nas pouczyć, że mają one coś wspólnego z wątkami... Ale czemu coś takiego jak wątki ma swoje "wtyki" już na tak niskim poziomie? Ano dlatego, że w Javie wielowątkowość jest pewnego rodzaju młotkiem, którego posiadanie zamienia wiele napotkanych zadań i problemów w gwoździe. Opowiem dzisiaj co nieco o podstawach posługiwania się tym tępym narzędziem :)

Zacznijmy od tego, że kiedy rozdzielamy program na więcej niż jeden wątek, prawie natychmiast pojawia się problem synchronizacji. Może on mieć wiele form, ale zaryzykuję stwierdzenie, że najczęściej występują dwie poniższe:

  • ochrona jakiegoś zasobu (w bardzo ogólnym sensie) przez równoczesnym dostępem z więcej niż jednego wątku
  • oczekiwanie wątków na jakieś zdarzenia i ich powiadamianie, gdy te zdarzenia zachodzą

Implementacje pierwszego przypadku nazywa się powszechnie sekcjami krytycznymi. W Javie siedzą one tak głęboko, że są częścią samego języka i mają swoje własne słowo kluczowe: synchronized. (Jest to właściwie dokładny odpowiednik lock z C#). Słowem tym możemy oznaczać metody lub bloki kodu, czyniąc je kodem synchonizowanym. Taki kod może być - dla danego obiektu - wykonywany tylko przez jeden wątek naraz. Wszystko więc, do czego się w takim kodzie odwołujemy, jest chronione przed jednoczesnym dostępem wielu wątków - tak jak w przykładzie poniżej:

public class Counter {
    public static final int MAX = 10;
    private int i = 0;
   
    public synchronized void add(int k) {
        if (i + k <= MAX) i += k;
    }
    public synchronized int get() { return i; }
}

Chroniona jest tu wartość zmiennej i licznika, dzięki czemu nie ma możliwości, że przekroczy ona ustalone maksimum. Bez synchronizacji mogłoby to się stać, gdyby jeden wątek zwiększył jego wartość tuż po tym, jak drugi uznał (instrukcją if), że też może to zrobić.

Drugi typ synchronizacji to powiadamianie o zdarzeniach i to właśnie do niego stosują się wspomniane na początku metody klasy Object. Świadczą one o tym, że w Javie każdy obiekt może być czymś, co fachowo nazywa się monitorem - wysokopoziomową konstrukcją synchronizacyjną (wyższą niż np. znane i lubiane semafory). synchronized jest jedną z części tego mechanizmu, zapewniającą wyłączny dostęp. Drugą jest możliwość, aby wątki czekały (wait) na zdarzenia sygnalizowane przez inne wątki (notify), czego podręcznikowym przykładem jest generowanie i przetwarzanie danych porcjami - czyli scenariusz producent-konsument:

public class Transfer {
    private object data = null;

    public synchronized void produce(object obj)
        throws InterruptedException {
        if (data != null) wait();
        data = obj;
        notify();
    }

    public synchronized object consume()
        throws InterruptedException {
        if (data == null) wait();
        object obj = data;
        data = null;
        notify();
        return obj;
    }
}

I tak mniej więcej przedstawiaj się podstawy wielowątkowości w Javie. Bardziej zaawansowane obiekty sychronizacyjne - jak choćby te z pakietu java.util.concurrent wykorzystują te własnie podstawowe mechanizmy zapewniania wyłączności oraz powiadamiania. Jeśli piszemy kod, który korzysta z współbieżności w prosty sposób, możemy wykorzystać je bezpośrednio.

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

Formatowanie tekstu

2010-12-12 19:03

Tematem budowania łańcuchów znaków zajmowałem się już kiedyś, badając efektywność tej operacji w C++ dla trzech różnych sposobów. Tym razem przyjrzę się sprawie z perspektywy bardziej niezależnej od języka. Ostatnio poczyniłem bowiem pewną obserwację. Zauważyłem mianowicie, że "tradycyjne" podejście do składania stringów - przez konkatenację kolejnych podciągów - staje się... hmm... niemodne, jeśli można tu użyć takiego określenia.

Ci, którzy kodują nieco dłużej niż ja pewnie zwrócą mi zaraz uwagę, że takie naprawdę tradycyjne podejście do problemu to to, które implementują funkcje z języka C podobne do printf:

fprintf (stderr, "[%s] Error (errno=%d)\n", tag, errno);

Polega ono na uprzednim zdefiniowaniu wzorca tekstu (tzw. formatu, tutaj jest to drugi argument fprintf), zawierającego symbole zastępcze takie jak %s czy %d. Są one następnie zastępowane podanymi wartościami (tutaj: tag oraz errno) w celu wyprodukowania finalnego ciągu. Nie ma tu jawnej operacji łączenia dwóch napisów. Zamiast tego mały parser przegląda podany wzorzec i w miejscu symboli zastępczych wstawia do wyniku podane wartości, przepisując bez zmian resztę znaków.
Wkrótce jednak nadszedł C++ z klasami string i ostream, oferującymi podobne możliwości bez użycia wzorców. Zamiast tego posługiwały się operatorami + i << w celu wyprodukowania tekstowego wyjścia:

cerr <<"[" <<tag <<"] Error (errno=" <<errno <<")" <<endl;

To działa, ale - jak można zobaczyć w porównaniu - wygląda często znacznie mniej przejrzyście. Nie dziwi więc, że w tym względzie historia zdaje się zatoczyć koło.

Obecnie bowiem operacja formatowania napisów (w sensie powyższej funkcji fprintf, a nie określania czcionki czy stylu tekstu) jest wbudowana w wiele nowoczesnych, popularnych języków programowania, jak choćby C#, Pythona czy Javę. Najczęściej też, co ciekawe, trzyma się ona z grubsza oryginalnej składni wzorców pochodzącej jeszcze z C, dodając oczywiście jakieś własne, bardziej zaawansowane rozszerzenia:

exc_type, exc, _ = sys.exc_info()
logging.error("[%s] %s" , exc_type.__name__, exc)

Console.WriteLine("[{0}] {1}", e.GetType().Name, e.Message);

Czasami jednak - jak widać wyżej - tak nie jest :) Na obecność mechanizmu formatowania łańcuchów znaków możemy aczkolwiek liczyć w każdym szanującym się języku. I to łącznie z C++, gdzie wszystko prawie wszystko, czego w nim pierwotnie nie ma, zawiera się w jakiejś bibliotece boost - w tym przypadku jest to boost::format.

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

Więcej pulpitów

2010-12-09 23:23

Pracując przez chwilę na Linuksie, odkryłem poważną zaletę jego interfejsu graficznego, którą Windows domyślnie nie może się pochwalić. Wirtualne pulpity, bo o nich mowa, to koncept, który w pierwszej chwili może wydawać się nieco dezorientujący. W końcu czasami ma się problem z ogarnięciem okien na jednym tylko pulpicie, więc co dopiero powiedzieć o - powiedzmy - czterech? :) Ale więcej miejsca na bałagan to także więcej miejsca na porządek i jeśli tylko potrafimy dobrze tę powiększoną przestrzeń zagospodarować, możemy znacznie zyskać na efektywności. Ograniczamy bowiem konieczność przełączania między programami za pomocą powolnych i niewygodnych metod, takich jaki klikanie w przyciski na pasku zadań czy pracowite przechodzenie po liście okien za pomocą przełącznika Alt+Tab.

To doprawdy wstyd, że Windows nie oferuje takiego mechanizmu wbudowanego w system. Jakby się jednak chwilę nad nim zastanowić, nie jest on żadnym rodzajem magii. Można go przynajmniej symulować za pomocą odpowiednio przemyślanego ukrywania i odkrywania okien na żądanie użytkownika, przechodzącego między kolejnymi "wirtualnymi «wirtualnymi pulpitami»". Zdaje się, że właśnie na takiej zasadzie działają programy, które uzupełniają system Windows o tę pożyteczną funkcjonalność.
Rozwiązaniem wypróbowanym przeze mnie jest VirtuaWin. Jest to bardzo mała, ale całkiem zmyślna aplikacja. Bez widocznego narzutu na zasoby systemowe (kilka megabajtów w pamięci) wprowadza ona możliwość przełączania się między wirtualnymi pulpitami przy pomocy typowych kombinacji klawiszy (czyli Ctrl+Alt+strzałki). I to niemal dowolną liczbą wirtualnych pulpitów, do których można automatycznie przypisywać okna na podstawie ustalonych (bazujących np. na klasie okna lub jego tytule). Jedyne, czego tu brakuje, to ładna animacja przełączania zamiast znikających i pojawiających się okien... ale cóż, nie można mieć wszystkiego ;)

W każdym razie polecam przyjrzenie się możliwości powielenia swojego pulpitu nawet bez przyłączania dodatkowych ekranów. Opłaca się.

Tags: , ,
Author: Xion, posted under Applications » 2 comments

Android jest fajny

2010-12-06 18:43

Od jakiegoś czasu zajmuję się programowaniem na platformę mobilną Android i zaczynam się już w niej całkiem dobrze orientować. Nie mogę oczywiście twierdzić, że poznałem ją kompleksowo i od podszewki, ale prawdopodobnie mogę już podzielić się swoimi wrażeniami na jej temat.
A te generalnie są pozytywne. Zalety Androida jako platformy programistycznej mogą podzielić w sumie na dwie kategorie: dostępności i wygody.

Przez dostępność rozumiem tutaj fakt, że pisanie aplikacji na tę platformę nie wymaga żadnych specjalnych wysiłków związanych np. z pozyskaniem SDK czy wręcz urządzenia do testowania. Pakiet programistyczny Androida jest bowiem dostępny za darmo i działa pod każdym sensownym systemem operacyjnym (Windows, linuksy i Mac OS X). To trochę (a w zasadzie zupełnie) inaczej niż w przypadku drugiej porównywalnej, a konkurencyjnej platformy mobilnej, co niewątpliwie działa Androidowi na korzyść. Jeśli zaś chodzi o urządzenie, to do testowania z powodzeniem wystarcza dołączony emulator - o ile tylko dysponujemy odpowiednio mocnym komputerem, który udźwignie działającego w nim małego "Linuksa".
Kiedy jednak już zechcemy przetestować naszą aplikację na rzeczywistym, fizycznym urządzeniu, to i wtedy nie będzie z tym większych problemów. Przy dostępnych pluginów możemy bowiem zintegrować Android SDK z naszym środowiskiem programistycznym (takim jak eclipse czy NetBeans), zyskując dostęp chociażby do pracy krokowej, breakpointów, podglądu zmiennych i innych tego rodzaju narzędzi do debugowania, działających bez problemu także w przypadku aplikacji uruchamianej na zewnętrznym urządzeniu. Rozumiem, że w dzisiejszych czasach nie jest to może nic nadzwyczajnego, ale ja wciąż pamiętam takie, gdy główną metodą znajdowania błędów w aplikacji mobilnej był odpowiednik zwykłego printfa :)

Wygodą programowania pod Androidem przejawia się też w całkiem przemyślanej architekturze systemu i API. Wyjaśnię tu pokrótce, że aplikacje androidowe składają się z komponentów czterech różnych rodzajów, z których prawdopodobnie najważniejszymi są aktywności (activities) i serwisy (services). Te pierwsze to komponenty UI, będące odpowiednikami okienek, form, widoków czy ekranów, zawierających interaktywne kontrolki. Te drugie to procesy działające w tle, mogące np. wykonywać dłuższe czynności takie jak ściąganie z plików.
Ważną cechą wszystkich komponentów aplikacyjnych jest to, że mogą być one tak zadeklarowane, by możliwe było ich użycie także z zewnętrznych programów. Taka komunikacja międzyaplikacyjna odbywa się przede wszystkim za pomocą "magicznych" obiektów typu Intent, zawierających określenie żądanej akcji (np. wyświetlenia listy kontaktów) oraz ewentualne parametry. Komunikacja między poszczególnymi komponentami - nawet w ramach jednej aplikacji - odbywa się głównie za ich pomocą, dzięki czemu możliwe jest prawie automatyczne udostępnienie wybranej części funkcjonalności aplikacji na zewnątrz. No, a przynajmniej taka jest teoria, bo - jak można się domyślić - bardzo typowym błędem w programach androidowych jest to, że "Intenty nie dochodzą" ;-)
Dostępne dla programisty API też wygląda całkiem przyjemnie; wydaje się klarowne i przemyślane. Ma też niewątpliwą zaletę w postaci posiadania doskonałej dokumentacji, bez problemu porównywalnej chociażby z MSDN Library. Dobrze wygląda też kwestia dołączania zewnętrznych zasobów (takich jak obrazki czy układy kontrolek) do aplikacji i dostępu do nich w kodzie, który jest niemal tak samo wygodny, jak w przypadku aplikacji okienkowych w .NET-cie.

Ogólnie zatem Android jako platforma programistyczna przedstawia się całkiem przyjemnie - pod jednym wszak warunkiem: że nie wzdrygamy się na myśl o kodowaniu w Javie. Nie ma tu niestety żadnego sensownego wsparcia dla jakiegokolwiek innego języka, poza małą częścią platformy związaną z aplikacjami natywnymi (pisanymi głównie - jeśli nie wyłącznie - w C). To ma oczywiście swoje dobre strony, chociażby w postaci bardzo dużej integracji maszyny wirtualnej z systemem, na czym z pewnością zyskuje wydajność ich obu.
W sumie więc jeśli ktoś posiada odpowiednie urządzenie - albo przymierza się do kupna takowego - polecam zaznajomienie się z platformą Android, bo może być to przyjemne i produktywne doświadczenie koderskie :)

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


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