2016. október 28., péntek

The walled city in your code


Walled cities have a really long history thanks to the fact that we love to kill each other for whatever reason. So city walls were a necessity from a very early history to modern times thanks to this fact. Of course a walled city also needs gates and guards who guard these gates and walls, so we feel a lot more safer. Nowadays we usual have fences, gates and security guards for the very same reason.
In this little post we will talk about when can our code feel a little bit safer.


An important lesson from Haskell

You can learn a lot from a pure functional programming language like Haskell, because it makes us view and solve problems in a different way. For example Haskell considers every IO action dangerous, because it causes side effects and side effects can cause unforeseen errors. It’s also one of the most important from Haskell is to be wary of any IO action.


The outside world

The outside world is dangerous, because you can caught a cold or get hit by a bus. The “digital” outside world also has it’s own dangers like errors, exceptions and bad inputs, which are things that programmers hate the most. Unfortunately we can’t live without the outside world, because we need to get and share information, but we also want to get rid of the dangers, so what to do?


The wall around the city

We build walls to control the madness of the outside world and also to feel a lot safer. In our case the goal of the wall is to protect us from the errors, exceptions and bad inputs. Basically it’s job is to handle any exception or error from the outside and also to validate any incoming value. This wall also needs to be robust so it won’t crash the system and it will recover from any unforeseen error.

For the wall we need a programming language, which can handle a lot of IO action, but it’s also robust against any exception or error.
The best language for this role is Erlang or Elixir(which is basically Erlang with simpler syntax). Erlang is a good fit, because it’s scalable and robust thanks to it’s lightweight green threads and the use of supervisor trees.


The city inside the wall

We are inside of the walls in our little safe place, far from the dangers of the world. Inside the wall is the ideal place to be, but it needs to be very strict to avoid causing any inside danger. We want to avoid causing any error or exception here, because it would spread like a fire through out the city. That’s why I said we need to be strict and so we need to use a programming language with strong type system that emphasis on avoiding anything that can cause side effects, exceptions or errors.

The best choices for this role is Haskell or OCaml, because both of them are strongly typed language. A strong type system is important, because it can guarantee that there won’t be any type mismatch or null exception(billion dollar mistake). They are also high level(functional) languages, which means it restricts the freedom of it’s users, which is a really good thing when you are going for correctness.

Another reason for using Haskell and Ocaml is that they both have a proof assistant based on them. Proof assistants are really important when you want to prove that your program works correctly. Proof assistants are basically really strict programming languages that can also be used for proving. These tools should be used, when you want really strong foundations for your city.


Final word

This idea describes a system where the core of the system is protected by the outer layer, so this way the system can isolate itself from the environment and the only thing that matters is the logical correctness of it’s code base. This is also why I really like this idea.


I hope you liked my first post in english. :D
Best way to enjoy Autumn is to watch a Summer music clip. :D

2016. február 6., szombat

Programozók nem tudnak bizonyitani

Ebben a kis bejegyzésben bizonyításról és annak szerepéről az informatikában lesz a téma.

Bizonyítás
  A bizonyítás nem más mint egy állítás helyességének az igazolása. Bizonyításokat a jó öreg ókori görög matematikusok találták ki és közülük is kiemelkedik Euclid munkája(Elemek).
Bizonyítások érdekessége, hogy készítésük során használhatunk bármilyen már bizonyított állítást, hiszen azoknak a helyességét már bizonyítottuk. Ezáltal a bizonyított állításokból még összetettbe állításokat tudunk megfogalmazni és bizonyítani.
  Bizonyítások szépsége, hogy megad egy biztos alapot, amire az ember építkezhet.

Félelem
  Eddigi tanulmányaim során mindig imádkoztam, hogy a matekos tárgyaknál ne legyen elvárás, hogy tudjam a bizonyításokat. Ami nem meglepő, mivel elég hosszúak voltak(tételhez képest), nehezen érthetőek és nem is értettem, hogy hogyan is csinálták őket. Nem is beszélve, hogy ha a bizonyítás nagyon informális volt, akkor a bizonyítás leírásából hiányozhatott néhány lépés, mert azok "egyértelműek" voltak(vagy csak drága volt a papír és az író takarékos akart lenni).
  Bizonyítások iránti félelmem abból fakadt, hogy egyszerűen nem értettem őket vagyis nem tudtam ,hogy hogyan kell bizonyítani. Van egy megérzésem, hogy ezzel nagyon sok kollégám küzd.

Oktatás
  A magyar egyetemek arról híresek, hogy elméletet nagyon komolyan veszik és ehhez képest eddigi tanulmányai során egyetlen olyan kurzusom se volt, ami magával a bizonyítás készítéssel foglalkozott volna. Viszont ennek ellenére rengeteg bizonyítással találkoztam.
  Lehet példákon keresztül kellet volna megértenem, hogy hogyan kell bizonyítani egy tételt, ami a magam részéről mondhatom, hogy nem vált be. Ez olyan mintha egy középiskolás osztálynak a lisp programozási nyelvet úgy próbálnám megtanítani, hogy csak a példa programok kódját adnám meg nekik.

