Seguimi su Youtubue
Iscriviti
Se desideri, puoi effettuare un'iscrizione gratuita al forum per entrare nella nostra community.
Accedi

Recuperare la parola d'ordine

Ricerca Avanzata
Pubblicità Google AdSense
Answers
Se necessiti di aiuto, clicca il pulsante "Cerco Aiuto" (disponibile anche per i non iscritti).
Ultimi argomenti
» Logger sito web in PHP in file txt
Da Poderak Sab Gen 14, 2017 11:16 am

» Dove acquistare relè arduino
Da Poderak Ven Gen 13, 2017 2:46 pm

» Recensione caricabatteria iVoler con 2 porte USB 24W 4.8A
Da Poderak Dom Gen 08, 2017 9:57 pm

» Recensione cuffie da gaming: Thrustmaster 300CPX (Doom Edition)
Da Poderak Sab Dic 24, 2016 10:51 pm

» Problemi connessione arduino compatibile
Da Poderak Mer Dic 21, 2016 1:53 pm

» Recensione Speaker Bluetooth - Anker SoundCore Mini
Da Poderak Sab Dic 17, 2016 4:44 pm

» Arduino + telecamera
Da Poderak Mar Dic 13, 2016 6:36 pm

» PRESENTATI AL FORUM
Da Poderak Mar Dic 13, 2016 4:07 pm

» Recensione Filo - Il portachiavi tech
Da Poderak Sab Dic 10, 2016 5:24 pm

I postatori più attivi del mese
Poderak
 
Ilfalco78
 

JSpaceInvaders: Gioco in ASCII art in puro JavaScript

Vedere l'argomento precedente Vedere l'argomento seguente Andare in basso

JSpaceInvaders: Gioco in ASCII art in puro JavaScript

Messaggio Da afilini il Mer Lug 08, 2015 10:36 am

Codice:
  
   ___ _____                     _____                    _              
  |_  /  ___|                   |_   _|                  | |              
    | \ `--. _ __   __ _  ___ ___ | | _ ____   ____ _  __| | ___ _ __ ___
    | |`--. \ '_ \ / _` |/ __/ _ \| || '_ \ \ / / _` |/ _` |/ _ \ '__/ __|
