Prawda o tworzeniu oprogramowania

2007-08-03 8:41

Tworzenie oprogramowania to nie jest lekki kawałek chleba. Zwłaszcza wtedy, gdy zajmujemy się tym komercyjnie, w zespole i jeszcze musimy dostosować się do wymagań klienta. Co wtedy się dzieje, zgrabnie opisuje rysunek, który wczoraj wpadł mi w ręce:

Prawda o tworzeniu oprogramowania

Na pewno jest w tym sporo prawdy :) Szczególnie interesujący z mojego punktu widzenia jest oczywiście czwarty obrazek, ilustrujący wyniki pracy programisty. Nie ma w nim absolutnie nic dziwnego, bo – jak wiadomo: “gdyby murarze budowali domy tak, jak programiści piszą programy, to jeden dzięcioł zniszczyłby całą cywilizację” ;]


Author: Xion, posted under Computer Science & IT » Comments Off on Prawda o tworzeniu oprogramowania

System GUI #1 – Założenia

2007-08-02 14:21

Skoro posiadam już w miarę sprawnie działający moduł odpowiedzialny za grafikę 2D, pora zająć się jednym z jego najważniejszych zastosowań. Bo oprócz menu czy ekranu powitalnego, najważniejszymi dwuwymiarowymi elementami w każdej grze są składowe jej interfejsu użytkownika.

Po co jednak pisać własny system GUI?… Cóż, oprócz uniwersalnej odpowiedzi (“bo tak”) można odrzec, że to po prostu fajne :) W bardziej rozwiniętej wersji uzasadnienie brzmi tak, iż struktura wewnętrzna dobrze napisanego systemu UI to jeden z najelegantszych przykładów zastosowania programowania obiektowego w praktyce. Jest w niej aż gęsto od przeróżnych wzorców projektowych i całość aż kipi od kipi od tego, co nazywam estetyką projektowania.
Tej estetyki niestety będzie mi prawdopodobnie brakować, kiedy później zajmę się już całkiem “trójwymiarowymi” aspektami silnika, jak modelami, organizacją sceny, materiałami, oświetleniem, itd. Zbalansowanie wydajności z przejrzystością interfejsu (i kodu) na pewno będzie wymagało wielu nieprzyjemnych wysiłków…

System UI z D3DX

A zatem z pewną przesadą można powiedzieć, że system GUI będę pisał dla… relaksu :) Wobec takiego postawienia sprawy nie ma rzecz jasna potrzeby odpierania argumentów w stylu: “Przecież to nie jest potrzebne!”, “W D3DX jest już system GUI (screen powyżej)”, “Dublujesz kontrolki systemowe”, itd. Dla porządku dam aczkolwiek jedno logiczne uzasadnienie: te gatunki gier, które najbardziej lubię – a więc RPGi, strategie czy gry ekonomiczne – wykorzystują UI w dużych i różnorodnych ilościach. Więc jeśli kiedyś… no ale do tego chyba przejdziemy znacznie później :]

GUI jest jedną z tych rzeczy, które można rozbudowywać właściwie w nieskończoność. Dlatego przydałoby się od razu ustalić założenia, jakie chciałbym spełnić. Przede wszystkim nie chcę mnożyć kontrolek ponad potrzebę, gdyż sądzę, że w dużej części przypadków do szczęścia wystarczą poniższe cztery:

  • etykieta (label) – czyli kontrolka ze statycznym tekstem
  • przycisk (button)
  • pole tekstowe (edit, textbox)
  • pole wyboru (checkbox) – kontrolka umożliwiająca włączanie/wyłączanie opcji

Faktycznie przydałaby się jeszcze jakaś kontrolka listowa, ale na razie dla prostoty chcę ją pominąć.
Oprócz samych kontrolek ważne jest też odpowiednie ich zachowanie się. Przede wszystkim chodzi tu o kwestię fokusu klawiatury czy capture myszki, a także funkcjonalności klawisza Tab. Krótko mówiąc, chciałbym żeby mój system przypominał UI, które na co dzień można spotkać w Windows.

Tyle że moje UI nie musi być wcale takie “piękne” jak Aero z Windows Vista ;P

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

Jak się liczy wartość FPS

2007-08-01 13:32

Pod koniec notki na temat czcionek i wyświetlania tekstu stwierdziłem, że podstawowym zastosowaniem tej części biblioteki 2D jest wyświetlanie licznika FPS :) No cóż, pewnie wcale nie byłem daleko od prawdy, bo – jak wiadomo – pomiar ilości generowanych na sekundę klatek jest bardzo ważny. Można to jednak robić na kilka sposobów.

