All english written articles have English article tag and lays under horizontal line. First part is written in Czech.

sobota 9. srpna 2014

Kterak jsem navšívil tábor pro programátory / Czech only article

Už minulý týden jsem navštívil spolu s Tomášem Slavíčkem tábor pro programátorskou omladinu. Cílem bylo povědět jim něco málo o tvorbě her obecně, o MonoGame a hlavně je motivovat a ukázat, že dělat hry dovede každý, když to celkem obstojně svedeme my dva. Nikdy jsem na nějakém takovém podniku/táboře nebyl, protože les a stan vždycky vyhrál. Moc dobře jsem nevěděl, co od těch dětí (oficiálně tedy účastníků jak jim bylo říkáno, ale pro mě to sou děti!) vlastně očekávat. Měl jsem pár takových tušení... no potvrdila se snad všechna.

Samotný příjezd byl zvláštní, ani sme netušili jestli na nás čekají a jeslti bude vůbec kde spat a co jest. Čekali jednoho a ne dva, ale to se nakonec neukázalo jako nějaký problém. Horší to už bylo s úč...promiňte dětmi. Ty se právě vydávaly na noční šifrovací hru. Předpokládaný příchod půlnoc až 4. hodina ráno. Obzvláště milé, když jim máte něco ráno od osmi ukazovat a ještě po nich chtít aby pracovali s vámi :-). Nakonec se to neukázalo být velký problém, to spíš, že to byli skoro samí linuxáci. A jako na potvoru nám linuxový template moc nepremával. Čekalo nás tedy večer ještě celkem hodně práce. Ale zpět ke šifrovací hře, celkem rychle se ukázalo, že by některá část naší skromné party nedošla ani k prvnímu stanovišti. Já zkušený už neskaut jsem poměrně záhy objevil trik první hádanky. Ale jak jsme zjistii, tak by sme dál asi nedošli...

Na pokoji nás čekalo hodně práce. Bylo nutné vše upravit a a vlastně vymyslet další 1,5 hodiny programu navíc. Které jsem se rozhodl iniciativně vyplnit trochou 3D s Vodáčkem. Schylovalo se k průseru. Šli jsme to raději zaspat. Ne však na dlouho. Ve čtyři hodiny se přihnalo stádo dupajících, křičících úč...totiž dětí. A vypadalo to, že se jim moc spát chtít nebude. Korunu tomu celému nasadil jeden nejmenovaný (ano hádáte správně dívky tam nebyly žádné) neznámý vykuk, který nahlas prohlásil, že to MonoGame je o ničem, protože je to .NET. Jak moc velmi mě to potěšilo a pozvedlo náladu snad nemusím ani vykládat.

Ráno, jsme se vzbudil jako vždy kolem šesté a ještě jsme stihl několik pár úprav před snídaní a katastrofě, která se blížila. Účas... děti ráno budila kytara a zpěv jednoho z vedoucích. Zaručeně po tomto výkonu vstali všichni. :-) Přednáška se poměrně rychle blížila a nervozitka taky nezůstala pozadu. Měl jsem totiž odpovídat celý začátek. Vlastně pro mě obvyklá role a taky to tak bylo. Stačilo se rozjet a ignorovat narážky jednoho úč...dítěte a pár jedinců, kteří dospávali šifry. Ten žil poměrně v jiném světu, světu černé příkazové řádky. Docela mě pěkně dokázal naštvat, hlasitou poznámkou co to mám za hnusný okna.Vysvětlení, že to mám na práci a ne na obdivování mu nestačilo a že prý on má oboje. Vlastně si tato osoba furt něco mlela a nebyla v klidu ani chviličku. Jinak se s nimi povedlo střílení asteroidů alespoň trochu nakousknout a naznačit, jak psaní takové hry vypadá. Kupodivu se všem povedlo prostředí rozjet bez nějakých velkých potíží. A vše se také povedlo celkem svižně a bez potíží.

Na druhou část o 3D, která byla čistá vodáčkovina a improvizace se nakonec dostavili čtyři, ale velmi vnímaví a otázek plní zájemci. Řekl jsem jim něco o málo o tom, jak 3D grafika funguje a pak jsme se pustili do rozpitvání ŽvB 2, aby tak nakoukli pod pokličku právě tvořené hře. Na závěr jsem načetl model v MonoGame a nechal ho otáčet, což doufám zbořilo veškeré mýty o tom, jak je to vše těžké. :-)

