Creando una app para Ubuntu Touch [QML] – [Parte 2]

Introducción:

Bien aquí tenemos el post que sigue a la primera parte, en este vamos a centrarnos en manejar los datos (preguntas), y empezaremos con la parte de la lógica del juego, en el próximo acabaremos la lógica y implementaremos el tiempo y las 3 opciones.

Podéis encontrar el código en mi repositorio de Launchpad (clic aquí), donde lo actualizaré a medida que avance.

Base de datos:

Para la base de datos usaremos U1db, que se trata de una base de datos que guarda los datos en formato JSON.

Primero de todo  veamos que datos debemos guardar, tenemos 1 pregunta (aparte del texto de la pregunta estaría bien tener un identificador), con 4 posibles respuestas, de las cuales solo 1 lo puede ser, por lo tanto el documento en JSON de una sola pregunta debería ser:

{
"id": 1,
"pregunta": " habra dev.desdelinux.net ",
"respuestas" : { r1: "si" , r2: "no" , r3: "no se sabe" ,  r4: "esto es una respuesta falsa" },
"correcta": 3
}

Como vemos hemos estructurado en formato JSON donde tenemos un identificador, un string con la pregunta y r1,r2 que representan la respuesta 1 y respuesta 2, finalmente tenemos cuál de las respuestas es la correcta.

Veamos un poco como funciona U1db, lo primero que tenemos que hacer para usar U1db es importar el módulo:

import U1db 1.0 as U1db

Declaramos la base de datos:

U1db.Database {
id: aDatabase
path: "aU1DbDatabase"
}

Las base de datos será guardada como aU1DbDatabase.u1db, ahora creamos un documento:

U1db.Document {
id: aDocument
database: aDatabase
docId: 'helloworld'
create: true
defaults: { "hello": "Hello World!" }
}

Donde podemos ver el formato { «hello» : «algo» }, para ejecutar querys, ya sea para agregar datos, obtener datos, borrarlos etc. Tenemos el elemento U1db.Query.

Podemos encontrar un tutorial en la web de desarrollo de Ubuntu.

Vamos a nuestra aplicación y a crear nuestra base de datos, como hemos visto definimos la base de datos:

U1db.Database { id: preguntasdb; path: "preguntasdb.u1db" }

Bien, ahora pongamos unos elementos por defecto en el documento de la base de datos preguntasdb:

    U1db.Document {
        id: aDocument
        database: preguntasdb
        docId: 'preguntas'
        create: true
        defaults: { "preguntas":
                    [
                        {"pregunta":"Habra dev.desdelinux.net ?", 
                        "r1":"si", "r2":"no", "r3":"nose", 
                        "r4":"respuesta falsa", "correcta": "3" },
                        {"pregunta":"Quien es hagrid (harry potter) ?", 
                        "r1":"El vicedirector de la escuela", 
                        "r2":"El guardabosques", 
                        "r3":"El profesor de transformaciones", 
                        "r4":"Un prefecto", 
                        "correcta": "2"},
                        {"pregunta":"¿Cúal es la capital de Islandia?", 
                       "r1":"Amsterdam",
                       "r2":"Reykjavik", 
                       "r3":"Tiflis", 
                       "r4":"Almaty",
                       "correcta": "2"}
                    ] }
    }

Soy consciente de que el código no se muestra como debería, pero si nos fijamos veremos que tenemos un elemento preguntas, el cual con los » [ ] » especificamos que pueden haber varios (no son estáticos) elementos; en este caso ya tendremos a 4 por defecto, 4 preguntas con sus respectivas respuestas.

Para conseguir los elementos del documento JSON, podemos especificar el identificador del documento que hemos creado (que es aDocument). Imaginemos que queremos obtener el texto de la primera pregunta:

aDocument.contents.preguntas[0].pregunta

Esta línea de código nos retorna el contenido de pregunta del documento aDocument, del elemento 0 (el primero del índice), que es: «Habra dev.desdelinux.net?». Si ponemos en el índice el número 1, entonces seáa la segunda pregunta.

Programando la lógica del juego

Bien, ahora que ya sabemos manejar un poco la base de datos donde tenemos guardado las preguntas, vamos a programar la lógica del juego. Primero de todo crearemos un archivo JavaScript (.js):  Add new -> Qt -> Js File. Lo llamaré logica.js.

En el archivo vamos a crear varias funciones, para importar el fichero js en nuestro documento qml:

