All english written articles have English article tag and lays under horizontal line. First part is written in Czech.
Zobrazují se příspěvky se štítkemXNA/ŽvB2. Zobrazit všechny příspěvky
Zobrazují se příspěvky se štítkemXNA/ŽvB2. Zobrazit všechny příspěvky

neděle 22. července 2012

XNA a Serializace IV. / XNA and serialization IV.

Původně jsem myslel, že dnes ukáži kus kodu pro provádění samotného ukládání a načítání, ale když jsem odeslal a vypustil do světe poslední článek, došlo mi pak v posteli (mimo jiné nejlepší místo na přemýšlení), že jsem zapomněl napsat jak je to u dědičnosti. Pokusím se to dnes napraviti.
Stejně jako minule uděláme si ukázkové dvě třídy, kdy bude jedna odvozena od druhé.
public class A{
    public A(){
    
    }

    public A(GenericReader reader){
        int version=reader.ReadInt();
        //nacitani hodnot
    }
    
    public virtual void Serialize(GenericWriter writer){
        writer.Write(0);//verze
        //zapis ostatnich hodnot
    }
}

public class B:A{
    public B(){
    
    }

    public B(GenericReader reader):base(reader){
        int version=reader.ReadInt();
        //nacitani hodnot
    }

    public override void Serialize(GenericWriter writer){
        base.Serialize(writer);
        writer.Write(0);//verze
        //zapis ostatnich hodnot
    }
} 

Následující příklad jasně ukazuje co je potřeba provést. Při ukládání metodou Serialize, je nutné pokaždé zavolat metodu od předka. Dále je také důležité aby metoda přepisovala metodu původní, to ale jak jistě milý čtenář ví provedeme klíčovými slovy virtual a override. Načítání hodnot v konstruktorech je běžné. Pouze opět zavoláme konstruktor předka pomocí base. Důležité je vědět, že se nejprve zavolá konstruktor předka a teprve potom konstruktor současný. Proto se nejprve při zápisu volá metoda od předka. Pořadí hraje v binární serializaci důležitou roli!!
Tak a zítra se podíváme konečně na obslužný kod, který napsané metody využije a zavolá.



In today's article I will write about serialization of derived classes. I simply forgot write about them yesterday.
This is our example, let's have two classes A and B:
public class A{
    public A(){
    
    }

    public A(GenericReader reader){
        int version=reader.ReadInt();
        //reading values
    }
    
    public virtual void Serialize(GenericWriter writer){
        writer.Write(0);//version
        //writing values
    }
}

public class B:A{
    public B(){
    
    }

    public B(GenericReader reader):base(reader){
        int version=reader.ReadInt();
        //reading values
    }

    public override void Serialize(GenericWriter writer){
        base.Serialize(writer);
        writer.Write(0);//version
        //writing values
    }
} 