Odpoledne se naštěstí detičky vydaly ven na venkovní hru, ale při návratu zpět je čekalo nemilé překvapení. NEFUNGOVAL INTERNET! Byli schopní to řešit několik hodin v kuse, zkoušet vše možné i nemožné a samo, že bez úspěchu. Vyhořelý routr moc spolupracovat nebude.

Večerní program obstarával výhradně to máš a na jeho přednášku o UX přišli dva lidé. Jeden organizátor a jeden účastník, který při přednášení usnul :-) Já jsem takticky ustoupil a vyslechl si něco málo o NSA. I tam se ale našli spáči.

Určitě to ale byla pěkná zkušenost a určitě se nebudu bránit to za rok zopakovat. Pokaď budu chtěn.

čtvrtek 22. listopadu 2012

C# a .config soubor / Czech only article

Celkem nedávno se mi naskytl při žvb-ákování problém s updaterem. Zkrátka měl dotyčný nainstalovanou jinou verzi frameworku, než byla potřeba a dostal prapodivnou hlášku:
Docela mi to dalo zabrat protože obvykle se zobrazila chyba 0x a tak dále. Řešení se nalezlo poměrně snadno (google nezklamal a pomohl). Řešení spočívá v umístění speciálního souboru s příponou config. Stačí aby uvnitř bylo něco jako toto:

<startup>
  <supportedRuntime version="v4.0.30319" />
</startup>

Pokud se vyskytuje těchto pár řádků uživateli je hned nabídnuta správná verze ke stažení. Snad to pomůže aj někomu jinému.

středa 1. srpna 2012

Raspberry pi dorazilo / Czech only article

Konečně je doma. Celkem jsem čekal asi měsíc a půl. Očekával jsem že to bude trvat dýl, ale naštěstí to bylo poměrně rychlé. Přišlo mi v pondělí. A jelikož sem jako obvykle nepřipravenej, tak sem neměl ani zdroj ani sd kartu ani krabičku. Jediný co sem měl byla malina.
Nabíječku sem sem sehnal až v úterý. SD kartu jsem si uzmul z foťáku (odpovídá tomu i rychlost se kterou se předvádí). Krabičku jsem opatřil z lega. Destička se vešla úplně přesně. Nahrál jsem tam raspbian. Naštěstí všechny součásti fungovaly hned napoprvé. Celý včerejšek jsem se snažil nainstalovat program pro vzdálenou plochu. Z nějakého divného důvodu se stále nedařilo. Program ,,vino" nešel a tak jsem nakonec podle tohoto návodu nainstaloval tightvncserver. Problémy taky dělal skript pro automatické spouštění po restartu. Musel jsem jej upravit do této podoby:
### BEGIN INIT INFO
# Provides:             vncserver
# Required-Start:       $remote_fs $syslog
# Required-Stop:        $remote_fs $syslog
# Default-Start:        2 3 4 5
# Default-Stop:         0 1 6
# Short-Description:    Start VNC Server at boot time
# Description:          Start VNC Server at boot time
### END INIT INFO

#!/bin/sh

export USER=root
export HOME=/root
export RUN_USER=pi

case "$1" in
  start)
    echo "Starting VNC Server"
    su pi -c "/usr/bin/vncserver"
    ;;

  stop)
    echo "Stopping VNC Server"
    su pi -c "/usr/bin/vncserver -kill"
    ;;

  *)
    echo "Usage: $0 {start|stop}"
    exit 1
    ;;
esac

exit 0

Další poznatky zas příště.

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

Viděl jsem: Doba ledová 4/ Czech only article

Tak jsem po delší době zašel do kina spolu s panem bratrem a Patrikem a Káťou. Tentokráte padla volba na nový animák Doba ledová 4.
Když jsme se dostali do kina docela sem si myslel kam se to sakra vlezl. Sál byl plný malých dětí s rodiči. Naopak reklamy (bezesporu nejlepší co v kině můžete vidět) nezklamaly. Hlavně upoutávka na nový český animovaný film Kozí příběh (se sýrem? nebo jak se menuje) nás všechny pobavila. Dostali jsme i předfilm. Docela jsem se podivoval, ale nakonec se ukázalo, že bez něj by celý program na těch 130 korun, které po nás chtěli, asi neměl.
Film samotný nebyl špatný a co navíc byl okořeněn komentářem jednoho malého diváka, který seděl za námi. Takové hlášky jako ,,Kdyby se pořádně dívali, tak by se jim to nestalo!" byly prostě super!

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.