Monthly archive for August, 2009

Trzeci dodatek do WoW-a

2009-08-22 21:53

Przez ostatni tydzień byłem na małych wakacjach, więc nie zajmowałem się niczym na tyle pożytecznym, by dało się o tym tutaj napisać ;] Ale na szczęście w międzyczasie zdarzyło się coś, o czym zdecydowanie warto wspomnieć.

Wczoraj mianowicie potwierdziły się spekulacje odnośnie kolejnego, trzeciego już dodatku do gry World of Warcraft. Rzecz była w sumie do przewidzenia, bowiem – podobnie jak dwa poprzednie – i to rozszerzenie zostało oficjalnie ogłoszone podczas BlizzConu. Co tam więc nowego ma zostać dodane do świata Azeroth?…
Ano odpowiedź brzmi: prawie nic albo niemal wszystko. W przeciwieństwie do poprzednich dodatków, ten nie doda żadnego nowego, dużego kontynentu do zwiedzania przez wysokopoziomowych graczy, a jedynie kilka nowych, mniejszych lokacji rozsianych po świecie. Tenże świat ma być jednak gruntownie przekształcony w wyniku tajemniczej i niezwykle brzemiennej w skutkach katastrofy – kataklizmu. Taki jest zresztą tytuł rozszerzenia – World of Warcraft: Cataclysm. Sprawcą całego zamieszania ma tu być Deathwing – pewien niezbyt przyjemny czarny smok, którego niektórzy może pamiętają z Warcrafta 2.
Jak widać, fabularnie prezentuje się to tak sobie, ale ciężko oczekiwać po tylu latach jakiejś wielkiej kreatywności :) To co bardziej interesujące, to oczywiście zmiany w samej grze, które dodatek ma przynieść. A są one następujące:

  • podniesienie maksymalnego poziomu postaci do 85
  • mniejsze lub większe zmiany w większości lokacji na dwóch starych kontynentach (tu coś zalane, tam jakiś wulkan wybuchnie, itp. ;]) oraz dodanie kilku nowych lokacji; częścią zmian będzie miedzy innymi umożliwienie swobodnego latania w “starym” świecie
  • dwie nowe rasy: Gobliny dla Hordy i Worgeni (takie wilkołaki) dla Sojuszu
  • wprowadzenie nowych kombinacji ras, które wcześniej nie były dostępne, np. Troll Druid czy Nocny Elf Mag
  • nowa poboczna profesja – Archeologia, pozwalająca na szukanie starożytnych skarbów i otrzymywanie za nich różnych nagród
  • nowe ścieżki rozwoju nie tylko dla postaci, ale i dla gildii – łącznie z Osiągnięciami (Guild Achievements), a nawet talentami
  • uproszczenie statystyk przedmiotów, usuwające z nich niektóre drugorzędne atrybuty, jak Attack Power czy Spell Power

Część zmian wydaje się drobna, gdyż tak naprawdę są fragmentem dość długiej listy niewielkich, acz ciekawych modyfikacji, które dodatek ma przynieść; wybrałem te, które wydały mi się najważniejsze. Widać oczywiście, że są też i większe nowości, ale nietrudno zauważyć, że brak wśród nich jednej z bardziej oczekiwanych – nowej klasy. Jej w Kataklizmie nie uświadczymy.

   

Tak w dużym skrócie całość się przedstawia i trudno byłoby zaprzeczyć, że wygląda to całkiem ciekawie. Osobiście wydaje mi się, że to właśnie rozszerzenie może być decydujące dla dalszych losów gry. Jeśli okaże się, że lifting starych, liczących sobie już prawie 5 lat krain wypadł pomyślnie, może to przyciągnąć jeszcze większą liczbę graczy i zapewnić WoW-owi pozycję lidera na kolejne kilka lat – czyli mniej więcej na tyle, na ile rozciągają się prawdopodobne plany kolejnych 2-3 dodatków. (Tę liczbę można wywnioskować z tempa podnoszenia maksymalnego poziomu postaci i niedwuznacznych sugestii Blizzarda, że poziom 100 będzie ostatnim). Nie muszę pewnie dodawać, że szansa na to, iż będzie inaczej Cataclysm okaże się komercyjną klapą, są – znając Blizzarda – baaardzo małe :)

Jak będzie w rzeczywistości, zobaczymy pewnie gdzieś w okolicach końcówki przyszłego roku. Ja mam tylko nadzieję, że Starcraft 2 będzie wydany wcześniej ;D

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

Gdzie jest pasek zadań

2009-08-10 15:11

Programy działające w tle (np. komunikatory) często używają różnego rodzaju “wyskakujących” powiadomień, które w założeniu mają pojawiać się tuż obok zasobnika systemowego (system tray), gdzie wspomniane programy mają swoje ikonki. W rzeczywistości pozycja tych komunikatów jest często hardcode‘owana w okolicach prawego dolnego rogu ekranu. Jeśli więc użytkownik przypadkiem ma pasek zadań gdzie indziej, to wtedy cały misterny plan idzie w… las ;]
Dlatego lepszym rozwiązaniem jest sprawdzanie, gdzie tak naprawdę ów pasek się znajduje. Przez długi czas można było to zrobić poprzez zwyczajne pobranie jego uchwytu (HWND) i odczytanie wymiarów tak, jak każdego innego okna – np. przez GetWindowRect:

  1. HWND hTaskBar = FindWindow(TEXT("Shell_TrayWnd"), NULL);
  2. // "Shell_TrayWnd" to klasa okna specyficzna dla paska zadań
  3. RECT rc; GetWindowRect (hTaskBar, &rc);

Począwszy od Windows Vista nie jest to jednak możliwe, gdyż ze względu na bezpieczeństwo (tzw. izolacja sesji 0) nie da się już tak po prostu pobrać uchwytu do paska zadań ze zwykłej aplikacji. Istnieje na szczęście przenośny sposób na pobranie jego pozycji; w tym celu trzeba się posłużyć funkcją powłoki systemowej SHAppBarMessage (z nagłówka shellapi.h i biblioteki shellapi.lib):

  1. UINT GetTaskBarPos(LPRECT rc)
  2. {
  3.     APPBARDATA abd = { sizeof(APPBARDATA), NULL };
  4.     if (!SHAppBarMessage(ABM_GETTASKBARPOS, &abd)) return 0;
  5.     if (rc) memcpy (rc, &abd.rc, sizeof(RECT));
  6.     return abd.uEdge;
  7. }

Tak możemy otrzymać nie tylko wymiary prostokąta okalającego pasek, ale też informację o tym, przy której krawędzi się on znajduje. Jest ona zawarta w polu uEdge struktury zwracanej przez funkcję SHAppBarMessage i równa którejś ze stałych ABE_BOTTOM, ABE_TOP, itd.

Mając te dwie informacje możemy nie tylko wyświetlać nasze powiadomienia w odpowiednim miejscu, ale też zapewnić, żeby w razie ich nagromadzenia “rosły” one w odpowiednim kierunku.

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

Typ zwracany funkcji wirtualnej

2009-08-04 16:42

Kiedy w klasie pochodnej piszemy nową wersję funkcji wirtualnej, to w C++ powinniśmy zawsze uważać na to, żeby jej nagłówek był identyczny z tym, który zdeklarowano w klasie bazowej. To dlatego, że składnia języka nie wymaga w tej sytuacji żadnego słowa kluczowego w rodzaju override. Jeśli więc coś nieopatrznie zmienimy, to nie uzyskamy nowej wersji funkcji, tylko zupełnie nową funkcję przeciążoną:

  1. class Foo
  2. {
  3.     public: virtual void Do(int x, int y, int z) { }
  4. };
  5.  
  6. class Bar : public Foo
  7. {
  8.     // to *nie* jest nowa wersja Foo::Do, tylko zupełnie inna funkcja
  9.     public: void Do(int x, int y, string z) { }
  10. };

Taki efekt jest jest w gruncie rzeczy oczywisty i łatwy do zrozumienia. Pewnie więc będzie nieco zaskakujące dowiedzieć się, że tak naprawdę postać funkcji wirtualnej w klasie pochodnej może się trochę różnić, a mimo to wciąż będziemy mówili o tej samej funkcji.

Jak to jest możliwe?… Dopuszcza się mianowicie różnicę w typie zwracanym przez nową wersję funkcji wirtualnej. Może on być inny od typu zwracanego przez wersję z klasy bazowej – ale tylko pod warunkiem, że:

  • pierwotny typ był wskaźnikiem lub referencją do klasy (a nie chociażby typem podstawowym, jak int)
  • nowy typ zwracany jest – odpowiednio – wskaźnikiem lub referencją do klasy pochodnej od tej z typu pierwotnego
  • nowy typ posiada tę samą kwalifikację const/volatile co typ pierwotny

Przykładowo więc, jeśli w klasie bazowej funkcja wirtualna zwraca const A*, to w klasie pochodnej może zwracać const B*, o ile klasa B dziedziczy publicznie po A. Nie może za to zwracać samego B* (niestałego) lub const X*, gdy klasa X jest niezwiązana z A.

Do czego taki “myk” może się przydać? Najczęściej chodzi tutaj o sytuacje, gdy mamy do czynienia z równoległym dziedziczeniem kilku klas, które na każdym poziomie są związane ze sobą. Mogę sobie na przykład wyobrazić ogólny menedżer zasobów w grze, którego metoda wirtualna Get zwraca wskaźnik na bazową klasę Resource, a następnie bardziej wyspecjalizowany TextureManager, który w tej sytuacji podaje nam wskaźnik na Texture. (Oczywiście klasa Texture w założeniu dziedziczy tu po Resource). Czasami coś takiego może być potrzebne, aczkolwiek takie równoległe hierarchie dziedziczenia nie są specjalnie eleganckie ani odporne na błędy.
Lepszym przykładem jest wirtualny konstruktor kopiujący: metoda, która pozwala na wykonanie kopii obiektu bez dokładnej znajomości jego typu. Zwyczajowo nazywa się ją Clone:

  1. class Object
  2. {
  3.     public:
  4.         virtual Object* Clone() const { return new Object; }
  5. };
  6.  
  7. class Foo : public Object
  8. {
  9.     public:
  10.         // nowa wersja metody Object::Clone
  11.         Foo* Clone() const { return new Foo; }
  12. };

Dzięki temu że metoda jest wirtualna, można ją wywołać nie znając rzeczywistego typu obiektu (co nie jest możliwe w przypadku zwykłych konstruktorów, które w C++ wirtualne być nie mogą). W wyniku jej wywołania otrzymamy jednak tylko ogólny wskaźnik Object* na powstałą kopię obiektu.
Gdybyśmy teraz nie zmienili typu zwracanego przez metodę w klasie pochodnej, to klonowanie podobne do tego:

  1. void Function(Foo* foo)
  2. {
  3.     Foo* copy = foo->Clone();
  4.     // ...
  5. }

wymagałoby dodatkowego rzutowania w górę, by mogło zostać przepuszczone przez kompilator.

Tags: , , , , ,
Author: Xion, posted under Programming » Comments Off on Typ zwracany funkcji wirtualnej
 


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