È da un po' di tempo che ci pensavo, avevo già accennato qualcosa di simile nella discussione Sviluppare app/giochi (anche) per PlayStation!
Vediamo ora un caso relativamente semplice (per questo l'ho chiamato "parte 1", arriverà anche la "parte 2" non so quando perché sarà enormemente più complessa 🙂): ho implementato un gioco del tris per browser (quindi codice HTML + CSS + JavaScript), creando gli elementi e gestendo poi il Drag&Drop.
Occorre però fare alcune premesse, non proprio scontate:
- includere un'immagine, rappresentazione grafica (es. in formato .svg) all'interno dello stesso file (anziché averla come riferimento esterno), la procedura è questa:
- codice CSS, proprietà dell'elemento che ci interessa:
background-image:url( ... );
- all'interno della funzione
url(...)
dobbiamo applicare una conversione ovvero nel caso di un'immagine raster es. una foto, quindi non vettoriale (caso meno ideale, conversione prima in Base64 tramite un apposito tool come base64-image.de); altrimenti nel caso di un file .svg, procedere in questo modo:
- aprire il file .svg con un editor di testo e scrivere il codice tutto su una riga
- sostituire il carattere # con %23 (es. per la codifica RGB #000 diventa %23000)
- sosituire i doppi apici con apice singolo
- tornando poi in
background-image:url( ... );
, si trasforma così: background-image:url("data:image/svg+xml;utf8, <svg> ... </svg>");
, dove ovviamente <svg> ... </svg>
è tutto il codice dell'immagine vettoriale
Fatta questa premessa, non sto a spiegare in dettaglio le 100 righe di codice che seguono, il concetto è che possiamo creare elementi con immagini come sfondo (quindi diciamo, texture degli elementi stessi) e tramite funzioni JavaScript di Drag&Drop li possiamo spostare all'interno della finestra, in altri elementi (di fatto possiamo creare un gioco interattivo 🙂).
Alcune precisazioni:
- non è chiaramente un'Intelligenza Artificiale, quindi siamo noi a giocare (quindi non ho implementato eventuali controlli mossa valida o non valida)
- ho creato il campo di gioco sopra e i pezzi sotto, che trasciniamo di volta in volta nel campo di gioco (nelle celle)
- non essendoci controlli, potrei fare anche mosse non valide, mettere più pezzi nella stessa cella (eddai, basta non farlo, se sbagliamo una mossa i pezzi si possono sempre spostare a piacimento)
- il rasto reset ritorna alla situazione iniziale
Ecco tutto il codice del programma:
<html>
<head>
<meta name="viewport" width="device-width,initial-scale=1">
<style>
body{
display:flex;
justify-content: center; /*centratura orizzontale*/
align-items: center; /*centratura verticale*/
flex-wrap:wrap; /*andare a capo*/
}
.container{
width:10%;
height:10%;
text-align:center;
cursor:grab;
}
#pezzo1,#pezzo2,#pezzo3,#pezzo4,#pezzo5{ /*cerchio*/
background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='100%' height='100%'><circle cx='50%' cy='50%' r='30%' fill='%23F00'/></svg>");
}
#pezzo6,#pezzo7,#pezzo8,#pezzo9,#pezzo10{ /*ics*/
background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' height='100%' width='100%'><line x1='0%' y1='0%' x2='100%' y2='100%' style='stroke:%23f00;stroke-width:5' /><line x1='100%' y1='0%' x2='0%' y2='100%' style='stroke:%23f00;stroke-width:5' /></svg>");
}
.cella{
width:25%;
height:27%;
border:1px solid #000;
margin-top:0px;
}
.cella:hover{
background:#ccc;
}
</style>
</head>
<body>
<div style="width:100%;text-align:center" onclick="window.location.replace('')"><button>Reset</button><br><br></div>
<div class="cella" id="cella1"></div>
<div class="cella" id="cella2"></div>
<div class="cella" id="cella3"></div>
<div class="cella" id="cella4"></div>
<div class="cella" id="cella5"></div>
<div class="cella" id="cella6"></div>
<div class="cella" id="cella7"></div>
<div class="cella" id="cella8"></div>
<div class="cella" id="cella9"></div>
<div style="width:100%"><br></div>
<div class="container" draggable="true" id="pezzo1"> </div><div class="container" draggable="true" id="pezzo2"> </div><div class="container" draggable="true" id="pezzo3"> </div><div class="container" draggable="true" id="pezzo4"> </div><div class="container" draggable="true" id="pezzo5"> </div><div class="container" draggable="true" id="pezzo6"> </div><div class="container" draggable="true" id="pezzo7"> </div><div class="container" draggable="true" id="pezzo8"> </div><div class="container" draggable="true" id="pezzo9"> </div><div class="container" draggable="true" id="pezzo10"> </div>
<script>
//tramite ID, no classi
const pezzo1 = document.getElementById('pezzo1');
const pezzo2 = document.getElementById('pezzo2');
const pezzo3 = document.getElementById('pezzo3');
const pezzo4 = document.getElementById('pezzo4');
const pezzo5 = document.getElementById('pezzo5');
const pezzo6 = document.getElementById('pezzo6');
const pezzo7 = document.getElementById('pezzo7');
const pezzo8 = document.getElementById('pezzo8');
const pezzo9 = document.getElementById('pezzo9');
const pezzo10 = document.getElementById('pezzo10');
const cella1 = document.getElementById('cella1');
const cella2 = document.getElementById('cella2');
const cella3 = document.getElementById('cella3');
const cella4 = document.getElementById('cella4');
const cella5 = document.getElementById('cella5');
const cella6 = document.getElementById('cella6');
const cella7 = document.getElementById('cella7');
const cella8 = document.getElementById('cella8');
const cella9 = document.getElementById('cella9');
for(let i=1;i<11;i++){
document.getElementById("pezzo"+i).addEventListener('dragstart', dragStart);
document.getElementById("pezzo"+i).addEventListener('dragend', dragEnd);
document.getElementById("pezzo"+i).addEventListener('dragstart', dragStart);
document.getElementById("pezzo"+i).addEventListener('dragend', dragEnd);
if(i!=10){ //i pezzi sono uno in più delle celle
document.getElementById("cella"+i).addEventListener('dragover', dragOver);
document.getElementById("cella"+i).addEventListener('drop', drop);
}
}
function dragStart(e) {
e.dataTransfer.setData('text/plain', e.target.id);
}
function dragEnd(e) {
e.target.style.width="100%";
e.target.style.height="100%";
}
function dragOver(e) {
e.preventDefault();
}
function drop(e) {
e.preventDefault();
const data = e.dataTransfer.getData('text/plain');
e.target.appendChild(document.getElementById(data));
}
</script>
</body>
</html>
Ecco un'immagine di come appare il gioco (viene anche evidenziata la cella che sto puntando con il mouse). La grafica (croce e cerchio) tramite svg è per ora semplice, volendo si può ovviamente migliorare.
Vi piace? Come ho detto questa è solo la parte 1, arriverà un gioco più interessante e completo nella parte 2 🙂