Autofirma DNIe falla en MacOS

Quan el programa autofirma s’obre i a continuació es tanca, hem de fer un by-pass per solucionar-ho.

Descripcio: En intentar executar l’aplicacio Autofirma s’observa com apareix la icona al dock i automaticament es tanca.

El problema és que internament intenta executar la següent ordre:

/Applications/AutoFirma.app/Contents/Resources/Home/bin/AutoFirma -Xms1024M -Xmx2048M -Dcom.apple.macos.useScreenMenuBar=true -Xdock:name=AutoFirma -Xdock:icon=/Applications/AutoFirma.app/Contents/Resources/JAR/afirma.icns -Djava.library.path=/Applications/AutoFirma.app/Contents/Resources/JAR -jar /Applications/AutoFirma.app/Contents/Resources/JAR/Autofirma.jar

Com es pot observar s’intenta executar el jar Autofirma.jar però en inspeccionar el paquet s’observa que existeix però amb la f en majúscula (AutoFirma.jar). Si s’ha triat un sistema de fitxers que diferencia majúscules de minúscules l’aplicació no funciona.

Workaround: Obrir una terminal i executar les següents ordres

$ cd /Applications/
$ cp AutoFirma.app AutoFirma.bak
$ cd AutoFirma.app/Contents/Resources/JAR
$ sudo mv AutoFirma.jar Autofirma.jar

https://github.com/ctt-gob-es/clienteafirma/issues/182

Introducció a Unity

Pas Zero: El disseny

Primer, pensem en les peces i parts de Pong: la “mecànica” individual (les regles i les característiques del joc) que haurem de programar.

  1. Teniu un fons per jugar
  2. Teniu un conjunt de paletes que pugen i baixen
  3. Teniu una bolla que rebota de parets i paletes
  4. Teniu un conjunt de parets laterals (dreta i esquerra) a les que heu d’arribar amb la bolla per poder anotar
  5. Teniu una puntuació per mostrar i actualitzar
  6. Teniu un botó de restabliment per poder tornar a començar la partida.

Comencem!

Primer pas: La configuració

Primer, descarregueu aquest fitxer. Conté imatges i altres recursos que utilitzarem en aquest tutorial.

Ara podem començar a configurar el nostre projecte. Obriu Unity i seguiu aquestes passes:

  1. Des de la pantalla de benvinguda, feu clic a Projectes. (Si l’editor Unity ja està obert, feu clic a Fitxer> Projecte nou.)
  2. Feu clic a “Nou”. Llavors, hauríeu de veure alguna cosa així:
  1. Poseu un nom al projecte, per exemple Pong.
  1. Assegureu-vos de triar la plantilla 2D.
  2. Feu clic a Create

Un cop creat el projecte, haureu de veure una graella en 2D a la vista Escena.

Configurar Unity en mode 2D fa diverses coses. En primer lloc, configura la nostra càmera de jocs perquè tot es vegi des d’una perspectiva 2D. També diu a Unity que importi imatges com Sprites en lloc de Textures. 

Recordeu aquell fitxer que hem descarregat? Ara és un bon moment per descomprimir aquest fitxer. Un cop ho facis, veuràs una carpeta anomenada unitspong-assets, que contindrà un conjunt d’imatges, tipus de lletra i altres actius que utilitzarem avui. Seleccioneu tots aquests fitxers i, a continuació, feu clic + arrossegueu-los al plafó Projecte de la part inferior de la finestra Unity. Ara hauria de sortir una cosa així:

Fes clic + arrosega la imatge Background des del panell Project al panell Hierarchy, just davall Main Camera. Haura d’aparèixer a la vista Scene, centrat per defecte. Si no està centrat, utilitza el panell Inspector per posar Transform Position a (0,0,0).

Selecciona el fons, ara al panell Hierarchy, i s’hauria de veure al panell Inspector de la següent manera:

Primer, a la part superior de l’inspector de Transform, canvieu la seva escala per (0.75, 1, 1). Això farà que es vegi millor en el nostre joc. Ara mireu el component Sprite Renderer. Volem assegurar-nos que el fons es mostra darrere dels altres sprites i no apareix accidentalment al damunt. Vés a Sorting Layer i fes clic a Add Sorting Layer. El plafó Inspector ara hauria de quedar així:

Feu clic a la icona + per afegir la nova capa. Canvieu el nom de “New Layer” a “Background”, després feu clic i arrossegueu la nova capa per sobre de la capa predeterminada. És important que col·loqueu la nova capa damunt la capa Default, ja que d’aquesta manera, qualsevol cosa de la capa d’ordenació de fons apareixerà darrere de qualsevol cosa de la capa predeterminada, que és exactament el que volem.

Ara torneu a seleccionar Background al plafó Hierarchy per tal que es mostri de nou a l’Inspector. Al component Sprite Renderer, feu clic al menú desplegable per ordenar la capa i escolliu la nova capa de fons. El vostre inspector hauria de quedar així:

A continuació, hem de fer alguns canvis a la càmera principal perquè el nostre joc quedi més agradable.

Seleccioneu càmera principal al plafó de Hierarchy. L’objecte de la càmera controla com veiem el món del joc (o “Escena”, en termes d’Unity). Quan juguem al nostre joc Pong, és possible que el nostre fons no sigui prou grans per cobrir tota la pantalla. Hem de fer dos petits canvis a la càmera principal per tenir-ne cura.

A l’Inspector, al component Càmera, canvieu la Mida a 3. Això augmentarà lleugerament sobre el fons. A continuació, feu clic a la fons propietat dede la càmera. Això ens permet canviar el color que serà visible a les vores de la pantalla si el fons no és prou gran. Trieu el color negre amb el selector de colors amb valors RGBA de (0,0,0,0). Aleshores, el component de la càmera a l’Inspector hauria de quedar així: 

Seria bo en aquest punt guardar els canvis pitjant CTRL+S

Passa 2: Les paletes

El següent pas és fer les nostres paletes. Cerqueu la imatge anomenada PongPaddle al plafó del projecte.

Ara feu clic i arrossegueu la imatge de la paleta a l’escena de la vista View. Un objecte PongPaddle hauria d’aparèixer al menú Hierarchy.

Feu clic a PongPaddle a la jerarquia. Al inspector, canvieu el nom a Paddle1 i feu clic al menú desplegable Tag i seleccioneu Player. (Més informació sobre això més endavant.) Definiu la posició a (X, Y, Z) = (-4, 0, 0) i Escala a (0,5, 1,5, 1). S’hauria de mostrar així a l’Inspector:

El que fem aquí és assegurar-nos que la paleta estigui situada on el volem. La capa d’ordenació i altres paràmetres no importen aquesta vegada, perquè volem que aquest objecte es dibuixi a la part superior, a la qual es defineix per defecte Unity.

A continuació, afegirem dos components a l’objecte Player. Feu clic al botó Add Component, a continuació, a Physics 2D. Aquí afegiu un Box Collider 2D i un Rigidbody 2D. El Box Collider 2D servirà per assegurar-se que la pilota rebotarà de la seva paleta i que el Rigidbody 2D perquè puguem moure la paleta.

Nota: és important utilitzar Physics, Box Collider i Rigidbody 2D aquí, ja que existeixen versions en 3D, no és el que volem en el nostre joc en 2D.

Ara, farem alguns canvis al component Rigidbody 2D. Unity té un gran sistema integrat de física realista que calcula els efectes de la gravetat, la fricció i altres forces sobre qualsevol objecte que tingui un component 2D Rigidbody. Sovint, aquest sistema és molt útil, però no el volem utilitzar per a les nostres paletes. Les nostres paletes no són exactament realistes, només són una mena de flotació a l’espai i només es mouen quan les expliquem. Per sort, Unity ens proporciona una manera de dir que el nostre Rigidbody 2D només es mogui quan ho expliquem. Només hem de fer clic al desplegable Body Type i seleccionar Kinematic.

Ara començarem la part interessant: afegir un script pel moviment de les nostres paletes.

Per afegir un script, seleccioneu Paddle1 al plafó de Jerarquia i, a continuació, aneu a Add Component i afegiu un nou script. Li podeu posar de nom PlayerControls, i a continuació, feu clic a Create and Add. L’script ara hauria d’aparèixer com a component i al panell de projecte 

Podeu fer-li clic a sobre i s’obrirà amb l’editor predeterminat segons el vostre sistema (Visual Studio, MonoDevelop, etc.)

Descripció del codi

El primer que apareix quan s’obri l’editor de codi són tres línies que corresponen a uns import en Java.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Just a continuació ve la definició de la classe PlayerControls que es correspon amb el nom que acabam de posar a l’script.

