Activitats

Creació d'una aplicació per a la línia d'ordres amb Node.js

L’objectiu d’aquesta activitat és aprendre a crear una aplicació amb Node.js que es pugui utilitzar des de la línia d’ordres.

Cerqueu a internet la manera d’accedir als arguments introduïts a la línia d’ordres quan s’executa una aplicació amb Node.js, per exemple, si l’ordre és node activitat1.js “Hola món” l’argument és “Hola món”.

Seguidament, implementeu una aplicació que en ser executada desi –acumulativament– el primer argument obtingut de la línia d’ordres en un fitxer anomenat activitat1.txt.

Si se cerca a Google sobre els arguments de Node.js per a la línia d’ordres es troba fàcilment que la propietat process.argv (www.goo.gl/wsbXZN) és la que dona accés als arguments.

Es tracta d’un array en el qual el primer element és la ruta d’execució de node, el segon la ruta d’execució del programa i els següents (des de l’índex 2 en endavant) corresponen als arguments.

Per poder desar dades cal utilitzar el mòdul fs (file system) i el codi generat serà el següent (el nom del fitxer amb el codi és activitat1.js):

  1. let fs = require ('fs');
  2.  
  3. let primerArgument = process.argv[2];
  4.  
  5. fs.appendFile('activitat1.txt', primerArgument, function(error) {
  6. let missatge;
  7.  
  8. if (error) {
  9. throw error; // No continuarà l'execució
  10. }
  11.  
  12. console.log('Dades afegides al fitxer correctament: ' + primerArgument);
  13. });

Per comprovar-ne el funcionament s’ha de posar a la línia d’ordres: node activitat1.js “Hola món” i s’afegirà Hola món al fitxer activitat1.txt.

Cerca i utilització de mòduls de Node.js mitjançant npm

L’objectiu de l’activitat és cercar un mòdul que permeti convertir objectes de JavaScript en XML i utilitzar-lo per desenvolupar una aplicació.

Cerqueu a www.npmjs.com un mòdul que serveixi per convertir objectes de JavaScript en XML, instal·leu-lo i implementeu una aplicació que mostri per la terminal el següent objecte en format XML:

  1. let alumne = {
  2. nom: "Maria",
  3. cognom: "Campmany",
  4. assignatures: ["m01", "m03b", "m02"]
  5. }
  6.  

Un dels mòduls que permeten convertir objectes a format XML és data2xml. El podeu trobar a l’enllaç següent: www.npmjs.com/package/data2xml.

Per instal·lar-lo s’ha de posar a la línia d’ordres npm install data2xml (és possible que es mostrin missatges d’avís per no haver generat un fitxer package.json per a l’aplicació).

El codi de l’aplicació serà el següent:

  1. let data2xml = require('data2xml');
  2. let convert = data2xml();
  3.  
  4. let alumne = {
  5. nom: "Maria",
  6. cognom: "Campmany",
  7. assignatures: ["m01", "m03b", "m02"]
  8. }
  9.  
  10. console.log (convert('alumne', alumne));

I el resultat en executar l’aplicació és el que trobeu a continuació (s’ha afegit el sagnat):

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <alumne>
  3. <nom>Maria</nom>
  4. <cognom>Campmany</cognom>
  5. <assignatures>m01</assignatures>
  6. <assignatures>m03b</assignatures>
  7. <assignatures>m02</assignatures>
  8. </alumne>

Cerca i utilització d'API de mapes estàtics

L’objectiu d’aquesta activitat és aprendre a mostrar un mapa estàtic.

Creeu una pàgina usant Leaflet que mostri la localització de la seu de l’IOC (lat: 41.375106,lng: 2.168342) amb un marcador, i quan es faci clic sobre aquest marcador, es mostri certa informació d’aquesta seu, com el nom i una foto del logo de l’IOC.

Per generar el mapa usant Leaflet es faria servir el codi següent:

<html>
<head>
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"
   integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="
   crossorigin=""/>
   <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"
   integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA=="
   crossorigin=""></script>
  <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