For saving values in Serialize method is important have this method virtual. This is done by keyword virtual and override as usual. Derived class MUST call method from base class and after that write all values. This must be done because of constructors. Constructors are invoked from the most base class (in C# object class) to top most. In binary serialization is order very important.
 See you tomorrow.

sobota 21. července 2012

XNA a Serializace III. / XNA and serialization III.

Včera jsem napsal o třídách, které se postarají o ukládání dat do souborů samotných a dnes se podíváme na to, jak je využít.
Každá třída, která má být serializována na to musí být uzpůsobena. Možností je několik. Já jsem nakonec vybral možnost tuto. Každá třída má virtuální metodu Serialize, ta se stará o ukládání a speciální konstruktor, ten se stará o načítání. RunUO to má kapku jinak, ale tato možnost se mi zdála být lepší. Kupříkladu takto:
using System;

namespace VodacekEngine {
    public class Priklad {
        public Priklad(){
        }

        public Priklad(GenericReader reader){
            int version=reader.ReadInt();
            //zde nacitani promennych
        }
 
        public virtual void Serialize(GenericWriter writer){
            writer.Write(0);//verze, k cemu se pouziva vice dale
        }
    }
}

Verze je pro všechny objekty stejná, vřele doporučuji ji tam mít. Slouží k tomu, když bude potřeba nějakou proměnnou přidat, nebo odebrat. Pokud by tam nebyla nastal by při načítání problém a obsah se načetl špatně, nebo by skončil chybou. Nejčastěji pokus o čtení za koncem souboru.
Pokud chceme přidat novou proměnnou jednoduše zvedneme proměnnou s verzí a do čtení pak na verzi dáme podmínku kupříkladu přidáme naší třídě proměnnou jméno:
using System;

namespace VodacekEngine {
    public class Priklad {
        public string Jmeno;
        public Priklad(){
        }

        public Priklad(GenericReader reader){
            int version=reader.ReadInt();
            if(version>=1)Jmeno=reader.ReadString();
            else Jmeno=null;//nebo jina pocatecni hodnota
        }
 
        public virtual void Serialize(GenericWriter writer){
            writer.Write(1);//<------ zvednuta o 1
            writer.Write(Jmeno);
        }
    }
}

Místo podmínky, lze užít třeba switch a case, důležité je zvednout verzi a číst a zapisovat ve stejném pořadí.
Pokud by bylo potřeba proměnnou Jmeno nopak zrušit, tak opět zvedneme verzi o jedničku. Zapisování proměnné smažeme a upravíme načítání:
using System;

namespace VodacekEngine {
    public class Priklad {

        public Priklad(){
        }

        public Priklad(GenericReader reader){
            int version=reader.ReadInt();
            if(version==1)reader.ReadString();//promennou nacteme, ale neukladame
        }
 
        public virtual void Serialize(GenericWriter writer){
            writer.Write(2);//<------ zvednuta o 1
        }
    }
}
Proměnnou načteme, ale nikam ji neuložíme. (ono taky mezi námi není kam ukládat když ta proměnná neexistuje) Načítání je potřeba provést tak jako tak, jinak hodnoty uložené za touto by byly načteny špatně. Podmínka se také mírně změnila. Tentokráte testujeme pouze na tu jednu verzi ve které se proměnná vyskytovala.
Dalším problematickým případem je ukládání polí. Používá se tam jeden fígl. Pojďme se podívat na naši ukázkovou třídu:
using System;

namespace VodacekEngine {
    public class Priklad {
        public string[] Jmena;
        public Priklad(){
            Jmena=new string[]{"Pepa","Jernom","Kucir","Jelen"};
        }

        public Priklad(GenericReader reader){
            int version=reader.ReadInt();
            if(version>=1){
                int pocet=reader.ReadInt();//nacteme pocet prvku
                Jmena=new string[pocet];//vytvorime pole o poctu prvku
                for(int i=0;i>pocet;i++){
                    Jmena[i]=reader.ReadString();//postupne nacteme prvky pole
                }
            }
            else Jmena=new string[]{"Pepa","Jernom","Kucir","Jelen"};//initializace
        }
 
        public virtual void Serialize(GenericWriter writer){
            writer.Write(1);//<------ zvednuta o 1
            writer.Write(Jmena.Length);//zapiseme pocet prvku
            for(int i=0;i<Jmena.Length;i++){
                writer.Write(Jmena[i]);//zapisuje vsechny prvky
            }
        }
    }
}
Nejprve se zapíše počet prvků pole a poté prvky samotné. Při načítání se načte počet a for cyklem se provede načítání jednotlivých prvků.

Tak to je pro dnešek vše. Příště (snad zítra) se podíváme na kod, který řídí zápis a čtení do souborů a který výše uvedené metody volá.



In my last English article I wrote something about classes that are used to saving and loading types from files. In this article I will write something about implementation of reading and writing code in each class, that is need to be serialized.
Each class have one virtual method Serialize (this method is used to write data to file) and special constructor for reading values from file. RunUO (ultima online emulator) is using slight different idea, but I thing that this is better for our purpose. Let's have this simple example class:
using System;

namespace VodacekEngine {
    public class Example {
        public Example(){
        }

        public Example(GenericReader reader){
            int version=reader.ReadInt();
            //here reading values
        }
 
        public virtual void Serialize(GenericWriter writer){
            writer.Write(0);//version, I will discus it later
        }
    }
}
Variable called version is very important. This variable is used when you want to add or remove some variable from serialization. If this variable don't exist, you can get into some serious trouble.
If we want to add new variable, we must increase version. Here is example with our class:
using System;

namespace VodacekEngine {
    public class Example {
        public string Name;
        public Exammple(){
        }

        public Example(GenericReader reader){
            int version=reader.ReadInt();
            if(version>=1)Name=reader.ReadString();
            else Name=null;//here belong initial value
        }
 
        public virtual void Serialize(GenericWriter writer){
            writer.Write(1);//<------ increased
            writer.Write(Name);
        }
    }
}
If is version grater than one variable is read from file, if not we should initialize it.Writing is more simple. Only version is increased and added new variable.

If we need to remove variable Name simply again increase version and remove writing part. In reading part simply add if statement for last version where variable exist. Something like this:
using System;

namespace VodacekEngine {
    public class Example {

        public Example(){
        }

        public Example(GenericReader reader){
            int version=reader.ReadInt();
            if(version==1)reader.ReadString();//variable MUST be read, but is not stored
        }
 
        public virtual void Serialize(GenericWriter writer){
            writer.Write(2);//<------ increased
        }
    }
}
Removed variable NEED to be read but is not stored. Variable is not exist any more.
Our last example is writing arrays. There is used little trick. Here is our example class:
using System;

namespace VodacekEngine {
    public class Example {
        public string[] Names;
        public Example(){
            Names=new string[]{"Pepa","Jernom","Kucir","Jelen"};
        }

        public Example(GenericReader reader){
            int version=reader.ReadInt();
            if(version>=1){
                int count=reader.ReadInt();//count of items in array
                Names=new string[count];//creates array
                for(int i=0;i>pocet;i++){
                    Names[i]=reader.ReadString();//reading members of array
                }
            }
            else Names=new string[]{"Pepa","Jernom","Kucir","Jelen"};//initialize
        }
 
        public virtual void Serialize(GenericWriter writer){
            writer.Write(1);//<------ increased
            writer.Write(Names.Length);//write count of members in array
            for(int i=0;i<Names.Length;i++){
                writer.Write(Names[i]);//write each member
            }
        }
    }
}
First of all is written count of members in array and then in for loop all members. Version is off course increased. In reading part, is standard if statement for adding values. Then is read count of members in array. Array is created and then in for loop added variables. Really simple.
That is all for today. In next article I will show you code that is used for calling this methods.

pátek 20. července 2012

XNA Serializace den po té / XNA Serialization the day after

Minule sem sepsal jaký máme možnosti a dneska se podíváme jak vlastně na to. Vybral jsem nakonec možnost druhou tedy, jeden soubor s indexem a druhý s daty. Samotné třídy jsem sebral (snad se to může) ze zdrojáků RunUO ze starší verze 2.0 RC1, tedy z té samé kterou používáme na ŽvB. Ti, kteří by se zajímali jak vlastně funguje (nebo jak si to představuju že to funguje) ukládání na již zmíněném RunUO snad také dostanou zajímavé informace. Třídy jsem vypreparoval a upravil tak, aby byly co nejjednodušeji a mohl je každý použít. Stáhnout si je můžete tady. Jak to vlastně celé funguje? Velmi snadno.Veškerou zapisovací parádu obstarávají dvě třídy: GenericReader a GenericWriter. Netřeba vysvětlovat co která asi bude dělat je to zřejmé již z jejich názvů. Třídy lze použít i k jiným možnostem ukládání, které jsem popsal v předešlém článku, možnosti se jen budou lišit samotným kodem, který je určen pro ukládání. Třídy obsahují ukládání základních datových typů se kterými se můžete běžně setkat. Jenže jak uložit třeba Vector2, Vector3 nebo Matrix (tedy matici) a jiné další? Také velmi snadno(jak jinak). Je možné je rozložit na prvky ze kterých jsou složeny. Vector2 na X a Y souřadnici, Vector3 na souřadnice tři, Matrix není nic jiného než 16 float čísel.

public void Write(Vector3 vector){
    if ((m_Index + 12) > m_Buffer.Length) Flush();
 
    Write(vector.X);
    Write(vector.Y);
    Write(vector.Z);
}

public Vector3 ReadVector3(){
    return new Vector3(ReadFloat(), ReadFloat(), ReadFloat());
}

Horší situace nastane pokud budeme chtít ukládat třeba třídu Model, Texture2D a další věci načítané pomocí Content Pipeline. Zde to lze snadno obejít, uložíme pouze jména souborů a ty potom běžně po proběhnutí serializace načteme. Uložit lze i obsah delegátů, ale o triku který jsem na ně vymylel napíši něco později. Jediné na co je potřeba myslet je to, že je nutné zapisovat a číst prvky ve stejném pořadí.

Jak používat tyto třídy opět v dalším článku.



In my last post about basic of serialization I wrote something about possible ways. In this post I want to introduce classes for reading and writing into binary files. I modified classes from RunUO 2.0 RC1 source, that is used as Ultima Online emulator on ŽvB project and add reading and writing code for some XNA classes. Code can be downloaded from here. Reading and writing those types is very simple. Vector2, Vector3 or Matrix are only couple of floats. Vector2 have two X and Y, Vector3 have three and Matrix is only set of 16 floats. Here is example of serialization of Vector3:

public void Write(Vector3 vector){
    if ((m_Index + 12) > m_Buffer.Length) Flush(); 
 
    Write(vector.X);
    Write(vector.Y);
    Write(vector.Z);
}

public Vector3 ReadVector3(){
    return new Vector3(ReadFloat(), ReadFloat(), ReadFloat());
}

Texture2D, Model etc.. (basically all classes that are loaded by content pipeline) classes needs to be stored as strings. Simply write only file names of that assets and then load them by Content Pipeline. Only one thing is important. All parts needs to be written and read in same order.

In next article I will show you my code that handles saving and loading.

pondělí 18. června 2012

Ovladače / Drivers

Nevím ani co mě to popadlo a jal jsem se aktualizovat ovladače grafický karty. Domníval sem se že to pomůže a vše mi poběží ještě lépěji, jak šeredně jsem se spletl. Pěkně spokojený jsem šel žvb 2 vyzkoušet, ale hned záhy jsme utrpěl ledovou sprchu. Z mého krásného terénu (generovaný z výškové mapy) se stal cedník nu posuďte sami (viz obrázek a vídeo pod englickou částí). Problém způsobil poslední Catalyst verze 12.4, když jsem opět nainstaloval starou verzi (12.3) vše funguje normálně. Zajímavé také bylo, že ostatní hry (zaklínač a minecaft) fungovaly normálně, někde je chyba asi v součinnosti s XNA. Podivné. Má někdo stejné nebo podobné zkušenosti?



Today I tryed to update my graphics card drivers to new version. I think that ŽvB 2 (my project) will be running more smoothly with new driver. I was totally wrong. When I try to run my application I got something like this:
Terrain and other models were dissorted and have gaps. I also take a video with it:
Problem was removed by installing older Catalyst 12.3. Interesting was that other applications (witcher and minecraft) runs without any problem. Do you have any similar experience?

pátek 2. března 2012

XNA Serializace / XNA Serialization

Je to vlastně proces při kterém se ukládají objekty do souboru aby se při dalším spuštění programu mohly znovu načíst a dále používat. Bude to použito k ukládání místností v žvb2. Nejčastěji se provádí XML serializace nebo také binární (zápis informací ve dvojkové formě do souboru). XML je docela fajn a dá se snadno editovat, ale já to moc nemusím, nelíbí se mi jak se to cele prochází při zpracování. Nějaké to node a spol. Binární serializace je mi o dost bližší. Používá jej RunUO které používá žvb1. Každá třída má svou metodu serialize a deserialize ve které provádí zápis ale také čtení z datového proudu. Hodnoty musí být zapsány a potom vyzvednuty ve stejném pořadí to je snad jediné úskalí této metody. Já jsem nakonec vzal právě binární serializaci přímo z RunUO a jen ji trochu promazal a upravil. Snad se to smí. Níže je jakási moje úvaha o tom jaký způsob přesně použít. Jsou v zásadě 3 o kterejch jsem uvažoval aniž bych musel číst nebo hledat řešení od někoho jiného, jak to obvykle dělám.

do jednoho souboru:
bin soubor
Typ komponenty
data

Při chybě nebo ztrátě typu máme totální smůlu a je to celé v háji.

do dvou souboru:
bin soubor                                         idx soubor
    data                                                       typ
                                                          start záznamu
                                                         délka záznamu

Při ztrátě typu nebo chybě přeskočíme daný blok a pokračujeme dalším. Při chybě v indexu máme smůlu.

do tří souborů - ala RunUO:
bin soubor                         idx soubor                         pdb soubor
data                                       id typu                             typy podle id
                                         start záznamu
                                        délka záznamu
Při ztrátě typu se prostě jen ignoruje to dané id, při chybě v indexu máme smůlu.



Serialization is process that save objects states into file/s and than load them and use them in future. Most common ways is use XML or writing binary files. XML is quite good, it can be simply edited with normal text editor, but I don't like way of parsing files with nodes. So I choose binary files. I have some good experiencis with this way (žvb 1 emulator RunUO used this) and is possible simply correct errors such as mising type of component or error in getting values. Each class that can be serialized have special constructor and two methods Serialize and Deserialize. Thats all that is requred. Only disandvatage is that variables must be saved and loaded in same order. So I chose binary serialization from RunUO and make some small corrections. I will post another blog entry when I think that is all working properly. Firt, I must choose one of three methods that I know.

to one file:
bin file
Component type
data

When error is occoured all date are lost

to two files:
bin file                                                   idx file
    data                                             Component type
                                                   start position in stream
                                                         length of stream

When error is occoured we can easily skip demaged area and try to continue with loading. If error is in index file everything is lost

do tří souborů - ala RunUO:
bin file                                 idx file                                pdb file
data                                    id of type                        type of component
                                start position in stream
                                      length in stream

Same as above but we have types saved in extra file. Missing types can be easily skipped by id.

pondělí 13. února 2012

Nové video - normály jako světlo / New video! Normals used as light

Když jsem se včera večer pokoušel znovu vyřešit stále trvající problém s projektorem (projective texturring se to menuje) a jako jeden výsledek mi vylezlo toto, tak jsem neváhal a dnes ráno to natočil. (vídeo je pod englickou částí) Jednoduše jsem použil normály modelů jako barvy, je to docela pěkné na pohled co myslíte?



Yesterday, I tryed to solve my almost half year problem with projective texure in my Light Pre-pass renderer. As one of my results I got this. (video is below) I simply used normal as light color. Isn't it look good?

středa 8. února 2012

Jak dostat zpět obsah Z-bufferu / How to Restore Depth Buffer in XNA

Po dlouhý době konečně zase další programátorský příspěvek a snad i englicky. Docela dlouho mě todle trápilo (snad i půl roku), dokonce jsem si na to položil otázku ZDE, ale bohužel bez výsledku. Až se konečně předevčírem poštěstilo a nalezl jsem TENTO článek, jak jinak než při řešení jiného problému jak to tak bývá. Základem úspěchu je mít hloubku uloženou v textuře (toto jsem již měl protože to používám pro věc zvanou light pre-pass) a tu potom projet speciálním shaderem popsaným v článku.

void PixelShaderFunction(in float2 texCoord:TEXCOORD0,
 out float4 color:COLOR0, out float depth:DEPTH){
    color=float4(0,0,0,0);
    depth=tex2D(DepthSampler, texCoord).r;
}

Tato část provádí ono kouzlo, protože zapisuje námi uloženou hloubku ale barvu ne (před vykreslením jsem povolil alfa blending). A to je kupodivu všechno. Jak prosté že ano? :-)