Najprościej jest chyba policzyć czas generowania ostatniej klatki w sekundach – i tak jest to potrzebne do wyliczenia nowych pozycji obiektów i uaktualnienia całej reszty symulacji. Odwrotność tego czasu będzie chwilową wartością FPS.
Można też policzyć ilość klatek narysowanych w jakimś krótkim odstępie czasu poprzedzającym chwilę obecną – zwykle w ciągu jednej sekundy. Wtedy podzielenia owego czasu przez zliczoną ilość ramek da nam średnie FPS.
Wreszcie można te obliczenia prowadzić od momentu uruchomienia gry, śledząc liczbę klatek i całkowity czas jej działania. Wówczas iloraz tych wartości da nam całkowite FPS.

Która wartość jest najlepsza do pokazania na ekranie?… Wartość chwilową najłatwiej wyliczyć, ale zmienia się ona co klatkę, więc podlega przypadkowym wahaniom, niemającym związku z kodem samej gry. Poza tym tak częsta aktualizacja sprawiałaby, że nie dałoby się tej wartości odczytać. W praktyce trzeba by więc wypisywać ją rzadziej, np. co sekundę, co komplikuje sprawę.
Z kolei całkowite FPS ze względu na swój globalny charakter “spłaszcza” wszelkie wahania. Im dłużej działa gra, tym mniejszy jest związek między jego wartością, a tym co widać na ekranie. Może się więc zdarzyć, że gra będzie strasznie przycinała, podczas gdy całkowite FPS będzie stało na wartościach 60-70 z lekką tylko tendencją spadkową.

Najlepiej jest więc pokazywać średnie FPS wyliczone dla jakiegoś krótkiego odcinka czasu. Ponieważ jego wartość zmienia się często (zazwyczaj co sekundę), dobrze odzwierciedla aktualną szybkość generowania klatek. Zmiana parametrów sceny (ilość wielokątów, światła, cienie, odbicia, cząsteczki, pozycja kamery, itd.) może więc prawie natychmiast przełożyć się na wartość FPS. Negatywnie, rzecz jasna :]
Jednocześnie średnie FPS nie podlega tak bardzo chwilowym i losowym zatorom na linii procesor-RAM-karta graficzna, gdyż jest liczone na podstawie przynajmniej kilkudziesięciu próbek.

I chociaż średnie FPS liczy się w nieco bardziej skomplikowany sposób niż chwilowe, jego wyznaczenie nie jest niczym trudnym ani kosztownym:

  1. UInt Frames = 0;
  2. Time time1 = GetTime(), time2;
  3. Time fpsTime = 0;
  4. while (!bClosing)   // główna pętla
  5. {
  6.   time2 = GetTime();
  7.   Time dt = time2 - time1;     // czas generowania ostatniej klatki
  8.   time1 = time2;
  9.  
  10.   // rysowanie klatki
  11.   Update (dt);
  12.   Render();
  13.  
  14.   ++Frames;
  15.   fpsTime += dt;
  16.   if (fpsTime >= 1.0)     // minęła sekunda
  17.   {
  18.     FPS = fpsTime / Frames;
  19.     fpsTime = 0;
  20.     Frames = 0;
  21.   }
  22. }

Jedno jest pewne: wartość FPS nie powinna spadać od samego jej liczenia ;)

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

O dwóch funkcjach do ścieżek

2007-07-31 14:53

Kolejnymi kawałkami kodu z poprzedniej wersji mojej biblioteki uniwersalnej, którym postanowiłem się przyjrzeć, były różnego rodzaju funkcje “systemowe”. Nazwa jest może trochę na wyrost, jako że dotyczyły one głównie pewnych operacji na plikach i ich nazwach. Wśród z nich znalazły więc procedury do pobierania nazw plików, ich rozszerzeń, sprawdzania istnienia plików, tworzenia całych ścieżek katalogów i tym podobne.

Ostały się też dwie najciekawsze funkcje o bardzo podobnych do siebie sygnaturach:

  1. String AbsoluteToRelativePath(const String& strBase, const String& strTarget);
  2. String RelativeToAbsolutePath(const String& strBase, const String& strTarget);

Wykonują one interesującą pracę: konwertują ścieżki względne na bezwzględne i odwrotnie. Jak wiadomo, ścieżka bezwzględna określa położenie w systemie plików w sposób jednoznaczny, np.:

  • C:\Program Files\Taphoo

oznacza podkatalog Taphoo w katalogu Program Files na dysku C – niezależnie od tego, gdzie się teraz znajdujemy. Natomiast ścieżka względna – taka jak ta:

  • ../images/logo.gif

mówi jedynie, że w celu dostania się do pliku logo.gif należy wyjść do nadrzędnego katalogu (..), a stamtąd przejść do katalogu images.

Do czego może przydać się konwersja między oboma typami ścieżek? Dobrym przykładem jest dyrektywa #include w C(++), która akceptuje ścieżki względne:

  1. #include "../Base/StrUtils.hpp"

Preprocesor musi jest rozwinąć, aby móc wstawić zawartość dołączanego pliku. Z użyciem wymienionej wyżej funkcji RelativeToAbsolutePath można łatwo dodać podobną dyrektywę do języka opisu lub skryptowego.

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

Błysk Flasha

2007-07-31 9:03

Dawno temu programowanie było jedynym sposobem na sklecenie jakiejkolwiek gry. Przed mniej więcej dziesięciu laty pojawiły się tzw. clicki, czyli programy mające w założeniu umożliwić tworzenie nawet skomplikowanych gier każdemu bez konieczności nauki programowanie. Idea może i szczytna, ale raczej mało realna, więc nic dziwnego że większość programów z tej kategorii ma dość żałosne możliwości.

Jest tylko jeden zadziwiający wyjątek, który jednak pierwotnie był pomyślany do zupełnie innych celów. Mówię o Flashu: początkowo przecież technologia ta była przeznaczona do tworzenia wektorowych animacji, np. bannerów reklamowych. Teraz wbudowany tam język ActionScript jest tak rozwinięty, że gry flashowe na stronach WWW już dawno przestały dziwić.

Screen z gry 3d Logic Screen z gry Tangerine Panic Screen z gry Flight of the Hamsters Screen z gry N

Ostatnio zobaczyłem jednak coś zupełnie niespotykanego. Mam tu na myśli grę Dofus, napisaną we Flashu i należącą do gatunku… MMORPG. Działa znakomicie, oferując wszystko co wymagamy od gier tego gatunku: obszerny świat do zwiedzania, zróżnicowanie klas, sporo potworków i questów, sprawna komunikacja między graczami, granie w drużynach, przynależność do gildii, itd. Niesamowite, że wszystko to działa na warstwach graficznych i jest kontrolowane ActionScriptem!

Screen z gry Dofus

Takie produkcje sprawiają, że czasem można lekko zwątpić, czy programowanie jest oby na pewno słuszną drogą… Na szczęście wystarczy spojrzeć na kilka dobrych, “normalnych” gier żeby wiara powróciła ze zdwojoną mocą :)

(Cztery gry ze screenów można zobaczyć tutaj: 3D Logic, Tangerine Panic, Flight of the Hamsters, N.)

Tags:
Author: Xion, posted under Games, Internet » 1 comment

Czcionki i tekst(ury)

2007-07-30 9:08

Żadna porządna biblioteka do grafiki 2D nie może obyć się bez narzędzi służących do wypisywania tekstu. Kiedy jednak mamy na uwadze głównie programowanie gier (lub pokrewnych aplikacji), sprawa wygląda nieco inaczej niż w bardziej “ogólnych” zastosowaniach. Nie trzeba na przykład rozkładać tekstu na czynniki pierwsze:

Linie pisma

Pozwalałoby to oczywiście w razie potrzeby dodać kursywę, pod-, nad- i przekreślenie. Zazwyczaj jednak nie jest to potrzebne.

Tak więc chociaż wygląda to na krok wstecz, stosuje się najczęściej czcionki bitmapowe. Pomysł polega na tym, że cały używany zestaw znaków danego kroju i danej wielkości jest rysowany na jednej teksturze w taki sposób, by łatwo można było obliczyć pozycję każdego znaku:

Tekstura czcionki Arial stworzona programem Bitmap Font Builder Tekstura czcionki Verdana stworzona programem Bitmap Font Generator

Wyświetlanie napisu polega wtedy na renderowaniu oteksturowanych prostokątów – po jednym dla każdego znaku. Jest to bardzo wydajne, bo chociaż trójkątów może być bardzo dużo, to ich tekstura jest zawsze taka sama. Można zatem wyrzucić całe połacie tekstu na ekran tylko jednym wywołaniem Draw[Indexed]Primitive.

Tylko skąd wziąć taką sprytną teksturę? Można rzecz jasna generować ją samemu przy pomocy funkcji GDI; choć jest to wolne, byłoby wykonywane tylko raz, więc nie stanowiłoby problemu. Lepszym rozwiązaniem jest użycie odpowiednich programów, z których najlepszym jest chyba Bitmap Font Generator. Potrafi on w sprytny sposób upakować w jednym obrazku sporą ilość znaków, zaś ich parametry opisuje w łatwym do odczytania formacie tekstowym przypominającym szczątkowy INI.

Obecnie używam więc właśnie jego i dzięki temu mogłem w końcu dodać do swojego silnika podstawowy i zupełnie niezbędny element: licznik FPSów :)

Pieszy, kryj się!

2007-07-28 8:56

Zielony listekJedyne co chciałbym zrobić w niniejszej notce, to bezwstydnie się pochwalić :) Sądzę bowiem, że okazja jest najzupełniej wystarczająca. Wprawdzie mam już za sobą maturę i cztery sesje egzaminacyjne na studiach, jednak muszę przyznać, że były one z spacerkiem w porównaniu z egzaminem na prawo jazdy :]

Na szczęście wczoraj udało mi się przejść i przez to – za drugim razem! Skutek jest oczywiście taki, że po tym wydarzeniu niezbyt bezpieczne polskie drogi staną się pewnie jeszcze gorsze ;D


Author: Xion, posted under Life » 6 comments
 


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