Idő
  Bizonyítások nagyon időigényes elfoglaltságok, mivel egy bizonyítás elfogadásához kell egy matematikus, aki eldönti, hogy helyes-e a bizonyítás. Tudományos körökben egy komolyabb állítás és annak a bizonyításának elfogadásához általában 2 évet kell várnia a tudósnak és ez még a jobbik eset. Kirívó ellenpéldának itt van Mocsizuki Sinicsi esete, aki egy évtizednyi munkával bizonyította be az abc sejtést, de 3 év elteltével is csak 4 ember érti a bizonyítást.
  Ebben az esetben a folyamatot az emberi tényező teszi nagyon lassúvá. Bizonyítani csak gyakorlással lehet megtanulni, de ehhez kell egy matek tanár is, aki átnézi az általunk készített bizonyítást. Viszont a matek tanárral csak hetente 1-2-szer tudunk találkozni, így a bizonyítás kipróbálásához néha napokat kellene várni.

Megoldás
  Emberiség a történelme alatt mindig kitalálta, hogy hogyan tudná az embert kiküszöbölni a folyamatokból. Ahogy eddig is mindig, most is egy gép vonja ki az embert az egyenletből.
Mi esetünkben ez nem más mint a számítógép által segített bizonyítás avagy más néven tétel bizonyítók(proof assistant) használata.
  Tétel bizonyítók segítségével egy tételt interaktív módon tudunk bebizonyítani és a bizonyításunkat a számítógép ellenőrzi le. Így sikerült kiküszöbölni a matek tanárt és sikerült magát a bizonyítás folyamatát interaktívvá tenni, ahol a számítógép minden lépésnél visszajelzést ad, hogy éppen hogyan állunk a bizonyításban.
  Az egész folyamat nagyon hasonlít a programozáshoz, hiszen a munkafolyamat ugyan az vagyis egy nagyobb problémát kisebb egyszerűbb problémákra bontunk fel. Bizonyítások esetében  egy nagyobb bizonyítást sok kisebb bizonyított állítások segítségével építünk fel.

Motiváció
  Persze jöhet a kérdés, hogy minek tanuljon meg egy programozó bizonyítani?
Bizonyítás szépsége, hogy bármilyen állításra lehet használni őket és maguk a programok is állítások sokaságából állnak össze. Egy metódus/függvény is egy állítás, ami azt állítja, hogy bizonyos bemenet hatására bizonyos kimenetet produkál. Tétel bizonyítóval ezt az állítást tudjuk megvizsgálni, hogy ténylegesen teljesül-e.
  Ezt a folyamatot formális verifikációnak hívjuk, ahol egy specifikáció alapján tudjuk verifikálni a rendszert vagyis le tudjuk ellenőrizni, hogy a rendszer tényleg azt csinálja, amit mi akarunk.
Formális verifikáció egy nagyon nagy, érdekes és fontos területe az informatikának, amiről érdemes tudni és figyelni az onnan érkező eredményeket mint például a Compcert, ami egy formálisan verifikált C fordító.

Ajánlott irodalom
  Software Foundations: Ebben a témában ez a könyv alapműnek számít. Iszonyat mennyiségű tartalom található meg a könyveben és legjobb benne, hogy online ingyen elérhető. Még mindig olvasom a könyvet, de nagyon pozitív tapasztalataim vannak a könyvel kapcsolatban.

Zárszó
  Szoftverfejlesztés kezd olyan irányba elmozdulni, hogy a jövő szoftverei már bizonyítottam biztos alapokon fognak nyugodni. Ahogy a matematikának úgy a szoftverfejlesztésnek is kellet egy kis idő, hogy fontos szerepet kapjon benne a bizonyítás.

Ahogy harcban, úgy a programozásban is fontos a fegyver megválasztása :D

2015. április 27., hétfő

Funkcionális kirándulás

Az elmúlt hónapban végre rávettem magam, hogy belevessem magam a funkcionális programozás világába.
Úgy mondhatnám, hogy még az út elején vagyok, mert 1 hónap nem túl sokra ha csak néhány nap tanulgatja az ember, de arra bőven elég, hogy beszámoljak az élményeimről.

Persze jöhet a kérdés minek a tanulni funkcionális paradigmát, ha majdnem mindenhol objektum orientált paradigma a meghatározó. Erre a válasz pedig a fejlődés, ami programozás világában a legfontosabb tulajdonság. Eddigi tapasztalataim alapján 4 nagy mérföld kő van, amivel jó ha találkozik az ember fejlesztőként:

  1. Első Hello World program futtatása.
  2. Valamilyen OOP nyelv elsajátítsa.
  3. Nagyobb projekt fejlesztése vagy/és egy könyvtár megírása.
  4. FP nyelv megtanulása.
Belegondolva ezek a lépések számomra egymás következményei voltak. Ezt a 4. mérföldkövet azért tartom fontosnak, mert kirángat a megszokott közegből és rákényszerít, hogy új dolgokat tanuljak és a megszokott dolgokra is új szemmel nézzek.

Ezelőtt is voltak kísérleteim FP nyelv tanulásával, de valahogy mindig elbuktam vele vagy egyszerűen csak nem érdekelt tovább, de most rávettem magam hogy azért is belevettem magam.
A legfontosabb különbség a korábbi próbálkozásaimhoz képest, hogy most volt időm és egy jó könyvem a témában.

Programozási nyelvnek Haskell-t választottam, mert az egyik legnépszerűbb tisztán funkcionális nyelv és nem is beszélve, hogy a nyelv 1990-ben jelent meg, ami azt jelenti, hogy nagyon érett és stabil. A nyelv egyik erőssége, hogy 20+ év alatt össze tudtak dobni egy 1-2 könyvet. :D

Régebben próbálkoztam a Scala megtanulásával, ami egy hibrid nyelv, ami keresztezi az funkcionális és objektum orientált paradigmát, de ezzel az a gond, hogy FP megtanulása tekintetében egy rossz választás, mivel egy hibrid nyelv és nem kényszeríti ki a funkcionális paradigmát hiszen ott van az objektum orientált része. Nem is beszélve, hogy nem találtam hozzá jó tanuló anyagot.
Kipróbáltam az online Scala kurzust és a hivatalos Scala könyvet is, de egyszerűen túl unalmasak voltak és ezért hagytam is az egészet.

A jó könyv, amit találtam pedig a Learn you Haskell for good, amit már nagyon régóta végig akartam olvasni, de valahogy sosem értem rá, de mostanában végre sikerült végig olvasnom. A könyv nagyszerűsége az egyszerűsége és hogy mókás játékos módon közelíti meg a tanulás kérdését. Na és persze a legjobb benne, hogy online ingyenesen elolvasható.

Haskell közösségben különlegességnek számít ez a könyv, mivel maga a kemény magja a közösségnek nagyon tudományos szemléletű, ami szerintem nagyon szembe tűnő más nyelvekkel szemben. Aki már olvasott posztokat r/haskell subredit-en az tudja, hogy miről beszélek. Ahelyett, hogy blog posztot írnának egy nyelvi érdekességről, helyette inkább egy tudományos papírt publikálnak pdf formában, amiben persze benne van a levezetés, ami megmutatja, hogy miért is működik ez az dolog.



Bennem a könyv olvasása közben 3 érzés tudatosult Haskellel szemben:

  1. Csodálatos, hogy milyen szép és rövid megoldásai lehetnek egy adott problémának.
  2. Értem a dolgot, de akkor is elég furán működik
  3. Nem igaz, hogy 3 sor kódot nem tudok megérteni vagy 2 napja
A könyv első fele elég gyorsan elment, mivel azokat már elég jól ismertem, habár még így is meggyűlt a gondom Haskell típus rendszerének megértésével. A neheze csak ezek után jött, ami nem volt más mint a funktor-ok megértése. Azért nehéz, mert igazából ez az első alkalom, amikor az olvasót megcsapja úgy igazán a matematika szele és nem valami kellemes érzés. :D

A könyvnek nagyon jó a félépítése, mert az alapoktól indul és mindig egymásra épülve adagolja az új tudást. Közben arra is figyel, hogy megértsük, hogy miért kellet a nyelvbe az a bizonyos nyelvi elem. Egy nyelv megértésénél nagyon fontos, hogy megértsük, hogy miért van benne az, ami benne van, mert ellenkező esetben akár rosszul is használhatjuk azt a bizonyos nyelvi elemet. Ennek ellenére is biztos, hogy  fog nehéz pillanatokat átélni az olvasó, mert ez még is csak egy teljesen más paradigma.

Funkcionális paradigmát azért hívják így, mert benne minden egy funkciónak tekinthető, ahogy egy objektum orientált nyelvben pedig minden egy objektumnak tekinthető. Ez akkor eset le nekem amikor láttam, hogy az összeadás is csak egy funkció. Összeadás olyan funkció, aminek 2 bemenete van és a kimenete a két összeadott bementi érték.

Szerintem mégis a legfontosabb fogalom, amit meg kell érteni az a rekurzív funkció fogalma és annak működése.
Azért fontos, mert a nyelveben nincs alapból for vagy while ciklus, hanem helyette rekurzív függvényekkel lehet ezeket megvalósítani és ezért nem is fontos, hogy benne legyenek. Már ebből is látszik, hogy máshogy kell funkcionális nyelvekhez viszonyulni.
Rekurzív függvényeknek a lényege, hogy az adott problémát felbontsunk alap és rekurzív esettre. Ha megértjük azt, hogy hogyan kell ezt csinálni, akkor gyakorlatilag már tudjuk is, hogy mi az a rekurzív funkció.

Másik nagyon fontos dolog pedig, hogy a nyelvben minden egy kifejezés vagyis vissza kell valami adnia. Ez elég érdekes lehet, mivel objektum orientált nyelvekben utasításokat is találhatunk, amiknek nem kell visszaadni semmit és általában  inkább beállítanak valamilyen értéket. Ez azt is jelenti, hogy Haskell-ben nincs void függvény, vagyis olyan függvény, amit semmit sem ad vissza.
Másik következménye, hogy Haskell-ben nehezebb nagy függvényeket írni, mivel nincsenek utasítások és mindenek vissza kell valami értéket adnia.
Ebből következik a következő érdekesség is egyben.

Haskell utolsó általam emlitett érdekessége, hogy meglévő változó értékét nem lehet módosítani vagyis a változók módosíthatatlanok alapból. A változó módosítását ezért csak úgy lehet megoldani, hogy egy új változót kreálunk a régi alapján. Ez a módszer nem új keletű, mivel objektum orientált nyelvek nagy részében ugyanígy működik a String objektum.
Azért elsőre kicsit fura lehet, hogy a kocsi színének a megváltoztatását nem festéssel, hanem egy új autó elkészítésével érjük el.

Elég furcsának tűnhet, hogy módosítás helyett mindenből újat csinálunk, de ennek van egy nagyon jó tulajdonsága, ami a side effect mentesség. A side effect nem más, mint amikor egy globális változónak az értéke hatással van egy általunk megírt metódusra. Emiatt fordulhat elő, hogy két azonos metódus hívás különböző eredményt add vissza ha globális változóra támaszkodik. Haskell-nek pontosan az egyik célja, hogy ilyen ne fordulhasson elő és minden azonos metódus hívás azonos eredményt adjon vissza és ne legyenek benne meglepetések a programozó számára.

Ezekből is látszik, hogy Haskell kikényszeríti a programozóból, hogy a problémákat felbontsa kisebb megvalósítható részekre, függvényeket egyszerűre készítse és  hogy ezek  a megírt függvények kiszámíthatóan viselkedjenek. Ha az olvasó is ráveti magát Haskell tanulásra, akkor észreveheti, hogy a nyelv megváltoztatja azt is, hogy más nyelvekben hogyan programozunk. Az már biztos, hogy az ember ezek után már jobban oda figyel arra, hogy kerülje a side effect-et és lehetőleg egyszerű metódusokat írjon, amiknek csak egyetlen egy feladatuk van.

Funkcionális programozás ugyan azt kényszeríti ki, mint a TDD(Teszt vezérelt fejlesztés), vagyis hogy jobb és egyszerűbben tesztelhető kódot írjunk. Ezért bárkinek csak ajánlani tudom, hogy vesse bele magát bármelyik funkcionális nyelv megtanulásába, mivel segít egy jobb és szebb kód megírásában.

Bevallom őszintén elég nehéz volt megírnom ezt a bejegyzést, mert annyi mindenről lehetne mesélni még így is, hogy alig foglalkoztam Haskellel, de mégis a bejegyzés megírása után kétes érzéseim keletkeztek a nyelvvel kapcsolatban.

Egyfelől a nagyon sokat tanultam magáról a programozásról a nyelv tanulása közben és csodálom, hogy milyen röviden és elegánsan megoldásokat lehet a nyelvvel készíteni.
Viszont a kétely is feléledt bennem, hogy menyire használnám a nyelvet tényleges valós problémák megoldására vagy egyáltalán menyire lehetséges ez egyáltalán. Ami olyan nagyszerűvé teszi a nyelvet az annyira ellene is játszik elterjedése szempontjából.

Számomra Haskell olyan mint a vim. Nagyon sok időt és gyakorlást kell belefektetni, hogy igazán produktív legyen vele az ember, de akik átélték ezt a tűz keresztséget azok mondák, hogy megérte.
Én személy szerint még olyan nyelveket fogok előnybe részesíteni, ami alapból OOP, de már megjelenek bennük a funkcionális paradigmák.(Dart, Java8)
Habár úgy nézz ki, hogy gőz erővel tartunk a hibrid nyelvek világába, szóval nem lesz nehéz dolgom ilyen nyelveket találnom és használnom.

Meglepetésként pedig jöjjön egy pokoli jó szám:

2014. november 9., vasárnap

Mi a vektor Viktor?

  Újabb hosszú idő után eljött az idő, hogy újabb "tanulságos" blog bejegyzést írjak játék fejlesztés téma körében. Ahogy talán a címből kiderül vektorokról fogok mesélni, hogy micsoda és hogy mire lehet használni őket.
  Gondolom hozzám hasonlóan sokan vannak úgy, hogy amit az ember az iskola alatt tanul annak a nagy részét soha nem fogja tudni használni. Ez alól kivétel a vektor,  ha az ember játékfejlesztéssel foglalkozik. Játékfejlesztés egyik szépsége, hogy nagyon sok mindenre megtanít és megmutatja, hogy mire lehet a megtanult dolgokat használni.

Mi a vektor?
  Elég a szócséplésből és inkább térjünk rá a lényegre. A vektort gyakorlatilag 2 dolog alkotja: irány és mennyiség. Vektort gyakorlatban nyíllal szoktuk jelölni, ami egy kezdőpontból egy végpontba mutat és a menyisége pedig a nyílnak a hossza.

Na de mire jó ez a mi esetünkben?
  A játékok általánosságban akkor izgalmasak, hogyha mozognak benne a dolgok és ahogy fizikából megtanultuk, ahol mozgás van ott vektornak is kell lennie. Tehát a vektorok tökéletesek mozgások leírására.

Hogyan programozzuk ezt le?
  Legegyszerűbb dolgunk a a mennyiséggel van mivel ez egy egyszerű szám, amit el kell tárolnunk.
Mozgás esetében a mennyiség lehet például a sebesség.
Irány sem sokkal nehezebb, mivel ehhez érdemes egy egyszerű irány vektort használni, aminek a hossza 1 és a kezdő pontja a koordináta rendszer origója vagyis (0,0), ami miatt csak a végpont koordinátáit(x,y) kell eltárolnunk.