I am back! Here is another english post this time with XNA theme. Problem how to restore Depth Buffer was with me almost half of a year. I post THIS question, but without any good answer. Finally tomorrow I found it! In this article I have found everything that I need to know. First you need to have depth stored in texture (I already have this from Light Pre-Pass) and use special shader described in article.

void PixelShaderFunction(in float2 texCoord:TEXCOORD0,
 out float4 color:COLOR0, out float depth:DEPTH){
    color=float4(0,0,0,0);
    depth=tex2D(DepthSampler, texCoord).r;
}

This part of code wites only depth and don't affect color (before drawing enable alpha blending). That's it!

sobota 14. ledna 2012

XNB soubor a základní informace / XNB file basic information

Před časem (rozuměj včera) jsem dostal najednou neodkladnou potřebu pro editor na ŽvB 2 vědět jak dostat informaci z XNB souboru co je zač. Zda-li je v něm uložena textura, nebo model a podobně. Naštěstí je dostupná jakási dokumentace formátu tohoto souboru ZDE všechno se zdálo být docela snadné pěkně jsem si plánoval jak soubor načtu, podívám se pro co je (windows, mobil, xbox) pro jaký je určen profil (HiDef, Reach) a potom konečně to po čem jsem nejvíc toužil, co je vůbec zač. Ale ejhle. Nemělo to být tak snadné a taky že nebylo (doteďka jsem na zjištění této informace krátkej). Cože to že jsem selhal? Může za to něco co se jmenuje ,,Xbox XMemCompress API". O této skoro až mystické věci se nikde nic nedozvíte. Naštěstí takto nejsou ošetřeny soubory vždy. Pouze v realise modu. Takže skoro vždycky jsem schopnej dostat základní informace. To pro začátek snad i stačí. Kompletní kod jde stáhnout TU.Jedná se jen o třídu co si sama informace ze souboru vycucne a potom je má v sobě uložený. Jak se to dá snadno použít je ukázáno v tom pragramu. Snad to pro někoho bude užitečný.



