środa, 13 października 2010

The PIMPL Pattern

The PIMPL this is a "private implementation". This pattern is useful to cut a time of compilation.

Advantages:
We don't need attach a lot of headers file to another header file.
We reduce a time of compilation.

Disadvantages:
For each object we must create one dynamic object.

How can we implement it ?

Look at this simple header file :

//Height map header
#include "Camera.h"
#include "Hero.h"
//etc.

class HeightMap{
   private:
   Camera camera;
   Hero hero;
   //etc.
};

We see that we must attach a few headers.
We can create a promising declaration, but we can create by this only a dynamic object.

We can solve this problem by private implementation. There is example of this solution:

//Height map header

class HeightMap_pimpl;

class HeightMap{
private:
   HeightMap_pimpl* pimpl;
};

//cpp file
#include "Camera.h"
#include "Hero.h"

class HeightMap_pimpl{
private:
   Camera camera;
   Hero hero;
}

HeightMap::HeightMap(){ pimpl = new HeightMap_pimpl; }

And that' s it. This is really simple and useful. We can also use a smart pointer from my general library to avoid responsibility to delete an allocated object :

class HeightMap{
private:
   scoped_ptr pimpl;
};

See you  later

niedziela, 10 października 2010

Simple resource manager

Hi!

Today I want to show you my simple resource manager. I never earlier have been writing similar mechanisms.

What is it?

A resource manager let us use frequently the same resource. But what can be a resource ? A lot of things can be a resource. The best example is file (model file, texture file, etc.). We can have a lot of object which refer to the same texture/model but we really have only one resource of texture/model. Below drawing show it :


My resource class look like below:

class IResource{
private:
    uint4 countLock;
    float lastUseTime;
    STATE_RES state;
    string name;
    string group;
protected:
    //Wywoływane podczas ładowania
    virtual void OnLoad() {}
    //Wywoływane podczas odładowywania
    virtual void OnUnload() {}
public:
    IResource(){}
    IResource(const string &Name, const string &Group = "");
    virtual ~IResource();
    void Load();
    void Unload();
    void Lock();
    void Unlock();
    const string& GetName() { return name; }
    const string& GetGroup() { return group; }
    STATE_RES GetState();
};

Each resource have own name. By this name we get a pointer to resource. Optionally each resource may have a group name. For example all files of texture may have name group : "texture" etc.

My resource manager is writing as Singleton. He provides functions to get a resource with the given name. This function is template, so we can get ever resource any type. And that's it. Manager haves a few function more, but I won' t describe it, you can download all source code below.

ATTENTION: You should create resource objects  in some function, but no as global objects because probably the program will return a mistake.

Use of my manager

Below example shows use of my manager :

class Texture : public library::IResource{
//some data like pixels
public: Texture(const string& name, const string& group = "") : library:IResource(name, group) {}
}