Irány vektor


WTF vektor a vektorban?
  Tudom tudom, de így lehet a legegyszerűbben elmagyarázni, hogy hogyan is kell irányt megadni.
Gyakorlatilag ez nem más mint egy iránytű, ami megmutatja, hogy egy adott játék elem milyen irányba mozog.

Aha, de hogy használom őket együtt?
  Mozgások esetében a mennyiség a sebesség lesz és az irány pedig a test mozgási iránya. Ebben az esetben csak annyi a dolgunk, hogy összeszorozzuk őket. Így pedig megkapjuk a vektort, ami gyakorlatilag elmondja, hogy a test milyen sebsebéggel mozog x és y irányban.

Triviális esetek:
Sebsebég: 300
Felfelé alkarunk haladni, akkor irányvektor: (x:0,y:1). Ezeket összeszorozva(x:0*300,y:1*300), ezt a vektort kapjuk: (x:0,y:300)
Gondolom innen már sejhető, hogy lefelé a vektor: (x:0,y:-300), balra a vektor: (x:-300,y:0) és jobbra a vektor: (x:300,y:0).

Nem triviális esetek:
  Szerintem az átlós mozgások nem triviálisak, mivel több fajta módon is be lehet állítani az irány vektort:
1. Kiszámoljuk az irányvektor végpontját az x tengely és az irányvektor közötti szög alapján. Például: cos(30) = 0.866, sin(30) = 0.5, tehát az irány vektor: (x:0.866,y:0.5)
2. Elforgatunk egy adott irányvektor, hogy az átlósan álljon.
3. Összeadunk két merőleges vektort és a keletkező vektort lezsugorítjuk, hogy a hossza 1 legyen.

Összegezve:
  Lényegében a vektorok a játékfejlesztésben tökéletesek a mozgások leírására és ezért alapvető elemei egy fizikai motornak. Vektorok egyszerűek mivel csak menyiségből és irányból állnak. Használatuk is igen egyszerű, mivel minden nyelven találhatunk vektor könyvtárakat.
  Nekem szerencsém volt mivel StageXL-ben van egy vektor osztály, amivel megtudtam valósítani a vektor irány részét és így már csak a mennyiség része maradt, ami meg triviális feladat.

Kiegészítés:
  Mozgások esetében a sebességet is ábrázolhatjuk vektorral ha a sebességet felbontjuk horizontális és vertikális sebességre. Azért jó, mert ebben az esetben is két értéket kell eltárolni, mint az irányvektor esetében. Nem is beszélve a tényleges vektor megadásához csak össze kell szoroznunk a sebesség - és irány vektort.(Ami vektorok esetében egyszerű dolog)

Egy kis példa:
  DartRocket esetében vektorokat használtam a mozgási és irányrendszerek megoldásához.
DirectionSystem: Irányokkal való munkát segíti és definiál néhány triviális irányt.
MovementSystem: Mozgások leírását és velük való munkát segíti. 

Bónusz: 

2014. augusztus 5., kedd

Streameljük az állapotokat

Ezt a bejegyzést már jó ideje megakartam már írni,de valahogy sosem vett rá a lélek.
Ebben a bejegyzésben bemutatom az állapotgépemet, amit csináltam még anno a játék motoromhoz, mert elég érdekesen csináltam meg, mivel Stream-et használtam hozzá. Előbb viszont tisztázok néhány fogalmat.


Állapotgép
Az állapotgép, ahogy a nevéből is kiderül egy olyan gép, aminek állapotai vannak. Ezek az állapotok között klasszikus értelemben van kezdő, aktuális és végállapot. Az állapotgép feladata, hogy események hatására egyik állapotból átmenjen egy másikba. A gép célja, hogy a kezdőállapotból eljusson a végállapotba.

Ez egy egyszerű kapcsolónak a diagramja.

Jól látszik az ábrából, hogy 2 állapot van, amikbe lehetünk. Kezdő állapot és végállapot nincs, de egy igazi rendszernél biztos a kikapcsolt állapot lenne a kezdő állapot. Események itt a kapcsoló használata, ami előidézi, hogy állapot váltás menjen végbe.

Aha, de mi köze van a játékfejlesztéshez?
Játékokat általánosságban elég jól elkülöníthető állapotokra lehet bontani. Gondoljunk csak arra, ahogy egy egyszerű webes játék felépül. Először fogad minket a töltési képernyő aztán következik a menü, ahol eldönthetjük merre tovább. Nem is beszélve, hogy maga a játékmenet is több szintből épülhet fel.

Ezek mind állapotnak tekinthetőek, ahol a kezdő állapot a betöltési képernyő, ahonnan végül tovább lehet jutni többi állapotba.


Stream
Aki már csinált valaha aszinkron programozást annak ismerős lehet a Stream fogalma. Stream magyarul folyamot jelent, viszont a mi esetünkben adatfolyamnak fordítanám le, mivel gyakorlatilag az a lényege, hogy adatot továbbítson folyamatosan. Mi pedig tudjuk fogni ezt az adatfolyamatot és megkapjuk belőle azokat az adatokat, amiket éppen továbbit.
Stream-eknek még van egy nagyon jó tulajdonsága, hogy bármikor meg lehet állítani és folytatni őket.
Nem is beszélve arról, hogy nagyon könnyű velük kommunikálni.