Tomorrow I was working little bit on my game editor for ŽvB 2. And I want to get some information about XNB files before loading them. Fortunatelly there is file format specification and it can be downloaded from HERE. With this I am able to get target platform (Windows, Mobile, XBox), profile (HiDef, Reach), version and if file is compressed od not. Main information I am seek for is type of the sousce file. If it si texture or model or something else. Unfortunatelly this information is in most situations compressed by some mysterious alogithm called ,,Xbox XMemCompress API". About this anything can't be found on the Internet. So I have written helper class that reads these basic information. It can be downloaded from HERE. I hope that can be usefull.

úterý 10. ledna 2012

ŽvB 2 - aneb cože to vlastně je/ ŽvB 2 - what the hell is this?

Ano na Nový rok jsem tady slíbil že se rozepíšu co je to vlastně ŽvB 2 a co od toho čekávám. Konečně jsem se dokopal k tomu něco o tom napsat, ikdyž to před chvilkou vypadalo že budu psát o něčem jiným.
ŽvB 2 by měla být jakási náhrada za ŽvB 1 (www.zvb.cz) což je projekt postavený na stařičké hře Ultima Online. Dnes a je to smutné už bohužel ručně malovaná hra s 2,5D rozhraním nepostačuje nárokům mládeže. Jakmile to není 3D a nemá to skvělou grafiku tak je to ihned odpad. Proto se zrodil už v září roku 2008 nápad že by bylo vhodné myslet na budoucnost a postupně si dělat zadní vrátka. Původně jsme si (spolu s Alexejem) mysleli že zvládneme udělat nějaký počátek a předložit jej jako dárek už do vánoc. V té době bylo v plánu udělat velkou síň (myšlena ta síň z Bradavického hradu z HP, ostatně vše co dělám je HP) ale cíl se postupně přetransformoval na pouze jakousi chodbu, kde by bylo možné ukázat spoustu věcí a představit možnosti. Dnes se píše rok 2012 a jak vidno do těch Vánoc sme to nestihli :-) Dnes jsem již bohužel sám. Našel jsem si sice spojence Junita, který mi dodal několik pěkných modelů které jsem použil ale ten jak se zdá už taky nemá tolik času. Pokusím se zde popsat česky i englicky jak jsem k jednotlivým částem dospěl, co jsem si kde vypůjčil a na co jsem přišel sám, snad to někomu pomůže. České zdroje neexistují vůbec (ikdyž je pravda že jsem našel jeden článek co mi pomohl přidat háčky a čárky...) bez engičtiny se tedy neobejdu vůbec. Jako základ jsem použil XNA a také InnovativeEngine od Seana Jamese. Docela jej doporučuju pro všechny kteří se chtějí takovéto věci naučit protože je zcela nehotový a vše si musíte dopsat sami a hlavně a to je to nejlepší celý je psán jako tutoriál, takže se snadno pochopí co a jak funguje. Taky jsem napsal pár věcí z jeho knihy, ta je taky dobrý zdroj informací. Pokud by se ale někdo rád přidal a s něčím s čímkoliv pomohl nebo by se chtěl optat tak mi určitě napište! A jako pokaždé se trošku musím vytáhnout tentokrát videem s implementovanou fyzikou JigLibX (je dole pod englickým článkem)



At New Year's day I have promised to tell you something about ,,ŽvB 2". ŽvB 2 is name of project based on todays project called ŽvB 1. And ŽvB 1 can be called as Harry Potter shard and therm shard is something like game sever of Ultima Online :-) Basicly is world of Harry Potter in Ultima Online. For young generation is Ultima very old game. Anything without 3D and cool effects and much blood is boring and ugly. At September 2008 an idea comes to me. I want to transfer ŽvB 1 to 3D world for future use. At this blog I try to write some articles about some parts of my Engine that I am writing. I have choosen XNA and as basic skeleton is used Sean Jame's Innovative Engine. Great thing about this engine is that is written as tutorial, so you can simply understand to all things in it. I have also implementend couple of thing from his book and tryed to improve them. Nowadays I am alone in this task. If anyone of you want to help me be suer to contact me!
And as last time there is my video with implemented JigLibX XNA physic library: