Seguimi su Youtubue
Iscriviti
Se desideri, puoi effettuare un'iscrizione gratuita al forum per entrare nella nostra community.
Ricerca Avanzata
Pubblicità Google AdSense
Answers
Se necessiti di aiuto, clicca il pulsante "Cerco Aiuto" (disponibile anche per i non iscritti).
Ultimi argomenti
» libreria LiquidCrystal.h e LiquidCrystal_ I2C
Da papat Mar Ago 08, 2017 11:56 am

» libreria LiquidCrystal.h e LiquidCrystal_ I2C
Da papat Dom Ago 06, 2017 12:02 pm

» TOP 5 oggetti che perdi spesso
Da Poderak Gio Lug 13, 2017 4:26 pm

» arduino e ethernet shield tutorial 3
Da mariogori Ven Lug 07, 2017 8:52 pm

» Arduino comandato da cellulare
Da Poderak Ven Lug 07, 2017 6:17 pm

» Simulatore di navi: Traino nave in avaria - European Ship Simulator
Da Poderak Sab Lug 01, 2017 1:16 pm

» arduino e ethernet shield tutorial 3
Da Poderak Gio Giu 29, 2017 8:05 pm

» Farming Simulator 2018 logo
Da Poderak Ven Giu 23, 2017 3:29 pm

» Codice display a 7 segmenti - Arduino
Da fulvio Ven Giu 02, 2017 10:00 am

I postatori più attivi del mese
papat
 


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.
avatar
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

Vedi il profilo dell'utente

Tornare in alto Andare in basso

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


 
Permessi di questa sezione del forum:
Non puoi rispondere agli argomenti in questo forum