void LoadAllResources(){
   Texture texture1("myTexture.bmp, "Texture");
 }

int main(){
   BindTexture( ResManager::GetResource("myTexture.bmp);
}
library:: this is my namespace where we can find all class of resource manager.
I strongly believe that this isn't hard.

Here you can download a source code.

Greetings.

niedziela, 3 października 2010

Biblioteka generalna

Opiszę tutaj pokrótce najniższą warstwę mianowicie bibliotekę generalną.

Kod tej biblioteki odpowiedzialny jest za uzupełnienie jakby, niektórych braków w c++.

Większość kodu mieści się w przestrzeni nazw general.

Moduł Base
Moduł ten zawiera nazwy podstawowych zmiennych (np unit8 to liczba bez znaku 64 bitowa).

Posiada niektóre funkcje i stałe matematyczne, których brak w C++. Są to m.in przeliczanie radianów na stopnie i odwrotnie, zaokrąglanie liczb, szybkie potęgowanie dla potęg całkowitych (w czasie O(lg n)), częśc całkowitą i ułamkową liczby itp. Posiada funkcję timera.

Zostały napisane (a raczej skopiowane) funkcje przekształcające z jednego typu do stringa i odwrotnie. Jest również funkcja szablonowa SthToStr i StrToSth konwertująca z jakiegoś typu do stringa i ze stringa do jakieś typu.(Autor: Adam Sawicki)

Zawiera 2 implementacje inteligentnych wskaźników (jedna nie pozwala kopiowania obiektu, a druga umożliwia kopiowanie i prowadzi politykę zliczania (wskaźnik jest usuwany gdy nie wskazuje na niego żaden inny obiekt)Autor: Adam Sawicki).

Ostatnim element to klasa Format, która zwraca tekst w stawionymi liczbami np Format("a = " % 5) zwróci nam tekst ("a = 5") (Autor: Adam Sawicki).

Moduł Error Umożliwia nam hierarchię błędów i zawiera funkcję ErrorMessage, która powoduje wyświetlenie komunikatu z błędem przesłanym jako string.

Moduł Event zawiera zdarzenia (narazie jest zaimplementowane zdarzenie, które jest uruchamiane po upływie określonego czasu.

Moduł File - udostępnia klasę, która operuje plikiem. Działa podobnie jak klasa fstream, lecz jest sporo prostsza i około 2 razy szybsza.

Moduł Math - moduł matematyczny (udostępniany wcześniej)

Moduł Tokenizer - jest to klasa, która w znaczny sposób upraszcza wydobywanie informacji z ciągu znaków. Jej działanie sprowadza się do zwracania zmiennych odpowiedniego typu z podanego ciągu wejściowego.
Działa to tak :

Tokenizer t("to jest liczba 123");
cout << t.GetStringNext() << endl;
cout << t.GetStringNext() << endl;
cout << t.GetStringNext() << endl;
cout << t.GetIntNext() << endl;

To powyższe linie kodu wypiszą nam w osobnych liniach każdy wyraz ciągu podanego w konstruktorze obiektu. Jest to jakby strumień stringstream z biblioteki standardowej c++, przy czym działa szybciej.

Na razie to tyle co oferuje nam biblioteka generalna.

Jej kod znajduje się do ściągnięcia TUTAJ.

Pozdrawiam Norbert G.

piątek, 1 października 2010

Reorganizacja projektu

Dłuższy czas nie pisałem, gdyż tak naprawdę całą organizację projektu zmieniłem. Myślałem, że dam to robić  na bieżąco, podczas rozwijania projektu ale to był zły pomysł. Już na samym początku miałem sporo problemów, a co dopiero działo by się potem. Dlatego uważam, że taka organizacja przyniesie wiele dobrego.

Pomocnym przy tym była książka "C++ dla programistów gier" oraz praca magisterska Pana Adama Sawickiego (do ściągnięcia z internetu w pdf).
Przede wszystkim wzorowałem się właśnie na powyższej pracy magisterskiej, jak i również zapożyczyłem kilka funkcji z pracy autora.

Na dzień dzisiejszy architektura silnika wygląda następująco :



Widać trzy główne osobne biblioteki. Na samym dole jest Biblioteka generalna, poźniej Obsługa OpenGL (w tym okien i zdarzeń) no i na górnej warstwie jest cały silnik grafiki 3D. Widzimy, że przy tym układzie nie powstają cykle (tzn że jakieś dwie warstwy muszę zależą od siebie), co myślę, że jest dobrą organizacją.
Najmniej dopracowana jest warstwa samego silniku ale to tylko taki prototyp. Jest prawie pewne, że to się zmieni. Na razie chciałbym zająć się warstwami, które składają się na cały engine. W pierwszej kolejności będzie to biblioteka generalna a potem obsługa okna OpenGL no i wreszcie cały engine. Trochę żałuję, że tak późno wziąłem się do zmiany całej architektury. Oczywiście tamten poprzedni kod co napisałem (wczytywanie terenu) na pewno wykorzystam w przyszłości, bo jest to już prawie pełny, kompletny działający kod.

Moduł matematyczny jest zaimplementowany, nic nie zmieniło się w nim od ostatniego update' u.

Pozdrawiam Norbert G.