/\__/ /\__/ / |_) | (_| | (_|  __/| || | | \ V / (_| | (_| |  __/ |  \__ \
\____/\____/| .__/ \__,_|\___\___\___/_| |_|\_/ \__,_|\__,_|\___|_|  |___/
            | |                                                          
            |_|                                                          

Ciao a tutti, vi mostro un gioco semplice semplice fatto in puro JavaScript, che magari vi potrà tornare utile come base per farne uno vostro. Il gioco è un'implementazione del famoso Space Invaders ed è fatto completamente in ASCII Art.
Riporto qui il codice ma vi raccomando sempre di scaricare l'ultima release stabile dalla repository Git hostata su GitHub (link alla fine della pagina).
Sulla stessa base ho creato anche uno snake, che verrà pubblicato sempre su questo forum più avanti.

Ci si muove con le frecce Destra e Sinistra oppure le lettere A e D. Si spara con la spacebar.
Link alla versione funzionante del gioco ospitata sul mio sito: afilini.com - JSpaceInvaders

License:
Codice:
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
(Per non allungare troppo il post non ho inserito la versione integrale della licenza, la potete trovare qui: GNU GPL V2)

Codice HTML:
Codice:
<html>
   <head>
      <script src="spaceInvaders.js"></script>

      <style type="text/css">
         pre {
            display: block;
            font-size: 9px;
         }
      </style>

   </head>
   <body onload="docReady()">
      <h2>JSpaceInvaders</h2>
      <pre id="console">
      </pre>
   </body>
</html>

Codice JavaScript:
Codice:
var display = [];

   var INF = 999999;

   var alive = true;

   var objects =  {navicelle: {},
               cannone: {},
               proiettili: {},
               boxNavicelle: {},
               casette: {}
               };

   var sprites = {
      navicella: {data: [['_ ', '_ ', '# ', '# ', '# ', '_ ', '_ '], ['\\ ', '_ ', '_ ', '_ ', '_ ', '_ ', '/ ']],
               width: 7,
               height: 2},
      cannone:    {data: [['  ', '  ', '@ ', '  ', '  '], ['@ ', '@ ', '@ ', '@ ', '@ ']],
               width: 5,
               height: 2
               },
      proiettile: {data: [['* '],['* ']],
               width: 1,
               height: 2
               },
      varProiettile: {data: [['! '],['o ']],
               width: 1,
               height: 2
               },
      casetta: {data: [['  ', '~ ', '~ ', '  '], ['% ', '% ', '% ', '% '], ['% ', '  ', '  ', '% ']],
               width: 4,
               height: 3
               }
   };

   var config = {
      width: 80,
      height: 50,
      nNavicelle: 10,
      nRowNavicelle: 2,
      distCannoneBasso: 4,
      vSpaceNavicella: 5,
      velocitaProiettile: 1,
      fireDelay: 3000,
      maxVmove: 20,
      minFireDelay: 800
   };

   var timeoutIds = {
      fireNavicella: 0,
      gestisciNavicelle: 0,
      rendering: 0
   }

   var ID = 0;
   var gestNavicelle = {
                  timer: 500,
                  direction: -1,
                  totalVmove: 0
                  };

   function fireNavicella() {
      var counter = 0;
      if (config.fireDelay > config.minFireDelay)
         config.fireDelay -= 100;
      for (var ID in objects.navicelle) {
         var item = objects.navicelle[ID];
         genProiettile(item.x + (sprites.navicella.width - 1) / 2, item.y + 3 ,1, "varProiettile");
         counter++;
      }
      if (counter == 0) {
         endGame(1);
      }
      config.fireDelay -= 5;
      timeoutIds.fireNavicella = setTimeout(fireNavicella, config.fireDelay);
   }

   function resizeBox () {
      objects.boxNavicelle.UpLeft      = {x: INF, y: INF};
      objects.boxNavicelle.DownLeft   = {x: 0, y: 0};
      objects.boxNavicelle.UpRight   = {x: 0, y: 0};
      objects.boxNavicelle.DownRight   = {x: 0, y: 0};

      for (var ID in objects.navicelle) {
         var item = objects.navicelle[ID];

         if (item.x - 1 < objects.boxNavicelle.UpLeft.x) {
            objects.boxNavicelle.UpLeft.x = item.x - 1;
            objects.boxNavicelle.DownLeft.x = item.x - 1;
         }

         if (item.x + sprites.navicella.width + 1 > objects.boxNavicelle.UpRight.x) {
            objects.boxNavicelle.UpRight.x = item.x + sprites.navicella.width + 1;
            objects.boxNavicelle.DownRight.x = item.x + sprites.navicella.width + 1;
         }

         if (item.y - 1< objects.boxNavicelle.UpLeft.y) {
            objects.boxNavicelle.UpLeft.y = item.y - 1;
            objects.boxNavicelle.UpRight.y = item.y - 1;
         }

         if (item.y + sprites.navicella.height + 1 > objects.boxNavicelle.UpRight.y) {
            objects.boxNavicelle.DownLeft.y = item.y + sprites.navicella.height + 1;
            objects.boxNavicelle.DownRight.y = item.y + sprites.navicella.height + 1;
         }
      }
   }

   function relativeBoxMove(x, y) {
      for (var ID in objects.navicelle) {
         var item = objects.navicelle[ID];
         objects.navicelle[ID].x += x;
         objects.navicelle[ID].y += y;
      }
   }

   function gestisciNavicelle () {
      if (gestNavicelle.timer > 100)
         gestNavicelle.timer -= 5;

      resizeBox();

      var relativeMove = {x: 0, y: 0};

      if (gestNavicelle.direction < 0) {
         if (objects.boxNavicelle.UpLeft.x > 2)
            relativeMove.x = -1;
         else {
            gestNavicelle.direction *= -1;
            
            if (gestNavicelle.totalVmove < config.maxVmove) {
               gestNavicelle.totalVmove += 2;
               relativeMove.y = 2;
            }
         }
      } else {
         if (objects.boxNavicelle.UpRight.x < config.width - 2)
            relativeMove.x = +1;
         else {
            gestNavicelle.direction *= -1;
            
            if (gestNavicelle.totalVmove < config.maxVmove) {
               gestNavicelle.totalVmove += 2;
               relativeMove.y = 2;
            }
         }
      }

      relativeBoxMove(relativeMove.x, relativeMove.y);

      timeoutIds.gestisciNavicelle = setTimeout(gestisciNavicelle, gestNavicelle.timer);
   }

   function genNavicella (x, y) {
      objects.navicelle[ID++] = {x: x, y: y};
   }

   function genCannone (x, y) {
      objects.cannone = {ObjID: ID, x: x, y: y};
      ID++;
   }

   function genProiettile (x, y, direzione, tipo) {
      objects.proiettili[ID++] = {x: x, y: y, direzione: direzione, tipo: tipo};
   }

   function genCasetta (x, y) {
      objects.casette[ID++] = {ObjID: ID, x: x, y: y, data: sprites.casetta.data};
   }

   function initNavicelle () {
      var navPerRow = config.nNavicelle / config.nRowNavicelle;
      var space = Math.floor((config.width - sprites.navicella.width * navPerRow) / (navPerRow + 1));
      var height = config.vSpaceNavicella;
      for (var i = 0; i < config.nRowNavicelle; i++) {
         for (var j = 0; j < navPerRow; j++) {
            genNavicella(space + (sprites.navicella.width + space) * j, height + (2 + height) * i);
         }
      }

      resizeBox();
   }

   function initCasette () {
      var houseNum = config.nNavicelle / config.nRowNavicelle;
      var space = Math.floor((config.width - sprites.casetta.width * houseNum) / (houseNum + 1));

      for (var i = 0; i < houseNum; i++)
         genCasetta(space + (sprites.casetta.width + space) * i, config.height - 5 - sprites.casetta.height);
   }

   function initCannone () {
      var space = Math.floor((config.width - sprites.cannone.width) / 2);
      var height = config.height - config.distCannoneBasso;
      genCannone(space, height);
   }

   function isPartOf (x, y, objectsArray, type) {

      for (var ID in objectsArray) {
         var item = objectsArray[ID];

         if ((x >= item.x && x <= item.x + type.width - 1) && (y >= item.y && y <= item.y + type.height - 1))
            return ID

      }
      return false;
   }

   function printDisplay () {

      for (var i = 0; i < config.height; i++) {
         display[i] = [];
         for (var j = 0; j < config.width; j++)
            display[i][j] = (i == 0 || i == config.height - 1 || j == 0 || j == config.width-1) ? '# ' : '  ';
      }

      /* PROIETTILI */

      for (var ID in objects.proiettili) {
         var item = objects.proiettili[ID];
         (function(){
            if (item.y < 2 || item.y > config.height - 3)
               delete objects.proiettili[ID];
            else {
               for (var i = 0; i < sprites.proiettile.width; i++)
                  for (var j = 0; j < sprites.proiettile.height; j++) {
                     if ((touchingID = isPartOf(item.x + i, item.y + j, objects.casette, sprites.casetta)) !== false) {

                        delete objects.proiettili[ID];
                        delete objects.casette[touchingID];
                        return;
                     }

                     display[item.y + j][item.x + i] = sprites[item.tipo].data[j][i];
                  }
                  
               objects.proiettili[ID].y += item.direzione * config.velocitaProiettile;
            }
         })();

      }

      /* CASETTE */

      for (var ID in objects.casette) {
         var item = objects.casette[ID];
         for (var i = 0; i < sprites.casetta.width; i++)
            for (var j = 0; j < sprites.casetta.height; j++) {
               display[item.y + j][item.x + i] = item.data[j][i];
            }
      }

      /* NAVICELLA */

      for (var ID in objects.navicelle) {
         var item = objects.navicelle[ID];
         for (var i = 0; i < sprites.navicella.width; i++)
            for (var j = 0; j < sprites.navicella.height; j++) {
               if (display[item.y + j][item.x + i] == '* ')
                  delete objects.navicelle[ID];
               
               display[item.y + j][item.x + i] = sprites.navicella.data[j][i];
            }
      }

      /* CANNONE */

      for (var i = 0; i < sprites.cannone.width; i++)
         for (var j = 0; j < sprites.cannone.height; j++) {
            if (display[objects.cannone.y + j][objects.cannone.x + i] == 'o ' || display[objects.cannone.y + j][objects.cannone.x + i] == '!')
               alive = false;

            display[objects.cannone.y + j][objects.cannone.x + i] = sprites.cannone.data[j][i];
         }

      /* GENERAZIONE STRINGA */

      var string = '';
      for (var i = 0; i < config.height; i++) {
         for (var j = 0; j < config.width; j++)
            string += display[i][j];
         string += '\n';
      }

      document.getElementById("console").innerHTML = string;

      if (alive)
         timeoutIds.rendering = setTimeout(printDisplay, 100);
      else
         endGame(false);
   }

   function start () {
      initCannone();
      initNavicelle();
      initCasette();
   }

   function leftArrowPressed() {
      if (objects.cannone.x > 1)
         objects.cannone.x -= 2;
   }

   function rightArrowPressed() {
      if (objects.cannone.x + sprites.cannone.width + 1 < config.width)
         objects.cannone.x += 2;
   }

   function fire() {
      genProiettile(objects.cannone.x + (sprites.cannone.width - 1) / 2, objects.cannone.y - 3, -1, "proiettile");
   }

   function endGame (result) {
      clearTimeout(timeoutIds.rendering);
      clearTimeout(timeoutIds.gestisciNavicelle);
      clearTimeout(timeoutIds.fireNavicella);
      var string = '';

      for (var i = 0; i < (config.height - 1)/2; i++)
         string += ' \n';
      for (var i = 0; i < (config.width - 9)/2; i++)
         string += ' ';

      if (result)
         string += "YOU WIN!!";
      else
         string += "GAME OVER";

      document.getElementById('console').style["font-size"] = "12px";
      document.getElementById('console').innerHTML = string;
   }

   function moveSelection(evt) {
      switch (evt.keyCode) {
         case 37:
         leftArrowPressed();
         break;

         case 65:
         leftArrowPressed();
         break;

         case 39:
         rightArrowPressed();
         break;
         
         case 68:
         rightArrowPressed();
         break;

         case 32:
         fire();
         break;

         default:
         console.log(evt.keyCode);
         break;
         }
      };

function docReady()
{
  window.addEventListener('keydown', moveSelection);
  start();
  printDisplay();
  gestisciNavicelle();
  fireNavicella();
}

Spiegare il codice non è un processo semplice, soprattutto a causa della sua lunghezza. Per questo motivo preferisco non aggiungere spiegazioni lunghe e noiose e preferisco siate voi lettori a farmi domande in caso abbiate curiosità. In caso ci fossero molte persone interessate a sviluppare giochi sulla stessa piattaforma potremo creare un thread in un'altra sezione e vi posterò qualche tutorial.

Per finire ecco il link alla repository Git: JSpaceInvaders by afilini - GitHub

Grazie mille dell'attenzione, spero questo post vi possa tornare utile nel creare il vostro personale gioco in ASCII Art.

afilini
Sono un nuovo membro
Sono un nuovo membro

Messaggi Messaggi : 1
Crediti Crediti : 3
Reputazione Reputazione : 0
Data d'iscrizione Data d'iscrizione : 07.07.15

Vedere il profilo dell'utente

Tornare in alto Andare in basso

Vedere l'argomento precedente Vedere l'argomento seguente Tornare in alto


 
Permesso di questo forum:
Non puoi rispondere agli argomenti in questo forum