dijous, 27 de novembre de 2014

Instal·lar lliurex 15

Bo, amb el canvi de versió d'ubuntu on es basa LliureX (passem de la 12.04 a la 14.04), instal·lar LliureX és més fàcil encara. Realment, en esta versió LliureX serà un ppa (un repositori de paquets) de la ubuntu. Per tant podrem instal·lar ubuntu 14.04, afegir el ppa de lliurex, i instal·lar qualsevol paquet de lliurex.

  1. Per tant, instal·lem ubuntu 14.04
  2. afegim els ppa de Lliurex (sudo nano /etc/apt/sources.list):
deb http://ppa.launchpad.net/llxdev/trusty/ubuntu trusty main 
deb-src http://ppa.launchpad.net/llxdev/trusty/ubuntu trusty main

  1.  Actualizem el synaptic per a que llisca els nou ppa i afegisca els paquets
  2. Seleccionem alguna versió de lliurex, per exemple, busquem lliurex-desktop, instal·lem i ja tindrem la lliurex edició escriptori instal·lada. 

Com encara falten coses per actualitzar pot pareixer incompleta, però poc a poc s'anirà actualitzant, tant per ubuntu, com per LliureX

    dimarts, 25 de novembre de 2014

    Modificació del apprise de jquery

    Per al projecte en el que estic treballant, necessitava mostrar un popup amb un editor de text. L'editor elegit ha segut el tinyMCE editor (http://www.tinymce.com/). Per tant, vaig decidir modificar el apprise. Primer anem a explicar com funciona el tinyMCE. Necessita un textarea (etiqueta <textarea>) que transformarà en un editor. El podrem identificar per classe, per nom, per id... Per exemple per a transformar amb un identificador:
     tinymce.init({selector: "textarea#"+idTiny }); 
    Això seleccionaria el textarea amb identificador contingut en idTiny. Val a dir que gasta la nomenclatura jquery, ja que utilitza esta biblioteca.
    Aleshores, si volem que mostre un editor haurem d'afegir al popup, una etiqueta textarea, sobre la línia 180, veurem que trobem:
      $Apprise.html('').append( $_inner.append('<div class="apprise-content">'
     que té pinta de ser el codi, afegit les etiquetes <textarea> amb un identificador arreu (per començar) i després, al final del codi de la funció Apprise, inicialitzem l'editor:
    tinymce.init({selector: "textarea#"+idTiny });

    Ara, des d'una web, incloent previament el tinyMCE i jquery, podrem obrir el nou apprise amb editor:

    Apprise('text');

    Que mostrarà el contingut 'text' en l'editor. Al meu github teniu una variació que ens permet passar-li paràmetres, entre altres coses dir-li el tipus. Si és "tinyMCE", crearà l'editor, si no, es portarà com sempre:



    dimarts, 4 de novembre de 2014

    Php Unit 4.3

    A data d'avui, la versió que duu el synaptic del php unit en Lliurex és la 3.5, no sols ser molt de tindre l'última versió, però la versió actual estable és la 4.3.4. Per tant,  con vull fer tests en php, vaig a decidir abaixar l'última versió:

    wget https://phar.phpunit.de/phpunit.phar

    Això ens abaixarà la darrera versió del php, per tal d'instal·lar-la al sistema haurem de posar-la en qualsevol carpeta que estiga a la PATH (per exemple /usr/localbin) i donar-li permisos d'execució:


    chmod +x phpunit.phar
    sudo mv phpunit.phar /usr/local/bin/phpunit
    phpunit --version 
     
     
    Ara ja podem fer tests (laic a pr0) amb la darrera versió del phpunit (i seguir qualsevol altre tutorial):

    dilluns, 27 d’octubre de 2014

    Jasime TDD en javascript

    Em vaig decidir provar el jasmine. La veritat què 2.0 mola per què no depen d'altra biblioteca (ajuda molt) i s'arranca des d'una web (més fàcil no pot ser), ens el baixem i mirem (editem) l'arxiu SpecRuner.html. Ahí haurem d'incloure els tests i els nostres arxius .js:


    Per exemple, podem veure el generador de questionaris que on estic treballant ara (https://github.com/fercavi/jsquest). Els tests es poden agrupar, el grup haurà de rebre un nom i es fa amb la funció describe:

    describe("Generar html per a preguntes individuals", function() {
      test1
      test2
    ...
    });

    cada test es realitzarà amb la funció it:
    it("Generar una pregunta de resposta llarga", function() {
      cos del test
    });

    el cos del test deurà de tindre unes condicions, definides amb la funció  expect, per exemple: expect(obj1).toEqual(obj2)
    (caldria mirar la documentació per veure totes les comparacions, anem a veure un test sencer:

    describe("Generar html per a preguntes individuals", function() {
      var item;

      it("Generar una pregunta de resposta llarga", function() {
        item = new ItemRespostaLlarga("De quin color era el cavall blanc de Santiago",666,false);
        item.generarPregunta();
        expect(item.html).toEqual("<form name='f666' ><p id=666 obligatoria='false' >De quin color era el cavall blanc de Santiago<br/><textarea cols=80 rows=6 name=pregunta666></textarea></p></form>");
      });
    });

    Per exemple l'arxiu complet tindria este aspecte:


    Recordem que al github tenim tots els arxius del projecte.
    Quan vaig publicar l'article se'm va oblidar posar una captura de que passa quan obrim l'SpecRunner.html:




    dimarts, 14 d’octubre de 2014

    Codin laic a pro: C#.net


    Ara vaig a veure com instal·lar C# (i poder programar en ell clar). Com les versions  que venen al repositori són velles, anem a instal·lar les noves versions via codi i compilar. Primer necessitem el Mono nou (Mono és una implementació lliure de .Net de microsoft):

    Compilant, no funciona


    sudo apt-get install git autoconf libtool automake build-essential mono-devel gettext
    git clone https://github.com/mono/mono

    Normalmetn sol haver un ./configure, però en aquest cas només trobem un script, anem a executar-lo:
    ./autogen.sh

    Entre altres coses, es posarà a abaixar dependències. Compilem:
    make get-monolite-latest
    make EXTERNAL_MCS=${PWD}/mcs/class/lib/monolite/Basic.exe

    I així és compilarà sense tindre cap versió de mono instalada, ara instal·lem:
    make install

    Després necessitarem instal·lar gtk-sharp, però com a pas previ ens demana els gtk-devel:
    sudo apt-get install libgtk-3-dev  gnome-sharp libglade2-dev libglade2.0-cil-dev 

    Una vegada instal·lada l'última versió de Mono (3.10 en estos moments), anem a fer el mateix amb monodevelop:
    git clone git://github.com/mono/monodevelop.git
    cd monodevelop
    ./configure

    i una vegada configurat, compilem:
    make
    I després de 15000 intents no funciona, per tant obtem per afegir els repositoris d'algú que haja pogut.

    Via fàcil


    sudo apt-add-repository ppa:ermshiperete/monodevelop
    Refresquem el synaptic, i si busquem monodevelop tenim el 5 ja, i el podem instal·lar. S'instal·la en la carpeta /opt, i per executar-lo tenim un launcher:
    /opt/monodevelop/bin/monodevelop-launcher.sh


    dilluns, 13 d’octubre de 2014

    Codin laic a pro: javascript

    Bo, anem a veure com programar en mode  pro ;) Els pros, ara gasten javascript (a mi no me mireu, jo li tinc mania). Però anem a veure com s'instal·la el node.js i un editor (també pro) anomenat atom (que no és més que una copia del sublime text ). Primer hem d'habilitar el repositori d'ubuntu:
    Aplicacions->Administració de Lliurex->Lliurex Apt i marquem ubuntu. Accepten i es posarà a actualitzar els repositoris:
    Ara instal·lem el node.js:

    sudo apt-get install nodejs

    Ara anem a la web d'atom (https://atom.io/) i amb tanta mala sort que no hi ha paquets per a linux en 32 bits. Ens diu que ens l'abaixem (https://github.com/atom/atom, podem abaixar-lo com a zip si no tenim el github, de tota manera ens el demanarà per instal·lar), i anem a instal·lar-lo:
    1. abaixar
    2. Descomprimir (unzip atom-master-zip)
    3.cd atom-master
    4.Instal·lació d'altres paquets de dependències:
    sudo apt-get install build-essential git libgnome-keyring-dev fakeroot
    5.executem l'ordre build dins de /script, a mi em dona el següent error:
    cd script
    ./build
    node v0.10 is required to build Atom, node 0.6.12 is installed, per tant, haurem d'actualitzar node.js:
    sudo apt-get update
    sudo apt-get upgrade
    I després de mitja hora actualitzant, vegem que continua donant el mateix problema;
    provem açò (https://rtcamp.com/tutorials/nodejs/node-js-npm-install-ubuntu/):
    sudo apt-get install python-software-properties
    sudo apt-add-repository ppa:chris-lea/node.js
    sudo apt-get update
    sudo synaptic (i marquem les actualitzacions de node.js) 
     
    Ara si intentem .build no ens dona cap problema, encara que tarda una estoneta (a un i7, a un c2d del treball va ser una sort que era hora d'esmorzar); una vegada haja acabat, podem fer tres coses:
    a) Instal·lar:
    sudo ./grunt install 
    b) Crear un paquet:
    sudo ./grunt mkdeb 
    c) executar des d'ahí:
    cd ..
    ./atom.sh
     
    Ara ja tenim un editor per a programar en mode pro, ara anem a provar-ho:creem amb el node un nou arxiu (prova.js):



    i ara ja podrem executar el programa:

     Ala ja som pro i programem en node.js ;)

    divendres, 10 d’octubre de 2014

    Jocs de Blizzard

    No he pogut solucionar el problema amb el dragon age, hui he intentat jugar als jocs de blizzard i ara comptaré com ho he fet. Primer de tot, instal·lar wine 1.7. La versió que tinc instal·lada és la 1.7.18 i ho he fet funcionar. La versió que m'ha instal·lat per defecte és la 1.6 i amb eixa petava el Battle.Net.
    La putada és que abans funcionava perfectament els jocs, però des que al launcher han afegit Battle.net fa les coses molt complicades; de moment puc jugar a 11 -20 fps. (deuria de jugar al màxim possible ;)):

    Veurem si puc optimitzar-ho o algo

    10 minuts després

    Després de diversos intents he aconseguit fixar l'API a OpenGL (sempre em tornava a DirectX 9, inclus posant l'D3D11). Tal i com he llegit ací:
    http://geebzor.com/tech/linux/wow-ubuntu-14-04-trusty/

    Obric l'arxiu WTF/Config.wtf i afegisc o modifique:
    SET gxAPI "OpenGL"

    Amb això ja em trau +60 fps i tot al màxim.
    PS:Obric el jocs amb wine wow.exe per a no traure el launcher de Battle.net

    dijous, 9 d’octubre de 2014

    Dragon age: Origins en Lliurex

    Aprogitant que Origin regala el dragon age per un període breu de temps, m'he proposat veure si funciona en Lliurex:
    https://www.origin.com/es-es/store/buy/dragon-age-1/pc-download/base-game/standard-edition

    Vegem que primer ens haurem de registrar. Des d'ahí podrem comprar el dragon age (si ho fem ja és de bades) i abaixar un client tipus steam.  L'arranquem amb el wine i vegem que instal·la, actualitza...
    I vegem que ens demana usuari:


    Una vegada posem correctament l'usuari i password ens ix la nostra biblioteca de jocs, des d'on podem seleccionar quins volem descarregar/instal·lar si no els tenim:
    De moment he posat a descarregar el Dragon Age, però és prou tard i ja és tard, demà provaré si funciona ;)

    Val, acaba de donar-me error de descàrrega i pel que he llegit pareix que no es puga instal·lar en Linux. Aarrg


    10 minuts més tard

    Prove en PlayOnLinux, li pose el títol i després d'un parell d'assistents, descàrregues... Em demana des d'on vull instal·lar, provarem des de Steam Store a veure si el l'abaixa. Per començar, m'instal·la l'Steam (per sort ja tinc usuari):

    Quan instal·lem ens demana actualitzar (per que no t'abaixes res actualitzat mai?). Després d'instal·lar-se, tenim l'steam instal·lat però pensava que s'abaixaria el joc o algo. No l'has de comprar tu i no he pogut posar el codi qu eme donen a Origin en l'Steam.


    Però qui sap igual hi ha alguna manera d'aprofitar el serial obtés amb origin ;) Però amb l'Steam, es veu que no.

    Drivers ATI

    Bo, per defecte, en teoria es podria instal·lar automàticament els drivers des de la finestreta de controladors restrictius, però a mi m'ha donat un error, per tant he anat a la pàgina web i m'he abaixat els drivers:

    els he descomprimit (unzip nomarxiu.zip) i anem a executar l'script que ens apareix com a superusuari, i ens apareixerà un assistent:


    Quan acaba, ens demana reiniciar i en teoria ja estaria, però no va ser tan fàcil. A mi almenys em donava un error. He hagut de esborrar tots els paquets (pareix ser que a l'intentar amb els controladors restrictius deixava paquets a mitges i feia conflicte amb l'instal·lador de la web). He hagut d'executar:
    sudo sh /usr/share/ati/fglrx-uninstall.sh 
    sudo apt-get remove --purge fglrx fglrx_* fglrx-amdcccle* fglrx-dev*
     
    he tornat a reiniciar, a instal·lar i ara si que m'ha anat bé, Aplicacions->Ferramentes del Sistema->Preferències->Amd Catalyst Control Center:

     Provem el glxgears i obtenim 6000fps no està mal, no?

    Comencem

    Arranquem amb la versió 14.04 de lliurex. De moment pareix que vaja bé en un alienware m17x r4 :
    intel i7 3610QM
    8GB de RAM
    disc dur SSD
     ATI HD7970

    Veurem quins resultats va donant:


    dimecres, 8 d’octubre de 2014

    Primer mal de cap en javascript, l'abast de les variables

    Per sort o per desgràcia vaig decidir provar javascript (en part per què volia veure com funcionava jasmine per fer tests, hauré de fer un altre post amb això).
    Aneu a veure el meu mal de cap, imaginem aquest codi:

    function recorrecvector2(){
      for(i=0;i<vector2.length;i++){
          //fer algo amb el vector2
         }
      }

    for(i=0;i<Vector.length;i++){
      recorrecvecto2();
    }


    Així a simple vista pot resultat correcte, però, però, però... resulta que en Js al no haver declaració de tipus, les variables "comencen el seu abast" quan són declarades i no són "substituïdes" a no ser que posem var. Si ens fixem amb l'index i dels bucles, és la mateixa variable. tant en el bucle de fora com en la funcio recorrecvector2. Els resultats són esotèrics ;). Amb una declaració estricta de tipus això no passaria, però javascript (ni en general cap llenguatge d'scripting) solen tindre eixe tipus de declaració. Després de dos dies calfant-me el cap, amb alerts per totes bandes, simplement posar un var davant de la primera i en cada bucle for se soluciona:

    function recorrecvector2(){
      for(var i=0;i<vector2.length;i++){
          //fer algo amb el vector2
         }
      }

    for(var i=0;i<Vector.length;i++){
      recorrecvecto2();
    }

    dimecres, 1 d’octubre de 2014

    PHP vs Node.js: rendiment en concurrència

    Bo, doncs per motius laborals i familiars he estat un poc absent (del bloc), però ja aprofitant unes proves que he fet al treball, vaig a mostrar els resultats obtesos.
    En principi, com sempre li he tingut mania al javascript, pensava que seria més lent que el php, però pareix ser que l'asincronisme fa que en determinades coses vaja molt més ràpid. La prova consisteix en recorrer un parell de taules enormes (400k registres) i fer alguns càlculs. He fet les proves amb el benchmarking de apache (ab), anem a veure el codi, he obviat les consultes per simplificar:

    PHP

    $sql='';
    $preguntesResult =  mysql_query($sql) or die('Consulta fallidaA: ' . mysql_error());

    $sqlrespostes= ''
    $respostesResult =  mysql_query($sqlrespostes) or die('Consulta fallidaB: ' . mysql_error());
    while($line = mysql_fetch_array($preguntesResult, MYSQL_ASSOC)){
      $preguntes[]= $line;
    }
    foreach ($preguntes as $pregunta) {

    }
    $cadena = "";
    while($line = mysql_fetch_array($respostesResult, MYSQL_ASSOC)){
      $respostes[] = $line;

      foreach($preguntes as $pregunta){
          $cadena .= $pregunta["id"] . ":" . $line["pregunta"] . "\n";
          //echo $cadena;
      }
    }
    file_put_contents("volcat1.php.txt",$cadena,FILE_APPEND);
    foreach($preguntes as $pregunta){
      //
    }


    Node.js


    var mysql = require('mysql');
    var http = require('http');

    function doProcess(req, res) {
      var connection = mysql.createConnection({
      });
      connection.connect();
      respostes = [];
      preguntes = [];
      sql = ';
      connection.query(sql, function(err, rows, fields) {
        if (err) throw err;
        for (i = 0; i < rows.length; i++) {
          preguntes[i] = rows[i];
        }
        for (i = 0; i < preguntes.length; i++) {

        }
        for (i = 0; i < preguntes.length; i++) {

        }
      });
      sql2 = '';
      cadena = "";
      connection.query(sql2, function(err, rows, fields) {
        if (err) throw err;
        for (i = 0; i < rows.length; i++) {
          respostes[i] = rows[i];
          for (j = 0; j < preguntes.length; j++) {        
            cadena += preguntes[j]["id"] + ":" + respostes[i]["pregunta"] + "\n";        
          }
        }
          res.writeHead(200, {
            'Content-Type': 'text/html'
          });
          res.write('Acabat');
          res.end();
        }
      });

      connection.end();
    }
    server = http.createServer(doProcess);
    server.listen(8080);


    Els resultats em van sorprender, executats a aquesta màquina:
    CPU: Intel(R) Core(TM)2 Duo CPU E8400 @ 3.00GHz
    RAM: 4GB 
    a un lliurex 14.04 Pime, anem a fer 10000 peticions amb una concurrència de 10 simulant les peticions que anaven a fer.

    Provem el benchmark php:

    ab -r -n 10000 -c 10 http://localhost/benchmark1.php

    i el resultat:

    Server Software: Apache/2.4.10
    Server Hostname: localhost
    Server Port: 80

    Document Path: /benchmark1.php
    Document Length: 6 bytes

    Concurrency Level: 10
    Time taken for tests: 5123.183 seconds
    Complete requests: 10000
    Failed requests: 0
    Total transferred: 2080000 bytes
    HTML transferred: 60000 bytes
    Requests per second: 1.95 [#/sec] (mean)
    Time per request: 5123.183 [ms] (mean)
    Time per request: 512.318 [ms] (mean, across all concurrent requests)
    Transfer rate: 0.40 [Kbytes/sec] received

    Connection Times (ms)
    min mean[+/-sd] median max
    Connect: 0 0 0.0 0 0
    Processing: 936 5123 1472.6 5331 9829
    Waiting: 936 5119 1471.5 5325 9829
    Total: 936 5123 1472.6 5331 9829

    Percentage of the requests served within a certain time (ms)
    50% 5331
    66% 5901
    75% 6233
    80% 6392
    90% 6864
    95% 7272
    98% 7737
    99% 8073
     100% 9829 (longest request)  


    És a dir, 1,42 hores en fer el test, una mitjana de 5s per petició. Ara provem el codi en node:

    ab -r -n 10000 -c 10 http://localhost/:8080

    i el resultat:

    Server Software:        Apache/2.4.10
    Server Hostname:        localhost
    Server Port:            80

    Document Path:          /:8080
    Document Length:        278 bytes

    Concurrency Level:      1000
    Time taken for tests:   59.963 seconds
    Complete requests:      100000
    Failed requests:        698
       (Connect: 0, Receive: 206, Length: 286, Exceptions: 206)
    Non-2xx responses:      99714
    Total transferred:      45669012 bytes
    HTML transferred:       27720492 bytes
    Requests per second:    1667.70 [#/sec] (mean)
    Time per request:       599.630 [ms] (mean)
    Time per request:       0.600 [ms] (mean, across all concurrent requests)
    Transfer rate:          743.77 [Kbytes/sec] received

    Connection Times (ms)
                  min  mean[+/-sd] median   max
    Connect:        0   18 255.1      1    7016
    Processing:     3  156 2055.9      9   52491
    Waiting:        0  103 1720.5      8   39935
    Total:          5  174 2103.1     10   52491

    Percentage of the requests served within a certain time (ms)
      50%     10
      66%     10
      75%     11
      80%     11
      90%     13
      95%     16
      98%     22
      99%   1190
     100%  52491 (longest request)


    Sorprenentment, i després d'esperar més d'una hora i mitja a l'enterior test, este tarda quasi un minut per a resoldre el mateix problema. Després d'un dia revisant el codi per que pareix que hi haja un error, per mi i per altra gent, i vegent i comparatnt resultats, vegem que node.js guanya en el seu terreny, és a dir, múltiples peticions concurrents. Ja que node no es bloqueja en cap cas, i en php cada petició a la base de dades és bloquejant.
    Vol dir que sempre va millor node.js? Doncs supose que no, però en este cas, absolutament sí, com s'ha demostrat.

    dilluns, 21 de juliol de 2014

    TDDs a Unity (i V)

    Al final, la demo la podeu veure a :
    http://hangedman.vicentfernandez.cat/

    Necessitareu instal·lar el plugin d'Unity

    Utilitzar un gestor de plantilles en php: Twig

    Tenia un parell de projectes a la vista, un personal i un altre per a una empresa en php, ambdós fallats ;) vaig començar a fer-los, i vaig pensar en utilitzar una cosa que tenia pendent: un gestor de plantilles en php. Em vaig decidir a utitzar Twig (no per res, però li tenia mania a smarty per què és el que gasta Vicent-Santi-programadorphp.es).

    Em va sorprendre com n'era de fàcil d'utilitzar, per a realitzar una aplicació normal he utilitzat 3 "capes":

    • Scripts d'accés a la base de dades mysql en php, cada petició tornarà el resultat en JSON
    • Scripts php que faran el processaran la plantilla
    • La plantilla on es poden mesclar diferents llenguatges: Html,css, javascript i "Twig". Per al disseny he gastat bootstrap i com a framework javascript: jquery.


    Per a instal·lar el Twig només farà falta baixar-lo en una carpeta i enllaçar-lo a la nostra aplicació. Anem a fer per exemple la pantalla de login:

    <?php
    require_once 'Twig/Autoloader.php';
    Twig_Autoloader::register();
    $loader = new Twig_Loader_Filesystem('templates');
    $twig = new Twig_Environment($loader, array(
    'cache' => 'cache',
    ));
    $template = $twig->loadTemplate('index.html');
    echo $template->render(array("user"=>"usuari"));
    ?>

    Bàsicament es dedica a  a crear l'objecte Twig, després agarrarà de la carpeta templates ( Twig_Loader_Filesystem('templates') ) , l'arxiu index.html, guardarà els resultat ja processat en la carpeta cache i després el renderitza. el renderitzat consisteix en substituïr l'array passat en render() per unes variables del llenguatge Twig en la plantilla. En aquest cas, es crearà una variable "user" amb el valor "usuari".
    Anem a veure com seria la plantilla: (anem a deixar de banda el javascript/css):
    <body>        
            <form name="formulari" class="form-horizontal" role="form">

                <div style="display: block; margin-left: auto; margin-right: auto;">
                    <div class="form-group">
                        <label for="login" class="control-label col-xs-3">Login</label>
                        <div class="col-xs-4">
                            <input type="text" class="form-control col-xs-4 col-md-4 col-sm-4" id="login" placeholder="{{user}}" />
                        </div>
                    </div>
                    <div class="form-group">
                        <label for="pass" class="control-label col-xs-3">Password</label>
                        <div class="col-xs-4">
                            <input type="password" class="form-control" id="password" placeholder="password" />
                        </div>
                    </div>
                    <div class="form-group">
                        <div class="col-xs-offset-3 col-xs-6">
                            <button type="button" class="btn btn-default bg-danger" id="botoSubmit">Entrar</button>
                        </div>
                    </div>
                    <p class="bg-danger col-xs-4 col-xs-offset-3" id="missatgeerror"></p>
        </div>
            </form>
        </body>
    Vegem de roig la variable user entre  {{}}. Això substituïrà {{user}} i mostrarà el seu valor "usuari":






    En la propera entrega veurem el codi jquery/bootstrap i les crides en ajax als scripts php ;)

    dimecres, 11 de juny de 2014

    TDDs a Unity(IV)

    I per últim, ara que les obligacions familiars m'han donat un respir (tinc al menut dormint al meu costat), li posarem una interfície gràfica al nostre joc. Com ja sabeu he triat Unity 3D, per què m'encanta, i accepta el meu llenguatge de programació preferit (C#) per a l'scripting. El primer que he fet és crear uns apassionants gràfics amb el meu supertalent i el... mspaint!!! Per no avorrir-vos, vos pose un exemple:











    Com podreu suposar, he creat una imatge per cada "vida", com el típic joc del penjat, així només s'ha de carregar en cada moment la imatge corresponent al nombre de vides (es podria fer més difícil, composant, animant... però el disseny no m'agrada, és molt avorrit i tediós i valdria més l'esperat que l'escurada).

    Ara vos pose els objectes que he posat:



    Si mirem la imatge tenim:
    • 1 Sprite, Vides que es on anem posant la imatge del penjat segons les vides
    • 5 3DText (TextMesh):
    1. Paraula: La paraula que hem d'encertar, les lletres que encara no hem encertat apareixeran amb un _
    2. LletresOK i LletresOK: una etiqueta indicant que davall està la llista de lletres encertades/fallades
    3. LletresOKText i LletresKOText: la llista de lletres encertades i fallades
    • La càmera
    • Un objecte (buid) GameController on he assignat l'script de control de joc (podria estar en la càmera, però no m'agrada barrejar coses)






    Ara anem al codi de l'script assignat a gamecontroller, primer definim les variables que anem a gastar:

                    private string Word;
    private string LettersOK;
    private string LettersKO;
    private int Lifes;
    private HangMan hang;
    private TextMesh WordCompletedText;
    private TextMesh LletresOKText;
    private TextMesh LletresKOText;
    private SpriteRenderer SpR;
    public Sprite[] Vides;





    La variable Sprite serà pública per que així podrem definir-la amb les imatges des de unity sense tocar una línia de codi, ja que les variables públiques apareixen a l'inspector de l'objecte a Unity.
    Continuem, a l'start, és a dir a la creació simplement creem l'objecte del joc hang:
                    void Start ()
    {
    hang = new HangMan ("hola");
    }
    Faltaria també posar el wordextractor, però per a este exemple no l'hem gastat, per simplificar. I ara el controlador que estarà en la funció OnGUI, tindrà 4 blocs:
    1. Assignació de variables
    2. Mostrar les variables
    3. Comprovar guanyat/perdut i mostrar missatge
    4. Comprovar si s'apreta una tecla i executar l'intent d'endivinar

    void OnGUI ()
    {
    //BLOC1
    Word = hang.GetWordCompleted ();
    Lifes = hang.lifes;
    LettersOK = hang.LettersOK;
    LettersKO = hang.LettersTried;
    WordCompletedText = (TextMesh)GameObject.FindWithTag ("WordCompleted").GetComponent (typeof(TextMesh));
    LletresOKText = (TextMesh)GameObject.FindWithTag ("LletresOK").GetComponent (typeof(TextMesh));
    LletresKOText = (TextMesh)GameObject.FindWithTag ("LletresKO").GetComponent (typeof(TextMesh));
    //BLOC2
    LletresOKText.text = LettersOK;
    LletresKOText.text = LettersKO;
    WordCompletedText.text = Word;
    SpR = (SpriteRenderer)GameObject.FindWithTag ("Vides").GetComponent (typeof(SpriteRenderer));
    SpR.sprite = Vides [Lifes];
    //BLOC3
    if (Lifes == 0) {
    print ("you die");
    }
    if (hang.WordCompleted ()) {
    print ("you win");
    }
    //BLOC4
    if (Input.anyKeyDown) {
    Event e = Event.current;
    if (e.isKey) {
    if (e.keyCode >= KeyCode.A && e.keyCode <= KeyCode.Z) {
    hang.GuessLetter (e.keyCode.ToString ().ToLower () [0]);
    }
    }
    }
    }

    L'única cosa que pot ser siga complicada és esta línia:
    SpR.sprite = Vides [Lifes]; 
    Com al vector d'sprites Vides tenim totes les imatges corresponents al penjat (sense cap part del cos a tot el cos una a una, en total 7: res, cap, tronc, braç esquerre,braç dret, peu esquerre, peu dret), li assignarem el corresponent a les vides que tinga. SpR és l'objecte sprite "Vides" que podem veure a la captura de pantalla de l'entorn Unity que he posat adés.
    En breu posaré el projecte per a baixar, i podreu veure la versió web a:
    http://hangman.vicentfernandez.cat (Encara no disponible)

    dilluns, 9 de juny de 2014

    TDDs a Unity(III)

    Bo, seguint amb el joc del penjat, ara necessitarem alguna font de dades de les paraules. La forma més fàcil que he pensat és llegir d'un arxiu que continga un text (aleatori, lliure...) i extraiga una paraula, és a dir,

    • Indique l'arxiu
    • demane una paraula entre min i max lletres (ens permetrà configurar nivell de dificultat)
    • si després d'un determinat nombre d'intents no la trobe retorne "fail" (alguna cosa debia de fer)

    Per tant només he trobat dos TDDs reals (altres com arxiu no existent... no els he contemplat, la veritat):

    • TestFailWord()
    • TestWordBetwenLimits()

    Analitzem el codi del primer test:

     [TestMethod]
            public void TestFailWord()
            {
                WordExtractorClass W = new WordExtractorClass(@"C:\Users\Vicent\Desktop\prova.txt", 100,200);
                W.getNewWord();
                Assert.AreEqual(W.CurrentWord, "fail");
            }

    Demanem de l'arxiu una paraula entre 100 i 200 lletres (suposem que no existeix) i comprovem que la paraula siga el cas d'error

    Vegem el segon:

    [TestMethod]
            public void TestWordBetwenLimits()
            {
                WordExtractorClass W = new WordExtractorClass(@"C:\Users\Vicent\Desktop\prova.txt", 6, 10);
                W.getNewWord();
                string _w = W.CurrentWord;
                Assert.IsTrue(_w.Length >= 6);
                Assert.IsTrue(_w.Length <= 10);
                Assert.AreNotEqual(_w, "fail");
            }
    Igual que l'anterior però ara la demanem entre 6 i 10 (per exemple). Comprovem que estiga entre els límits i que la paraula no siga "fail". L'última comprovació és per què en algun test vaig posar límits entre 2 i 6, i tornava "fail" que si que acomplia eixos requisits però era debut error del programa.


    Si ens fixem ja tenim el joc en c#. Ara només necessitem una interfície. Es pot programar en mode consola, en unity, XNA, DirectX... el que siga, podem empotrar-ho on vullgam que el que és el joc, ja està creat.

    dissabte, 7 de juny de 2014

    TDDs a Unity (II)

    Bo, doncs com ja comentava intentarem crear un joc simple del penjat. Les regles són simple:

    1. Es tria una paraula
    2. Es tenen 6 vides (cap, braços, cos, cames)
    3. La paraula ix inicialment substituida cada lletra per un caràcter '_'
    4. Es pot elegir entre resodre i endivinar una lletra
    • Si resols i encertes guanyes
    • Si resols i no encertes perds una vida
    • Si endivines una lletra se substituix el caràcter '_' per la lletra corresponent en la posició pertinent
    • Si no encertes la lletra perds una vida


    Comencem a programar ;) Obrim el Visual Studio i creem un projecte C# (per exemple de consola). Si no elegixes un projecte buid com jo, a l'intentar fer els tests, et dona un error que no troba cap main, te tocarà crear un nou arxiu.cs, i posar-li una funció main dummy:


     class Program
        {
            static void Main(string[] args)
            {
            }
        }

    Afegim a la solució un projecte nou de test (ja ho vaig explicar a un altre post) i automàticament ens crea un test d'unitat, jo vaig pensar en aquestos tests:

    • public void GuessWordOK()
    • public void GuessWordFail()
    • public void LetterFail()
    • public void LetterOK()
    • public void WordCompleted()
    • public void WordNotCompleted()
    • public void YourDead()
    • public void CantGuessWordWhenDead()
    • public void CantGuessLetterWhenDead()
    • public void IndexIsGuessed() (Este crec que no faria falta )
    • public void GetLetterAtIndex() (Este crec que tampoc faria falta)
    • public void GetWordCompleted() 


    No vaig a copiar i pegar totes les funcions per no avorrir (potser puge el codi el github), mirem per exemple la primera i la última:

     [TestMethod]
            public void GuessWordOK(){
                Tests.HangMan Hang = new Tests.HangMan("hola");
                bool res1 = Hang.DoTry("hola");
                Assert.IsTrue(res1);
            }
    Creem la classe penjat (el joc), i intentem endevinar la paraula.
    [TestMethod]
            public void GetWordCompleted()
            {
                HangMan Hang = new HangMan("hola");
                Hang.GuessLetter('o');
                Hang.GuessLetter('l');
                Hang.GuessLetter('z');
                Assert.AreEqual("_ol_", Hang.GetWordCompleted());
            }
    Creem la classe joc i després de 3 intents (dos encertats i un fallit) comprovem que les lletres encertades estan actives i les que no amb un '_'

    TDDs a Unity

    Sí ja sé que feia molt de temps que no escrivia al bloc, no és que ho tinga abandonat, però acabe de ser pare, i l'embaraç i la meua xiqueta i el treball han segut prou durets últimament. A banda, duc aprenent a gastar Unity3D estos temps, la veritat és que estic enamorat del seu sistema, i a més em permet gastar el meu actual llenguatge preferit: C#.
    Unity no és un entorn de desenvolupament, si no un entorn per a la creació de videojocs. Només es gasten llenguatges de programació per al comportament (scripting). Per a això és gasta un editor extern (ve per defecte el Monodevelop, però vaig aconseguir una vegada posar el Visual Studio.). Una de les primere limitacions que veig com a programador, és què Unity3d no està pensat en ells. Per tant no hi ha moltes opcions. Per exemple no he trobat cap eina per a realitzar els TDDs. Pot ser amb un plugin del Monodevelop, però vaig idear no pedre el temps. En un minijoc que estic realitzant ara (dels meus projectes mitjanets ja parlaré en un altre post) vaig pensar aïllar tot el que siga programació i fer-ho amb el Visual Studio amb nunit. Programes totes les classes que necessites (ja vaig parlar a un post anterior) i després inclous els arxius C# al teu projecte Unity. Simplement necessitaràs "programar" la classe de gestió dels objectes i les classes que deriven de MonoBehaviour, però deurien de ser les mínimes. Per exemple, si vullguerem fer un enemic, podriem programar l'atac, els atributs, l'AI... sense capturar update,OnGUI... i després afegir-lo... Estic parlant de C#, si gastem Javascript res ens impedix gastar jasmine, per exemple...

    dimecres, 5 de febrer de 2014

    Aprendre Unity

    Estos dies m'he llegit un llibre totalment recomanable per a aprendre a fer programes en 2d amb unity:

    El podeu comprar en amazon Kindle:

    Tinc pendent el llibre de desenvolupament de jocs en 3d

    Javascript, javascript i més javascript...

    Després d'un temps de pausa, torne a la càrrega... Un anàlisi "de mercat" d'aquest fastigós llenguatge de programació.
     Un dels llenguatges a que més li tinc mania és el javascript. I com sempre que trie, elegisc l'opció incorrecta, estic mirant que és el futur. És increïble veure la quantitat d'adeptes que té.
    [Sempre he relacionat la programació en intèrprets (scripts) amb la mediocritat (els homes de deveres programes en llenguatges compilats) Primer va ser en ASM->C/Pascal. Després programació tradicional vs programació orientada a objectes.. I així successivament un seguit de males eleccions. De tota manera, ja fa temps que tot és interpretat (inclús l'ASM) per tant...]
    El cas, que me'n vaig per les rames, és que ha aplegat un moment que pareix que tot se programen en Javascript (inclús les aplicacions d'escriptori!!!). Va iniciar-se com a complement web per afegir certa funcionalitat. Ara podem fer de tot:

    • Funcionalitat bàsica Javascript en el navegador
    • Funcionalitat avançada amb moltes biblioteques i comunicació amb un servidor (jquery, ajax...)
    • Disseny web (css, jquery...)
    • Programació de servidor : node.js
    • Programació d'aplicacions d'escriptori (les noves aplicacions de Windows Store 8.1 es podran programar directament en JS)
    • Llenguatge de base de dades: MongoDB és una base de dades no SQL que funciona amb javascript
    • Llenguatge de comunicació: ara la informació entre dos aplicacions, dos parts de l'aplicació o client-servidor sol ser cadenes JSON (arrays de Javascript) en detriment de l'XML
    • Programació de jocs. A banda de la gran quantitat de frameworks  de jocs que des d'HTML 5 s'han incorporat. Fins i tot Unity 3D suporta com a llenguatge d'scripting (per al comportament) JS o C# (es poden barrejar al mateix projecte però en unitats diferents).
    • A banda, hi ha classes intèrprets de JS en molts llenguatges de programació (java...)
    Podríem (potser deuríem) de pensar que és el llenguatge del futur, però té ventatges i inconvenients:

    Ventatges (Alta productivitat)
    • Curva d'aprenentatge molt ràpida
    • Moltes biblioteques ja implementades 
    Inconvenients
    • No es pot fer debug/depuració (almenys en la majoria de sistemes)
    • Els llenguatges interpretats solen ser més lents que els compilats
    • En la majoria d'entorns no es defineixen les varaibles: errors difícils de detectar
    • No està tipat: pot ser una ventatja al ser més ràpid programar però un inconvenient a l'hora de revisar/definir aplicacions: "3" +"3" és "33" o "6"?
    En fi, veure'm que ens depara el destí ;)