Na ennek meg mi köze van az állapotgéphez?
Valóságban nincs túl sok közük egymáshoz, viszont mégis érdemes vegyíteni őket , mert meglepően sokat tudó rendszert lehet csinálni vele minimális kód megírásával.

Mi esetünkben egy Stream egyelő lesz egy állapottal. Tehát van máris egy állapotunk, amivel tudunk kommunikálni és akkor indítjuk el vagy állítjuk meg amikor csak akarjuk.
A valóságban csak annyi dolgunk volt, hogy az állapot(State) osztállyal örököltettük a Stream osztályt és innentől kezdve csak ki kellet egészíteni, hogy tényleg úgy viselkedjen, mint egy állapot.


Állapotok kezelése
Eddig vannak az állapotaink, de ki tárolja el ezeket az állapotokat és vajon ki indítja el a kezdő állapotot vagy egyáltalán melyik a kezdő állapot?Nem is beszélve, hogy hogyan fogunk állapotokat váltani?

Kérdések megválaszolására kell csinálnunk egy állapot menedzsert, aminek egyetlen dolga, hogy ezeket a problémákat megoldja.

Tárolás mondja egy szimpla asszociatív tömb, amiben a kulcs neve az állapot neve és a kulcshoz tartozó érték pedig egy állapot.

Kezdő állapot definiálás és indítás elég könnyű, mivel csak meg kell adni, hogy melyik állapotot kezdje el hallgatni.(Ugyebár az állapot egy Stream)

Az állapot váltásnál tudnunk kell, hogy melyik állapot következik. Én ezt úgy oldottam meg hogy éppen aktuális állapot tárolja a következő állapot nevét. Név tudatában pedig tudjuk, hogy melyik állapotot hallgassuk meg következőként, viszont előtte még az aktuális állapotot kell megállítanunk.


Állapotok megvalósítása
Az állapotgép csak akkor működik, ha vannak olyan egyéni állapotok, amik öröklik azt az absztrakt állapot osztályt, amit csináltunk és megvalósítják annak az összes absztrakt metódusát.
Az én esetemben csak a create metódus megvalósítását várom el a programozótól.

Magyarázat
Az absztrakt metódus azt jelenti, hogy nincsen megvalósítása. 
Az absztrakt osztály pedig azt jelenti, hogy tartalmaz legalább 1 absztrakt metódust és az osztály nem példányosítható.


Összegezve
Megéri az állapotokat streamelni, mivel valamennyire egyszerű a megvalósítás és nagyon sok lehetőség rejlik benne. Én személy szerint a kommunikációs készségében látom a legnagyobb lehetőséget, amit jó magam még alig használtam ki.

Ha kódot is szeretnétek látni ajánlhatom a játék motorom Állapot és Állapot menedzser osztályát. 

2014. május 31., szombat

Amikor érdemes játékmotort késziteni

A mondás
A játékkészítő közösségben van egy mondás, hogy "Készíts játékot, ne játékmotort".
Szerintem ez a mondás nagyon is igaz abból a szempontból, hogy ha tényleg játékot akarsz készíteni, akkor válasz egy jól ismert játékmotort és kezd el a fejlesztést, mivel ezek az eszközök azért vannak, hogy megkönnyítésék a játékkészítést  és ugyebár mi értelme van feltalálni a kereket ismét?
Viszont itt is lehet találni kivételeket, amikor igenis el kell gondolkozni egy saját játékmotor fejlesztésén.

Mikor érdemes tehát belefogni?
 Most csak az én esetemet tudom felhozni, ami nem más mint a saját 2D HTML5 játékmotorom, amit DartRocket- nek hívok. Az én esetemben az ok egyszerű volt. Dart nyelven nem volt egy igazi játékmotor sem és én Dart-ban akartam játékokat készíteni.
Itt találtam is egy kiskaput mivel ha nincs játékmotor, akkor csinálni kell egyet. :D


Hogyan kezdődőt el?
Ha időrendben akarok menni, akkor azt kell mondanom, hogy négy időszak volt, ami meghatározó volt.

Phaser: Ebben az időszakomban a Phaser+Javascript-es HTML5-ös játék készítéssel voltam elfoglalva. Nagyon sok időt töltöttem azzal, hogy megismerkedjem azzal, hogy hogyan érdemes vele játékot készíteni. Ezáltal megláttam azokat a dolgokat amik kelletek egy játék motorhoz és ami szerintem még fontos, hogy megtanultam API dokumentációt olvasni.
Phaser időszakom végére beleuntam, hogy nem tudtam igazán szépen strukturált kódot csinálni, még olyan eszközzel sem mint Require.js.

Dart+StageXL: Phaser-ből való kiábrándulásom után úgy voltam vele, hogy megpróbálok végre csinálni Dart-tal egy játékot. Ehhez választottam a StageXL nevezetű webGL render engine-t, amiről már jó sokat hallottam és volt hozzá néhány példakód. Az indulás döcögős volt, mert sokat kellet tanulnom Dartról és StageXL-ről. Főleg az utóbbi volt a nehezebb, mert elég hiányos hozzá a dokumentáció.
Elsőként csináltam egy space invaderes játékot és néhány kísérletet, míg végül rájöttem, hogy közeleg LD29 játékkészítő kihívás. 