public class PlayerControls : MonoBehaviour {

A continuació de la definició de la classe ja haurem de posar unes línies que són les variables que utilitzarem

public KeyCode moveUp = KeyCode.W;
public KeyCode moveDown = KeyCode.S;
public float speed = 10.0f;
public float boundY = 2.25f;
private Rigidbody2D rb2d;

Les dues primeres com podeu intuir, corresponen a la definició de les tecles que volem utilitzar per la paleta. La següent és la velocitat de desplaçament de la paleta. La variable boundY és la posició més alta a la qual podrà arribar la paleta. Això evitarà que segueixi movent-se per amunt més enllà dels límits de la pantalla. La darrera variable referida al Rigidbody2D l’utilitzarem més endavant.

Start() és la funció que s’executará quan iniciem el joc. L’utilitzarem per fer qualcunes configuracions inicials, com per exempla al Rigidbody2D:

void Start () {
   rb2d = GetComponent<Rigidbody2D>();
}

Update() és una funciós que s’executarà una vegada per frame. L’utilitzarem per saber quin botó s’ha pitjant i moure la paleta en consonància, o, si no s’ha pitjat cap botó mantenir la paleta al seu lloc. Finalment limitarem la paleta verticalment entre +boundY and -boundY, la qual cosa ens la mantindrà dintre de la pantalla del joc en tot moment.