</head>
<body>
  <!-- Element on es mostrarà el mapa -->
  <div id="mapid" style="height:600px"></div>

  <script>
    //Afegim el mapa centrat en les coordenades concretes i un zoom (13)
    let elMeuMapa = L.map('mapid').setView([41.375106, 2.168342], 13);

    //Afegim el tipus de tessel·les desitjat
    L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://cloudmade.com">CloudMade</a>',
        maxZoom: 18
    }).addTo(elMeuMapa);

    //Afegim el marcador a les coordenades demanades i amb el missatge que volem que surti quan es cliqui
    let marcador = L.marker([41.375106, 2.168342]).addTo(elMeuMapa);
    marcador.bindPopup('<h3>Seu de l\'<i>IOC</i></h3><img width="80px" src="https://pbs.twimg.com/profile_images/1046722856929947649/hytXqKH0_400x400.jpg">');
  </script>
</body>
</html>

Podeu veure aquest exemple en l’enllaç següent:codepen.io/ioc-daw-m06/pen/XWMzrZO?editors=1010.

Fixeu-vos que Leaflet necessita que carreguem inicialment dues llibreries.

Al fitxer html solament faria falta crear un element per contenir el mapa.

Finalment, al codi JavaScript, haurem de centrar el mapa en unes coordenades concretes, afegir el tipus de tessel·la que desitgem d’entre les disponibles a Leaflet, i finalment afegir el marcador i el contingut que s’ha de mostrar el fer clic.

Cerca i utilització d'API de geocodificació

L’objectiu d’aquesta activitat és aprendre a cercar i utilitzar API amb capacitats de geocodificació.

Cerqueu què és la geocodificació i trobeu una API basada en les dades d’OpenStreetMap que permeti realitzar geocodificació. Desenvolupeu una petita aplicació amb JavaScript que a partir d’un text introduït en un quadre de text mostri per la consola la informació obtinguda.

Nota: s’haurà de fer una petició AJAX i es pot utilitzar la biblioteca jQuery per simplificar el codi.

La geocodificació és el procés de convertir una adreça en unes coordenades geogràfiques. La geocodificació inversa consisteix a fer el contrari, convertir coordenades en una adreça.