import "logica.js" as Logica

Le asociamos el nombre Logica, por lo tanto cuando queremos llamar una función lo haremos como Logica.funcion(), como si de un objeto el cual tiene sus métodos se tratara.

De momento, para que el post no se haga muy largo, dejaremos el tiempo de la pregunta y las opciones para más adelante, nos concentraremos en las preguntas y los puntos, veamos una función que haremos servir para pasar de pregunta:

function nextPregunta(num) {
    //tiempo = 0
    pregunta.text = aDocument.contents.preguntas[num].pregunta;
    resp1.text = aDocument.contents.preguntas[num].r1;
    resp2.text = aDocument.contents.preguntas[num].r2;
    resp3.text = aDocument.contents.preguntas[num].r3;
    resp4.text = aDocument.contents.preguntas[num].r4;
}

Como vemos, le pasamos como argumento el número de pregunta donde estamos y a partir de aquí pone las respuestas a los botones y al label la pregunta. Veamos ahora para validar si la respuesta seleccionada es correcta:

function acierto(num, opcion) {
    var acierto = false;
    var num_correcto = aDocument.contents.preguntas[num].correcta;
    if (opcion == num_correcto) acierto = true;
    return acierto;
}

El código habla por sí solo, en caso que la opción elegida sea igual que la que nos proporciona la base de datos, entonces será cierta, en caso contrario no. Ahora que ya tenemos estas funciones definidas, las aplicaremos en nuestro código qml.

Primero de todo añadiremos una variable que será la que controle en que pregunta estamos, la llamaremos num; también tendremos tres variables más: aciertos,fallos y puntos.

    property int num: 0
    property int nfallos: 0
    property int naciertos: 0
    property int npuntos: 0

Inicialmente están todos a 0.

Ahora agregamos un onClick a todos los botones de respuestas. onClick, como dice su nombre, es un evento que pasará cuando se dé click a dicho boton:

            Button {
                id: resp1
                text: "Respuesta 1"
                anchors.horizontalCenter: parent.horizontalCenter
                width: parent.width - 20
                onClicked: {
                    if(Logica.acierto(num,1)){
                        num = num + 1;
                        Logica.nextPregunta(num)
                        npuntos = npuntos + 50
                        naciertos = naciertos + 1
                    }
                    else {
                        nfallos = nfallos + 1
                    }
                }
            }

Vemos que al darle click al botón, comprueba si es el correcto o no, en caso de que sí lo sea suma los puntos y pasa de pregunta, en caso contrario resta una vida.

Por último haremos que la primera pregunta se cargue cuando se cargue el componente Page:

    Page {
        id: pageJuego
        Component.onCompleted: {
            Logica.nextPregunta(0)
        }

Veamos como ha quedado:

test


Deja tu comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

*

*

  1. Responsable de los datos: Miguel Ángel Gatón
  2. Finalidad de los datos: Controlar el SPAM, gestión de comentarios.
  3. Legitimación: Tu consentimiento
  4. Comunicación de los datos: No se comunicarán los datos a terceros salvo por obligación legal.
  5. Almacenamiento de los datos: Base de datos alojada en Occentus Networks (UE)
  6. Derechos: En cualquier momento puedes limitar, recuperar y borrar tu información.

  1.   Gabielus dijo

    Voy siguiendo los pasos y funciona todo. Solo para colaborar digo que:
    * No cambia el valor de los aciertos y fallos. Hay que agregar eso en cada botón en su evento click.
    * Y que en la linea:
    if(Logica.acierto(num,1)){
    hay que cambiar el 1 por el numero del botón/respuesta.

    lolbimbo, me parece interesante tu aporte. Espero nuevos tutos!!!

    Gracias por compartir.

    1.    lolbimbo dijo

      Me gusta que hayas comentado estos puntos por que no lo deje claro en el post, es más, no me acorde de los puntos, los aciertos y fallos, si lo miras veras que cuando le damos al boton si que sumamos los puntos los aciertos… pero no se reflejan en el Label, eso es por que tenemos que ponerle en su propiedad text que muestre los puntos:

      Label {
      id: fallos
      text: «Fallos: » + nfallos
      color: «red»
      }

      Label {
      id: aciertos
      text: «Aciertos: » + naciertos
      }

      Label {
      id: puntos
      text: «Puntos: » + npuntos
      fontSize: «medium»
      }

      Igualmente lo aclarare en la 3 parte.