    void Update()
    {
        var vel = rb2d.velocity;
        if (Input.GetKey(moveUp))
        {
            vel.y = speed;
        }
        else if (Input.GetKey(moveDown))
        {
            vel.y = -speed;
        }
        else if (!Input.anyKey)
        {
            vel.y = 0;
        }
        rb2d.velocity = vel;

        var pos = transform.position;
        if (pos.y > boundY)
        {
            pos.y = boundY;
        }
        else if (pos.y < -boundY)
        {
            pos.y = -boundY;
        }
        transform.position = pos;
    }

Aquí teniu el codi complet per descarregar PlayerControls.cs

Ara assegura’t de gravar els canvis a l’editor.

En aquest punt ja podreu provar que efectivament la paleta es pot moure. 

És important destacar que durant el mode de joc, podeu veure (a mode de debug) com es van modificant el paràmetres a través del Inspector i fins i tot modificar-los a la vostre conveniència, però tot allò que faceu durant el mode de joc no es quedarà guardat després.

Ara tornam pitjar el botó de Play per abandonar el mode de joc.

Crearem la segona paleta. Per això podrem duplicar l’objecte Paddle1 i posar-li de nom Paddle2. Ho farem al plafó Hierarchy fent clic amb el botó dret a sobre de Paddle1 i a continuació Duplicate.

Hem de canviar les tecles de moviment i la seva posició inicial. Podem posar, per exemple ‘Up Arrow’ per anar cap amunt i ‘Down Arrow’ per anar cap abaix. La posició serà (4, 0, 0), recordeu que això ho feim al plafó Inspector havent seleccionat Paddle2 a Hierarchy.

Ara hauríem de tenir una cosa semblant a això:

Podem tornar al mode de joc per comprovar que tot funciona tal i com esperam.

Passa 3: La bolla

La bolla és una mica més complicat que les paletes però no gaire més. Pensem que la bolla ha d’anar rebotant per la pantalla, detectar la puntuació i interaccionar amb les paletes.

Per començar, localitzarem la imatge Ball al panell Project abaix de la pantalla (és la icona blava). La seleccionem i l’arrosseguem cap al plafó de jerarquia. Ara tindrem un nou objecte anomenat Ball que el seleccionarem i anirem a modificar els seus atributs al panell Inspector.

Primer crearem una etiqueta. Les etiquetes són la manera d’identificar objectes de joc únics d’Unity i és realment senzill utilitzar-les per trobar objecte. A la part superior de l’Inspector, feu clic a Tag > Add Tag… i l’Inspector canviarà per mostrar les etiquetes i les capes. 

Ara, hem de fer clic a  + per afegir una nova etiqueta. Anomenem-ho Ball. Guardam i en tornar en el desplegable d’etiquetes seleccionarem la nova etiqueta que hem creat.

Canvia l’escala de la nostra bolla a (0,5, 0,5, 1). Una pilota més petita ajuda a fer que el joc se senti més ràpid i divertit.

A continuació, hem d’afegir components similars als que hem fet a la paleta. Feu clic al botó Add Component i afegeix un component Physics 2D, en aquest cas seleccionarem Circle Collider 2D i, per descomptat, Rigidbody 2D. Al Collider de cercles, canvia el radi a 0,23. D’aquesta manera el col·lisionador s’envolta molt més a la pilota.

També volem aplicar un material de física 2D. Seleccioneu BallBounce del plafó del projecte i mireu l’Inspector. Veureu que el valor de fricció és 0 i el factor de rebot (bounce factor) és 1. D’aquesta manera la nostra bola no experimenta fregaments de res, incloses les nostres paletes i parets. El factor de rebot significa que tampoc perd cap velocitat. Rebota amb la mateixa velocitat exacta amb la que va assolir l’objecte.

Per aplicar el material, seleccioneu Ball a l’Inspector i, a continuació, feu clic i arrossegueu el BallBounce material al quadre Circle Collider 2D. També necessitem ajustar diversos paràmetres a Rigidbody 2D per aconseguir el nostre comportament desitjat. Ens hauria de quedar així al final:

Però, per descomptat, per aconseguir que la bola es mogui, necessitem codi. Amb la pilota encara seleccionada a la vostra jerarquia, feu clic a Afegeix un component> Nou script. Aquesta vegada anomenarem a l’script BallControl

Descripció del codi

Primer, com sempre, importem els nostres paquets i confirmem que el nostre nom de classe coincideix amb el nostre nom de fitxer (i script).

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BallControl : MonoBehaviour
{

Hem de declarar una variable que després utilitzarem.

private Rigidbody2D rb2d;

També necessitem una funcio GoBall(), que escollirà una direcció aleatòria (a l’esquerra o a la dreta), per després fer que la bola comenci a moure’s.

    void GoBall()
    {
        float rand = Random.Range(0, 2);
        if (rand < 1)
        {
            rb2d.AddForce(new Vector2(20, -15));
        }
        else
        {
            rb2d.AddForce(new Vector2(-20, -15));
        }
    }

Amb start, inicialitzarem la nostra variable rb2d. A continuació, invocarem la funció GoBall(), mitjançant Invoke(), que ens permet esperar abans de l’execució. Es farà esperar dos segons per donar temps als jugadors per preparar-se abans que la pilota comenci a moure’s.

    void Start()
    {
        rb2d = GetComponent<Rigidbody2D>();
        Invoke("GoBall", 2);
    }

ResetBall() i RestartGame() són dues funcions utilitzades per altres scripts que més endavant escriurem. ResetBall() s’utilitza quan es compleix la condició de victòria. Atura la pilota i restableix la seva posició al centre del tauler.

    void ResetBall()
    {
        rb2d.velocity = new Vector2(0, 0);
        transform.position = Vector2.zero;
    }

RestartGame() s’utilitza quan es prem el nostre botó de reinici. Més endavant afegirem aquest botó. Aquesta funció utilitza ResetBall() per centrar la pilota sobre el tauler. Aleshores s’utilitza Invoke() per esperar 1 segon, i després torna a començar la bola movent-se.

    void RestartGame()
    {
        ResetBall();
        Invoke("GoBall", 1);
    }

OnCollisionEnter2D() espera fins que xoquem amb una paleta, i després ajusta la velocitat adequadament utilitzant tant la velocitat de la bola com la de la paleta.

    void OnCollisionEnter2D(Collision2D coll)
    {
        if (coll.collider.CompareTag("Player"))
        {
            Vector2 vel;
            vel.x = rb2d.velocity.x;
            vel.y = (rb2d.velocity.y / 2.0f) + (coll.collider.attachedRigidbody.velocity.y / 3.0f);
            rb2d.velocity = vel;
        }
    }

Resumint, ara tenim dues paletes que funcionen, i ara una bola que rebotarà de forma realista. L’script complet que acabem d’afegir hauria de ser així: 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BallControl : MonoBehaviour
{

    private Rigidbody2D rb2d;

    void GoBall()
    {
        float rand = Random.Range(0, 2);
        if (rand < 1)
        {
            rb2d.AddForce(new Vector2(20, -15));
        }
        else
        {
            rb2d.AddForce(new Vector2(-20, -15));
        }
    }

    // Use this for initialization
    void Start()
    {
        rb2d = GetComponent<Rigidbody2D>();
        Invoke("GoBall", 2);
    }

    void ResetBall()
    {
        rb2d.velocity = new Vector2(0, 0);
        transform.position = Vector2.zero;
    }

    void RestartGame()
    {
        ResetBall();
        Invoke("GoBall", 1);
    }

    void OnCollisionEnter2D(Collision2D coll)
    {
        if (coll.collider.CompareTag("Player"))
        {
            Vector2 vel;
            vel.x = rb2d.velocity.x;
            vel.y = (rb2d.velocity.y / 2.0f) + (coll.collider.attachedRigidbody.velocity.y / 3.0f);
            rb2d.velocity = vel;
        }
    }

}

Aquí teniu el codi sencer per descarregar BallControl.cs

Passa 4: Les parets

Potser ja us heu adonat que la vostra bolla pot volar per la pantalla, però hem de fer unes parets.

Primer fem un objecte de joc que contingui les nostres parets. Assegureu-vos que no s’hagi seleccionat res al plafó de Jerarquia i, a continuació, feu clic amb el botó dret a un espai buit de la Jerarquia i trieu Create Empty. Es crearà un objecte de joc buit simple, que anomenarem Walls. No hem de canviar res, excepte per assegurar-nos que tingui una posició de (0,0,0).

Ara a fer un mur real. Al plafó de Jerarquia, feu clic botó dret a sobre de l’objecte Walls que acabem de fer i escollim Create Empty. Això farà que un objecte de joc nou sigui un “fill” de l’objecte Walls. Per als nostres propòsits, tenir les parets com a fills de “Walls” ens ajudarà a mantenir la jerarquia agradable i clara, ja que podem fer clic a la petita fletxa al costat de Walls sempre que no vulguem veure cada objecte de paret individual. La idea d’objectes de joc fills és realment molt potent i fa molt més que simplement organitzar coses, però no hi aprofundirem gaire en aquest tutorial.

En qualsevol cas, anomeneu a aquest nou objecte secundari RightWall. Assegureu-vos també que aneu a Afegir component i afegiu un Box Collider 2D. Així la pilota rebotarà de l’objecte de la paret, tal com volem.

Ara dupliqueu el nou objecte de paret tres vegades. Anomeneu a aquests duplicats LeftWall, TopWall i BottomWall. Ara necessitem moure i dimensionar les parets perquè estiguin al lloc correcte de la vista del joc. Ara mateix, són només punts que queden al centre de la taula. Hem de fer que semblin parets.

Per al RightWall, configureu la posició (5.8, 0, 0) i la seva escala a (1, 6, 1). Això ho farà agradable i alt. El LeftWall és el mateix, excepte la posició X que és -5.8. (Els números poden ser diferents al vostre ordinador, bàsicament, només assegureu-vos que la pantalla tingui la imatge de pantalla següent, amb les parets dels extrems de cada costat de la vista de la càmera.)

TopWall s’ha de situar a (0, 3.5, 0) amb una escala de (10.7, 1, 1), i BottomWall té la mateixa escala però amb una posició Y de -3,5. Si feu clic a l’objecte “Walls” hauríeu de veure-ho així a la vista Escena:

En aquest punt la pilota rebota però no és el que volíem. És un bon moment per explicar la física que aporta Unity. 

Ara mateix Unity està simulant una bolla amb una massa de 1, una rotació angular de 0.05 i una escala de gravetat de 1. Per això veieu una cosa semblant a això:

En definitiva està simulant una bolla que rebota simulant la vida real. Com que per aquest joc no ho volem així haurem de modificar el paràmetres de manera posem massa a 0.1, angular drag a 0 i Gravity Scale a 0

Si ara tornem a prova el mode de joc veurem com si ja surt com volíem.

A continuació ve una part important, però lleugerament més dura. Hem de fer que aquest sigui un joc real, no només una pilota rebotant. Necessitem un sistema de puntuació, una manera de mostrar la puntuació, alguna condició de victòria i un botó de restabliment.

Passa 5: La interfície d’usuari de puntuació

Primer el que necessitem per a la nostra HUD (Heads-up display) és un objecte de joc. Feu clic amb el botó dret sobre un espai buit al plafó Jerarquia (no a l’objecte del joc de parets!) I trieu Crear buit. Anomeneu al nou objecte HUD, centra la seva posició a (0, 0, 0) i afegiu un nou script a l’objecte HUD anomenat GameManager.

Fixeu-vos que ara l’script té una icona diferent. Serà un script bastant llarg, però és important per al nostre joc.

Descripció del codi

Primer, com sempre, importem els nostres paquets i declarem la nostra classe.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameManager : MonoBehaviour {

A continuació, fem quatre variables. Les dues primeres variables són només nombres enters per fer un seguiment de les puntuacions dels dos jugadors. El següent és un objecte GUI (interfície gràfica d’usuari). Aquest objecte serà l’encarregat de mostrar tots els nostres diferents botons i gràfics. Crearem aquest objecte de tipus Skin a Unity. L’última variable és una referència al nostre objecte de bolla.

    public static int PlayerScore1 = 0;
    public static int PlayerScore2 = 0;

    public GUISkin layout;

    GameObject theBall;

A continuació ve la funció Start() que com ja hem dit abans, farem servir quan comença el joc per primera vegada.

    void Start () {
        theBall = GameObject.FindGameObjectWithTag ("Ball");
    }

A continuació es mostra la funció Score (). Cridarà un altre script que farem tot d’una, que detecta quan la pilota colpeja a les parets laterals.

    public static void Score(string wallID) {
        if (wallID == "RightWall") {
            PlayerScore1++;
        } else {
            PlayerScore2++;
        }
    }

La funció OnGUI () s’ocupa de mostrar la puntuació i la funcionalitat del botó de restabliment. També comprova si cada vegada que succeeix alguna cosa, si algú ja ha guanyat i en aquest cas invoca la funció  ResetBall ().

    void OnGUI() {
        GUI.skin = layout;
        GUI.Label (new Rect (Screen.width / 2 - 150 - 12, 20, 100, 100), "" + PlayerScore1);
        GUI.Label (new Rect (Screen.width / 2 + 150 + 12, 20, 100, 100), "" + PlayerScore2);

        if (GUI.Button (new Rect (Screen.width / 2 - 60, 35, 120, 53), "RESTART")) {
            PlayerScore1 = 0;
            PlayerScore2 = 0;
            theBall.SendMessage ("RestartGame", 0.5f, SendMessageOptions.RequireReceiver);
        }

        if (PlayerScore1 == 10) {
            GUI.Label (new Rect (Screen.width / 2 - 150, 200, 2000, 1000), "PLAYER ONE WINS");
            theBall.SendMessage ("ResetBall", null, SendMessageOptions.RequireReceiver);
        } else if (PlayerScore2 == 10) {
            GUI.Label (new Rect (Screen.width / 2 - 150, 200, 2000, 1000), "PLAYER TWO WINS");
            theBall.SendMessage ("ResetBall", null, SendMessageOptions.RequireReceiver);
        }
    }

“SendMessage” és una cosa que hem estat utilitzant molt en aquest fragment de codi. Aquesta invocació el que farà serà activarà qualsevol funció que coincideixi amb el nom que li enviem en una classe que especifiquem. Així doncs, quan diem theBall.SendMessage (“ResetBall”), diem al programa que tingui accés a la classe “BallControl” i desencadeni el mètode ResetBall (). Aquí teniu l’script complet

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameManager : MonoBehaviour {

    public static int PlayerScore1 = 0;
    public static int PlayerScore2 = 0;

    public GUISkin layout;

    GameObject theBall;

    // Use this for initialization
    void Start () {
        theBall = GameObject.FindGameObjectWithTag ("Ball");
    }

    public static void Score(string wallID) {
        if (wallID == "RightWall") {
            PlayerScore1++;
        } else {
            PlayerScore2++;
        }
    }

    void OnGUI() {
        GUI.skin = layout;
        GUI.Label (new Rect (Screen.width / 2 - 150 - 12, 20, 100, 100), "" + PlayerScore1);
        GUI.Label (new Rect (Screen.width / 2 + 150 + 12, 20, 100, 100), "" + PlayerScore2);

        if (GUI.Button (new Rect (Screen.width / 2 - 60, 35, 120, 53), "RESTART")) {
            PlayerScore1 = 0;
            PlayerScore2 = 0;
            theBall.SendMessage ("RestartGame", 0.5f, SendMessageOptions.RequireReceiver);
        }

        if (PlayerScore1 == 10) {
            GUI.Label (new Rect (Screen.width / 2 - 150, 200, 2000, 1000), "PLAYER ONE WINS");
            theBall.SendMessage ("ResetBall", null, SendMessageOptions.RequireReceiver);
        } else if (PlayerScore2 == 10) {
            GUI.Label (new Rect (Screen.width / 2 - 150, 200, 2000, 1000), "PLAYER TWO WINS");
            theBall.SendMessage ("ResetBall", null, SendMessageOptions.RequireReceiver);
        }
    }

}

Aquí teniu el code sencer per descarregar GameManager.cs

Si miram al HUD, veurem una variable que no hem utilitzat es tracta del skin. Però ara hem de fer-ho a Unity. Si busqueu la carpeta d’actius, haureu de veure un fitxer que hem descarregat que és un tipus de lletra especial anomenat “6809 Chargen”.

Al plafó del projecte, feu clic amb el botó dret i creeu una GUI Skin anomenada ScoreSkin. Feu clic a aquest skin i hauríeu de veure un camp variable anomenat “Font” a la part superior del quadre de l’Inspector. Feu clic a “+” i arrossegueu el nostre tipus de lletra a aquesta ranura variable.

Si es desplaça cap avall i es mira els menús desplegables de “Etiqueta” i “Botó”, també es pot canviar la mida del text, etc. Juga al voltant amb la mida fins que quedi bé. Vaig definir les mides del tipus de lletra per a la meva etiqueta i botó a 42 i 20, respectivament. 

També haurem de seleccionar HUD a la jerarquia per modificar el layout dins del panell Inspector. Hem de seleccionar ScoreSkin.

Al final, el HUD’s Game Manager (Script) es veu així:

Ara ens assegurem que el joc sap quan marquem un punt. Per fer-ho, hem d’afegir un script als LeftWall i RightWall al desplegable HUD. És el mateix script per la qual cosa hauria de ser bastant fàcil de fer. Primer, anirem a Add Component> New script al LeftWall i posarem el nom d’aquest nou script SideWalls.

Descripció del codi

Després d’importar els nostres paquets, només haurem d’escriure una funció. Aquesta funció detecta quan alguna cosa xoca amb les nostres parets esquerra o dreta. Si es tracta de la pilota, cridem al mètode de puntuació a GameManager i restablim la pilota al centre.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SideWalls : MonoBehaviour
{

  void OnTriggerEnter2D(Collider2D hitInfo)
  {
      if (hitInfo.name == "Ball")
      {
          string wallName = transform.name;
          GameManager.Score(wallName);
          hitInfo.gameObject.SendMessage("RestartGame", 1, SendMessageOptions.RequireReceiver);
      }
  }
}

Aquí teniu el code sencer per descarregar SideWalls.cs

Ja heu afegit el script a LeftWall, i ara, ja que està escrit, aneu a Add Component> New script al RightWall. Seleccioneu l’script que acabem d’escriure. 

Ara, per tal que Unity invoqui al nostre mètode OnTriggerEnter2D, ens hem d’assegurar que tant a LeftWall com a RightWall hi hagi marcada la casella Is Trigger als seus Colliders Box en el panell Inspector. Això vol dir que Unity no tractarà aquestes parets com a parets físiques, sinó que “desencadenen” alguna cosa en el joc (en aquest cas, donen un punt al jugador).

Ara és el moment de prova si tot funciona.

Últim pas: Construir el joc

Ara, només hem de fer que el nostre joc es pugui jugar fora d’Unity. Per fer-ho, aneu a Fitxer al menú de la part superior. Vés a Build Settings i, a continuació, tria Mac, PC, Linux Standalone. Això farà que un fitxer executable (reproduïble) aparegui al nostre escriptori. És possible que hagueu de seleccionar Add Open Scenes per assegurar-vos que el main s’inclogui al Build.

Ara, feu clic a Player Settings. Aquí és on heu de posar el vostre nom al projecte, escollir una icona (he escollit el sprite de bolla) i seleccionar les desmarcar Default Is Full Screen. Demana l’amplada i l’altura de la pantalla per defecte. Podeu posar qualsevol cosa.

Introducció a Unity per Xavier Sastre

   CC BY-NC-SA 4.0          

Document basat, traduït i adaptat d’aquest

Exercici adreçament IP

Realitzar un pla d’adreçament IP pel següent esquema:

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

Baixar fitxers original i pdf