LD29: Azt tudni kell, hogy a legutóbbi LD óta részt akartam venni rajta, mivel nagyon megtetszett a kihívás. Tudtam, hogy kell valami különleges dolog, amivel kitűnhetek a tömegből ezért gondoltam, hogy a játékomhoz szinteket fogok csinálni. A szintekhez meg kellet egy állapot gép(state machine), ami segítségével tudok szépen egyszerűen szinteket csinálni. Végül az egész verseny ennek a kifejlesztésére ment el és az előkelő 1200 valahányadik lettem összetettben. 

LD29 után: Észrevettem, hogy a játékom egy hatalmas hack, tele copy-paste-tel és még lassan is ment vele a fejlesztés. Ezért tudtam, hogy a következő kihívásra kell csinálnom egy játékmotort, hogy ne kelljen olyan dolgokkal vesződnöm, amik csak rabolják az ember idejét.
 Tehát volt egy problémám, ami az volt, hogy Dart-nak nincs játékmotorja és én tudtam, hogy ez egy olyan probléma, amit megtudok oldani és ezért fontos problémává vált számomra, amiért el is kezdtem rajta dolgozni.

Hogyan kezdtem hozzá?
 Szerintem egy játékmotor legfontosabb része az állapot gép, mivel ahhoz, hogy a játék szép és strukturált legyen, előbb fel kell az bontani állapotokra. Szerencsére LD29 alatt meglett ez a fontos hozzávaló. 
 Egy másik fontos hozzávaló maga StageXL volt, mivel már volt egy alapom amire építhetem az egész rendszert így nem kellet nulláról kezdenem. StageXL a játékmotorom szempontjából olyan, mint Phasernek Pixi.js.(Pixi.js egy 2D webGL renderer)
 Harmadik fontos dolog maga a célkitűzés, mert nem mindegy, hogy mi az. Én ugyanazokat az elveket vallom mint Phaser-t készítő Rich, vagyis csinálni egy olyan játékmotort, ami egyszerű, ami így magában hordozza, hogy egyszerű megérteni és használni.

 Ezeket mind észben tartva kezdtem meg a fejlesztést és miután lett egy kézzel fogható változat négy dolgot csináltam:
  • Csináltam egy Github repot és feltöltöttem oda és így mindenki elérhet
  • Feltöltöttem Dart-nak a csomag kezelőjére vagyis Pub-ra
  • Csináltam egy blogot DartRocket-nek és megcsináltam az első bejegyzést
  • Bejelentettem a Dart közösségnek, hogy mit csinálok
 Szerintem az egyik legfontosabb dolog, hogy a közösségnek bejelentettem, mivel ezáltal kaptam jó visszajelzéseket és nyomás alá is helyeztem magam, hiszen ezzel azt jelentettem be hogy ezt komolyan veszem és nyugodtan várjanak el jó munkát tőlem.

Mit remélek DartRocket-től?
 Amit a legjobban remélek, hogy valamennyire ismert lesz majd és néhányan veszik a bátorságot, hogy csináljanak vele egy játékot és közben tanuljanak magáról a Dart nyelvről. Ősszintén szólva az egyik ok, amiért elkezdtem az egészet, hogy népszerűsítsem a Dart nyelvet, mivel szerintem a nyelv nagyon is megérdemli és szerintem a játékkészítés egy nagyon hatásos módja annak, hogy másokkal megismertessünk egy nyelvvel.

Napi tipp:
 Nagyon tudom ajánlani Hamming előadását: You and your research(videó)(írott).
Számomra kiderült belőle, hogy mik is az igazán fontos problémák.
Akik nem szeretnek túl sokat olvasni vagy nézni azoknak mondom, hogy az előadás végén van egy összefoglaló.

2014. április 30., szerda

Hétvége a versenyzésről szólt

Ez a hétvégém csak egyetlen egy dologról szólt, a versenyzésről. Összesen 2 online versenyen vettem részt. Amik ugyanazon a hétvégén voltak ezért egymástól vettek el időt, de nem panaszkodok.

1. codingame.comSkynet Revolution 

  A verseny 2 feladatból állt össze, amit egy általunk választott programozási nyelven kellet megvalósítani. Mivel mostanság nagyon rákaptam a Dart-tal való programozásra ezért ezt választottam fegyvernemnek. A feladatok félépítése nagyon egyszerű: van egy input, amire egy megfelelő outputtal kell szolgálni különböző tesztesetek alapján.(Inkább úgy mondanám, hogy teszteseteket kell teljesíteni)

  Az első feladat viszonylag könnyen teljesíthető volt, amire ajánlottan 1 órát volt érdemes száni. Nekem éppen sikerült vele 1 óra alatt végezni. Feladat lényege az volt, hogy egy motorost kellet átjuttatni a híd egyik oldaláról a másikra. A nehézség abból adódik, hogy ez a híd hibás és van  rajta lyuk, amit át kell ugratni megfelelő sebességgel. Feladathoz 4 parancsot tudtunk kiadni SPEED,WAIT,SLOW,JUMP. Ezeket a parancsokat körönként kellet kiosztani.
  Ez viszonylag könnyen teljesíthető volt mivel csak az volt a lényeg, hogy megfelelő sebességre gyorsítsunk aztán a megfelelő időpontban elugorjunk majd végül megálljunk.

  A második feladat leírásánál láttam, hogy ezt bizony nem fogom tudni megoldani. Ajánlott idő intervallum 2 óra volt, de mivel az egész verseny 4 órás volt ezért többet is rá lehetett száni.