Al següent lloc web es pot trobar tota informació sobre Nominatim API (https://nominatim.org/release-docs/latest/api/Search/), que és la que permet fer aquestes operacions, a més de retornar molta informació sobre el punt geogràfic.

Per utilitzar aquesta API cal utilitzar l’URL següent: https://nominatim.openstreetmap.org/search.php, afegint el paràmetre format amb el valor del format desitjat i el paràmetre q assignant l’adreça que cal cercar.

El codi del programa per buscar la informació a partir d’una adreça utilitzant jQuery seria el següent:

  1. <html>
  2. <body>
  3. Adreça: <input id="adreca" value="Martorell"/>
  4. <button id="cercar">cercar</button>
  5. <hr/>
  6. <label for="lat"></label>Latitud: <span id="lat"></span>
  7. <br/>
  8. <label for="lon"></label>Longitud: <span id="lon"></span>
  9. <hr/>
  10.  
  11. <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
  12. <script>
  13. let $adreca = $('#adreca');
  14. let $cercar = $('#cercar');
  15.  
  16. $cercar.on('click', function(e) {
  17.  
  18. $.ajax( {
  19. url: 'https://nominatim.openstreetmap.org/search.php?format=json&q=' + $adreca.val(),
  20. dataType: 'json',
  21. success: function(data) {
  22. $('#lat').text(data[0].lat);
  23. $('#lon').text(data[0].lon);
  24. }
  25. });
  26. });
  27. </script>
  28. </body>

Podeu veure aquest exemple en l’enllaç següent: codepen.io/ioc-daw-m06/pen/OWYLKm?editors=1010.

Cerca d'un llistat de museus d'un Open Data

L’objectiu de l’activitat és aprendre a cercar i obtenir informació d’una font de dades obertes.

Cerqueu a les dades obertes de l’Observatori de dades culturals de Barcelona (www.barcelonadadescultura.bcn.cat/dades-obertes) el llistat de museus corresponents al districte de l’Eixample. Aquesta informació ha d’incloure la latitud i la longitud.

Indiqueu els passos seguits i l’URL final que s’ha de demanar per obtenir aquestes dades.

  1. Entreu a la pàgina següent: www.barcelonadadescultura.bcn.cat/dades-obertes.
  2. Feu clic sobre l’enllaç al document XML que conté la informació del catàleg: www.dades.eicub.net/doc.
  3. Cerqueu museus al document i comproveu els diversos conjunts de dades. Només n’hi ha un que inclou la latitud i la longitud: museusexposicions-inventari, que es pot consultar a l’URL següent: www.dades.eicub.net/api/1/museusexposicions-inventari.
  4. Per filtrar el resultat per districte cal que afegiu el paràmetre Districte amb el valor que volem filtrar.
  5. Per conèixer el valor correcte pel districte de l’Eixample només cal que visiteu el llistat complet i feu una cerca per Eixample. El codi que trobareu és 02. Eixample.

Així doncs, l’URL per realitzar la consulta és el següent: www.dades.eicub.net/api/1/museusexposicions-inventari?Districte=02.%20Eixample (fixeu-vos que s’ha codificat l’URL i s’ha reemplaçat l’espai per %20).

Comparació de motors de joc HTML5

L’objectiu de l’activitat és conèixer els motors de joc de tercers que hi ha al mercat i les seves característiques.

Cerqueu un motor de joc per a HTML5 que admeti WebXR i un altre que admeti WebGL. Compareu quines diferències trobeu entre tots dos segons els criteris següents:

  • Gràfics
  • Documentació
  • Comunitat
  • Opcions multijugador
  • Altres

Nota: Podeu cercar els motors de joc més populars a l’enllaç següent: ssiddique.info/best-html5-game-engines.html.

Un dels pocs motor de jocs per generar continguts WebXR és PlayCanvas (www.playcanvas.com). Entre els motors que utilitzen WebGL el més popular és Construct (www.construct.net).

  • Gràfics: tots dos funcionen amb WebGL i permeten crear tant contingut en 2D com 3D.
  • Documentació: al lloc web de PlayCanvas és pot trobar molta informació, però hi ha pocs recursos externs; en canvi, per a Construct es poden trobar centenars de tutorials al seu lloc web.
  • Comunitat: la comunitat de PlayCanvas és petita i no es troba pràcticament cap contingut fora del seu lloc web; en canvi, per a Construct es poden trobar centenars de vídeos tutorials a YouTube.
  • Opcions multijugador: la documentació sobre aquest aspecte a PlayCanvas és molt poca i només indica que s’ha de fer servir un servidor implementat amb Node.js. Construct ofereix les opcions multijugador només als usuaris amb llicència de pagament però inclou tutorials i exemples de jocs, a més d’una biblioteca de xarxa més avançada.
  • Altres: Construct permet desenvolupar jocs amb uns coneixements de programació més reduïts. PlayCanvas ofereix un editor en línia, de manera que no cal descarregar cap programari; es treballa directament sobre la web, els jocs generats tenen un pes molt més reduït i afirmen estar molt optimitzats, de manera que s’aconsegueix una més fluïdesa.

En conclusió, es pot determinar que amb Construct és molt més fàcil desenvolupar jocs i trobar tot tipus d’informació. Per altra banda, PlayCanvas requereix uns coneixements més avançats però permet utilitzar una tecnologia que no està a l’abast de molts dels altres (WebXR) i produir jocs més optimitzats.

Modificació del joc "IOC Invaders" utilitzant les dades

L’objectiu de l’activitat és entendre com funcionen les estructures de dades i aprendre a modificar-les per afegir un nou nivell al joc IOC Invaders.

Creeu un nou nivell del joc IOC Invaders amb les característiques següents:

  • Nom del nivell: Nivell 4.
  • Descripció: Aquest és el quart nivell del joc.
  • Música: star-commander.
  • Capes: el doble de velocitat que el nivell anterior i les imatges següents: bg_layer_1_green,bg_layer_2, bg_layer_3_green, bg_layer_4.
  • 2 onades de 5 enemics (de qualsevol tipus): la primera ha d’aparèixer als 200 punts de distància i la següent als 400 punts.
  • El nivell acaba en arribar a 600 punts de distància.

Recordeu que podeu trobar el codi complet del joc IOC Invaders a l’enllaç següent: www.github.com/XavierGaro/ioc-invaders.

Per afegir un nivell nou s’ha d’afegir l’estructura de dades al final del fitxer level-data.json. Fixeu-vos que ha de quedar dins de l’array levels.

El codi per generar el nivell indicat (que s’ha d’afegir al fitxer) és el següent:

  1. {
  2. "name": "Nivell 4",
  3. "description": "Aquest és el quart nivell del joc.",
  4. "music": "star-commander",
  5. "background": {
  6. "layers": [
  7. {
  8. "id": "bg_layer_1_green",
  9. "speed": {
  10. "x": -120,
  11. "y": 0
  12. }
  13. },
  14. {
  15. "id": "bg_layer_2",
  16. "speed": {
  17. "x": -240,
  18. "y": 0
  19. }
  20. },
  21. {
  22. "id": "bg_layer_3_green",
  23. "speed": {
  24. "x": -480,
  25. "y": 0
  26. }
  27. },
  28. {
  29. "id": "bg_layer_4",
  30. "speed": {
  31. "x": -960,
  32. "y": 0
  33. }
  34. }
  35. ]
  36. },
  37. "waves": [
  38. {
  39. "distance": 200,
  40. "spawns": [
  41. {
  42. "type": "alien_a",
  43. "formation": {
  44. "type": "row",
  45. "amount": 5,
  46. "spacer": 50
  47. },
  48. "position": {
  49. "x": 1024,
  50. "y": 100
  51. },
  52. "speed": {
  53. "x": -120,
  54. "y": 0
  55. }
  56. }
  57. ]
  58. },
  59. {
  60. "distance": 400,
  61. "spawns": [
  62. {
  63. "type": "alien_b",
  64. "formation": {
  65. "type": "column",
  66. "amount": 5,
  67. "column_height": 1000,
  68. "spacer": 50
  69. },
  70. "position": {
  71. "x": 800,
  72. "y": -200
  73. },
  74. "speed": {
  75. "x": 0,
  76. "y": 120
  77. }
  78. }
  79. ]
  80. }
  81. ],
  82. "end": 600
  83. }

Creació d'un nou tipus de formació

L’objectiu de l’activitat és aprendre a ampliar un component ja existent afegint-hi una nova opció.

Examineu el funcionament de la funció spawnFormation() de la classe GameEngine i afegiu-hi un nou tipus anomenat random que faci servir la propietat spacer per determinar els límits en què es pot instanciar la nau.

És a dir, si el valor d‘spacer és 100 i la posició central és (100,100) la posició de cada nau es col·locarà aleatòriament entre 0 i 200 tant per l’eix x com per l’eix y.

Recordeu que les formacions s’estableixen al fitxer de dades level-data.json i podeu comprovar el funcionament de la nova formació substituint-la als enemics del primer nivell d’aquest fitxer.

Al fitxer ioc-invader, dintre de l’objecte gameEngineContructor es troba la funció spawnFormation(). Dintre del switch s’ha d’afegir el codi següent (abans de default:):

  1. case "random":
  2. originPosition = {x: wave.position.x, y: wave.position.y};
  3. spacer = wave.formation.spacer;
  4.  
  5. for (i = 0; i < wave.formation.amount; i++) {
  6. this.enemyPool.instantiate(wave.type, {
  7. x: originPosition.x + Math.random() * (spacer * 2) - spacer,
  8. y: originPosition.y + Math.random() * (spacer * 2) - spacer
  9. }, wave.speed);
  10. }
  11. break;

Per comprovar el funcionament de la nova formació podeu modificar el primer enemic que s’instancia en el lloc (en el fitxer level-data.json) per un codi similar al següent:

  1. {
  2. "type": "alien_a",
  3. "formation": {
  4. "type": "random",
  5. "amount": 10,
  6. "spacer": 100
  7. }

Afegir una nova acció al jugador

L’objectiu de l’activitat és aprendre com ampliar el gestor d’entrada d’un joc i implementar una nova funcionalitat.

Afegiu una nova acció per al jugador que permeti destruir tots els enemics del joc. Com que es tracta d’una funcionalitat de prova no cal afegir cap limitació i podrà ser utilitzada sense limitacions. S’ha d’assignar aquesta nova acció a la tecla enter i el nom de la funció ha de ser specialAttack(). Tampoc no caldrà augmentar la puntuació del jugador.

Nota. Aquesta funció pot afegir-se als objectes de tipus Player, això permetria crear diferents tipus de nau per als jugadors amb diferents atacs especials mitjançant l’herència.

Per una banda s’ha de modificiar el mòdul InputManager per afegir-hi la nova tecla (Enter correspon al codi 13):

  1. const KEY_CODES = {
  2. 32: 'Space',
  3. 37: 'ArrowLeft',
  4. 38: 'ArrowUp',
  5. 39: 'ArrowRight',
  6. 40: 'ArrowDown',
  7. 13: 'Enter'
  8. };

El pas següent és implementar la funció specialAttack() dins de la classe Player al mòdul gameObjects. Però com que no hi ha cap manera d’obtenir una llista d’enemics actius, primer caldrà augmentar funcionalitat de la classe GameEngine afegint el mètode getActiveEnemies():

  1. getActiveEnemies = function() {
  2. let enemies = this.enemyPool.pool.slice(0, this.enemyPool.actives);
  3. return enemies;
  4. };

A continuació es pot afegir la funció specialAttack():

  1. specialAttack(enemies) {
  2. for (let i=0; i<enemies.length; i++) {
  3. enemies[i].isDestroyed = true;
  4. }
  5. }

Finalment cal afegir la importació del mòdul inputController i la detecció dins del mètode update() de la classe GameEngine per comprovar si s’ha pres Enter.

  1. import {KEY_STATUS} from "./inputController.js";
  1. update(gameTime) {
  2. window.requestAnimationFrame(this.update.bind(this));
  3.  
  4. // Comprovem si ha passat suficient temps entre actualitzacions per limitar el nombre de
  5. // quadres per segon
  6. if (!this.isUpdateRequired(gameTime)) {
  7. return;
  8. }
  9.  
  10. // Diferencia de temps entre quadres en ms
  11. let deltaTime = (gameTime - this.previousGameTime)/1000;
  12. this.previousGameTime = gameTime;
  13.  
  14. // Detectem si s'ha pres la tecla enter i activem l'acció especial
  15. if (KEY_STATUS.Enter) {
  16. this.player.specialAttack(this.getActiveEnemies());
  17. }
  18.  
  19. this.updateWaves();
  20. // resta del codi original ...
  21. }

Podeu trobar el codi del joc IOC Invaders modificat amb la solució de les activitats a l’enllaç següent (branca SolucioActivitats): www.goo.gl/9p6Glt. També podeu descarregar-lo directament d’aquest material:

Cal tenir en compte que aquesta no és la millor solució, ja que la gestió de l’entrada de tecles s’hauria de gestionar a la classe Player, però en aquesta implementació no comptem amb cap mecanisme per accedir a la classe GameEngine directament des de Player, així que per simplificar hem optat per implementar-lo dins del mètode update() de la classe GameEngine.

Anar a la pàgina anterior:
Desenvolupament de casos pràctics
Anar a la pàgina següent:
Exercicis d'autoavaluació