A feladat annyiban változott meg az elsőhöz képest, hogy kevesebb volt az input és a hídon több sáv, motoros és lyuk volt amiknek változatos lehetett az elhelyezkedésük. 2 új paranccsal is gazdagodtunk UP és Down, amikkel sávot lehetett váltani. Feladat lényege, hogy átjuttassunk minimálisan előírt motoros menyiséget a híd túl végére. Az első feladatnál 6 teszt esett volt, ennél 12. Én csak a 4.-ik megoldásáig tudtam csak eljutni.

  Versenyre visszanézve megtanultam, hogy ad-hoc megoldás sosem célra vezető. Ezt főleg a 2. feladatnál érzékeltem. A másik, hogy a lehető legtöbb adatot kell begyűjteni egy feladat megoldásához.
Az utolsó pedig, hogy mindig van egy sokkal szebb megoldás mint az enyém. :D

Eredményeket itt megtaláljátok.

2. Ludum Dare 29 

Ludum Dare egy online játék készítő verseny, aminek 2 verseny kiírása van. Van egy 48 órás egyéni része, ami az egyik legnépszerűbb, amint Compo-nak hívnak és van egy 72 órás csapatatok számára,amit Jam-nek hívnak. Jam-et még egyéni versenyzők is szoktak csinálni ha kifogynak az időből.

  Én gondoltam egyet és kipróbáltam magam a 48 órás egyéni megméretetésen. Ezt már vagy egy hete terveztem, mivel mindig is ki akartam próbálni.
A másik ok amiért ki akartam próbálni, hogy előtte készülgetett a Dartban írt állapot gépem, amiről úgy gondoltam, hogy kész leszek vele a versenyre és igazam is lett mert tényleg kész lettem vele (Nagyjából).

  Gondolom kitaláljátok, hogy milyen nyelven ment a fejlesztés. :D Igen ismét Dart-ot választottam ki és hozzá segítségként pedig StageXL könyvtárat használtam, amiről már írtam az előző blog bejegyzésemben. Főleg azért használtam mivel tényleg megkönnyíti az ember dolgát egy 48 órás versenyen ha nem kell magával a megjelenítéssel szórakozni.

  Verseny egész jól indult. Sikerült összepárosítanom StageXL és  az általam készített állapot gép működését, amit boldogan vettem tudomásul. Csináltam néhány pixeles képet piskell segítségével és egy darab játszható szintet összedobtam segítségükkel.
Nagyjából ezzel elment egy nap, mivel közben még Skynet-re is fordítottam időt.

  Második nap már nem volt ilyen szerencsés, mivel előjött bennem a gondolat, hogy egy szintet újra játszhatóvá kéne tennem. Úgy voltam vele, hogy ezzel nem lesz semmi gond, de tévedtem.
Most nem mennék bele abba, hogy hogyan működik az állapot gépem, de azt elmondhatom, hogy nem sikerült a legegyszerűbb megoldás, ezért az állapot gépemnek azt a tulajdonságát kellet használnom, amit eddig még nem tudtam működésre bírni. Ezért először magán az állapot gépen  kezdtem el kísérletezgetni, hogy rájöjjek, hogy miért nem működik. Végül 2-3 óra múlva rájöttem, hogy 1 darab metódus hívást kellet kitörölnöm, hogy működésre bírjam.

  Mivel egy játék sosem olyan egyszerű, mint egy kísérlet ezért be kellet vezetnem egy kis üzenet küldő rendszert az állapot és az állapot kezelő között. Nem is beszélve az új adatszerkezet illetve logikáról, amit még hozzá kellet adnom, hogy működjön a dolog. Összességében viszont sokkal jobban kezelhetővé vált a dolog és végre egy szint újra játszható lett.

  Szóval a bug hunt után maradt hátra még 5 órám az egész versenyből és a játékom nem volt éppen élvezhető és nem is volt semmi célja. Kaptam néhány tanácsot, amit be s tartottam: pontszámláló, és háttérszín ne barna legyen. A következő amire gondoltam, hogy még így is csak egy sima pont számlálós játék ezért kapott a játék egy kis meglepetést a végére, amit nem árulok el. :D

Végül már csak annyi maradt hátra, hogy még végleg leteszteljem, feltöltsem az oldalamra és publikáljam a játékom ludum dare oldalán. Összeségében elég jó kritikákat kaptam, amin meg is lepődtem, habár  azt megjegyzem, hogy ludum dare közössége nagyon pozitív és támogató.
Szóval a célközönség olyan fejlesztők, akik értékelik azt a munkát, amit a játékod elkészítésébe fektettél.

Játékom Ludum Dare-en

Összefoglalva:

Megéri versenyezni, mivel ha nem is nyered meg, akkor is szerzel olyan tapasztalatot és visszajelzéseket, amiket csak így kaphatsz meg.

Napi tipp:
Próbáljátok ki a Dart nelyvet. :D