finalizzazione del progetto
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 1.6 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.7 MiB |
+139
-10
@@ -1,19 +1,148 @@
|
||||
/* --- VARIABILI COLORI --- */
|
||||
:root {
|
||||
--bg-light: #f8fafc;
|
||||
--text-dark: #1e293b;
|
||||
--green-eco: #10b981;
|
||||
--green-dark: #065f46;
|
||||
--gold: #f1c40f;
|
||||
--silver: #95a5a6;
|
||||
--bronze: #cd7f32;
|
||||
--white: #ffffff;
|
||||
}
|
||||
|
||||
/* --- RESET E BASE --- */
|
||||
body {
|
||||
font-family: "Arial";
|
||||
}
|
||||
table, h1 {
|
||||
margin: auto;
|
||||
font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||
background-color: var(--bg-light);
|
||||
margin: 0;
|
||||
padding: 40px 20px;
|
||||
color: var(--text-dark);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
padding: 15px;
|
||||
color: var(--text-dark);
|
||||
font-size: 2.5rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
table {
|
||||
width: 75vw;
|
||||
|
||||
/* --- BOTTONI ORDINAMENTO --- */
|
||||
.sorting-buttons {
|
||||
text-align: center;
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.sort-button {
|
||||
display: inline-block;
|
||||
padding: 12px 25px;
|
||||
margin: 0 10px;
|
||||
background-color: var(--white);
|
||||
color: var(--green-eco);
|
||||
text-decoration: none;
|
||||
border-radius: 12px;
|
||||
border: 2px solid var(--green-eco);
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.sort-button:hover {
|
||||
background-color: var(--green-eco);
|
||||
color: var(--white);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.sort-button.active {
|
||||
background-color: var(--green-eco);
|
||||
color: var(--white);
|
||||
box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3);
|
||||
}
|
||||
|
||||
/* --- TABELLA --- */
|
||||
table {
|
||||
width: 100%;
|
||||
max-width: 1100px;
|
||||
margin: 0 auto;
|
||||
border-collapse: separate;
|
||||
border-spacing: 0;
|
||||
background-color: var(--white);
|
||||
border-radius: 20px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 10px 30px rgba(0,0,0,0.05);
|
||||
}
|
||||
|
||||
th, td {
|
||||
padding: 10px;
|
||||
border: 1px solid black;
|
||||
padding: 18px;
|
||||
text-align: center;
|
||||
border-bottom: 1px solid #edf2f7;
|
||||
}
|
||||
|
||||
th {
|
||||
background-color: var(--green-eco);
|
||||
color: var(--white);
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
font-size: 0.85rem;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
/* --- COLORAZIONE PODIO DINAMICA (Basata su Classi) --- */
|
||||
|
||||
/* 1° Posto - ORO (Funziona ovunque sia la riga) */
|
||||
tr.rank-gold {
|
||||
background-color: rgba(241, 196, 15, 0.08) !important;
|
||||
}
|
||||
tr.rank-gold td:first-child strong {
|
||||
color: var(--gold);
|
||||
font-size: 1.4rem;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* 2° Posto - ARGENTO */
|
||||
tr.rank-silver {
|
||||
background-color: rgba(189, 195, 199, 0.08) !important;
|
||||
}
|
||||
tr.rank-silver td:first-child strong {
|
||||
color: var(--silver);
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
/* 3° Posto - BRONZO */
|
||||
tr.rank-bronze {
|
||||
background-color: rgba(205, 127, 50, 0.05) !important;
|
||||
}
|
||||
tr.rank-bronze td:first-child strong {
|
||||
color: var(--bronze);
|
||||
font-size: 1.15rem;
|
||||
}
|
||||
|
||||
/* Stile base per la colonna posizione */
|
||||
td strong {
|
||||
font-weight: 800;
|
||||
color: var(--text-dark);
|
||||
}
|
||||
|
||||
/* Effetto al passaggio del mouse sulle righe */
|
||||
tr:hover {
|
||||
background-color: #f1f5f9;
|
||||
}
|
||||
|
||||
/* Arrotondamento angoli inferiori della tabella */
|
||||
table tr:last-child td:first-child { border-bottom-left-radius: 20px; }
|
||||
table tr:last-child td:last-child { border-bottom-right-radius: 20px; }
|
||||
|
||||
/* Rimuove l'ultima linea per pulizia estetica */
|
||||
table tr:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
/* --- RESPONSIVE --- */
|
||||
@media (max-width: 768px) {
|
||||
body { padding: 20px 10px; }
|
||||
table { font-size: 0.8rem; }
|
||||
th, td { padding: 12px 8px; }
|
||||
h1 { font-size: 1.8rem; }
|
||||
.sort-button { padding: 10px 15px; margin: 5px; }
|
||||
}
|
||||
+292
-115
@@ -1,31 +1,25 @@
|
||||
/* --- VARIABILI GLOBALI --- */
|
||||
:root {
|
||||
--green-bright: #2ecc71;
|
||||
--green-glow: rgba(46, 204, 113, 0.6);
|
||||
--glass-bg: rgba(0, 0, 0, 0.7);
|
||||
--glass-border: rgba(46, 204, 113, 0.3);
|
||||
--top: 10px;
|
||||
--border: 20px;
|
||||
--text: 1.5rem;
|
||||
}
|
||||
|
||||
/* --- RESET E BODY --- */
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
#punti {
|
||||
position: absolute;
|
||||
top: var(--top);
|
||||
left: var(--border);
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
background-color: #000;
|
||||
color: white;
|
||||
font-size: var(--text);
|
||||
pointer-events: none;
|
||||
display: none;
|
||||
}
|
||||
#tempo {
|
||||
position: absolute;
|
||||
top: var(--top);
|
||||
right: var(--border);
|
||||
color: white;
|
||||
font-size: var(--text);
|
||||
pointer-events: none;
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* --- HUD DI GIOCO (Punti e Tempo) --- */
|
||||
#punti, #tempo {
|
||||
position: absolute;
|
||||
top: var(--top);
|
||||
@@ -33,182 +27,365 @@ body {
|
||||
font-size: var(--text);
|
||||
pointer-events: none;
|
||||
display: none;
|
||||
/* Aggiungi questa riga */
|
||||
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.7);
|
||||
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.8), 0 0 10px var(--green-glow);
|
||||
font-weight: bold;
|
||||
z-index: 50;
|
||||
}
|
||||
|
||||
/* Cursore */
|
||||
#punti { left: var(--border); }
|
||||
#tempo { right: var(--border); }
|
||||
#fps-counter {
|
||||
position: absolute;
|
||||
top: var(--top); /* Usa la stessa variabile degli altri */
|
||||
left: 50%;
|
||||
transform: translateX(-50%); /* Lo centra perfettamente */
|
||||
color: var(--green-bright);
|
||||
font-size: 1.2rem; /* Leggermente più piccolo dei punti per non distrarre */
|
||||
font-family: monospace;
|
||||
pointer-events: none;
|
||||
display: none; /* Verrà mostrato insieme agli altri al lock() */
|
||||
text-shadow: 0 0 10px var(--green-glow);
|
||||
z-index: 50;
|
||||
}
|
||||
|
||||
/* --- MIRINO (Crosshair) --- */
|
||||
#crosshair {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
color: white;
|
||||
color: var(--green-bright);
|
||||
font-size: 24px;
|
||||
font-family: sans-serif;
|
||||
pointer-events: none;
|
||||
display: none; /* Sarà visualizzato solo durante il gioco */
|
||||
display: none;
|
||||
z-index: 10;
|
||||
text-shadow: 0 0 5px #000;
|
||||
}
|
||||
|
||||
/* Schermata iniziale del gioco */
|
||||
/* --- SCHERMATA DI CARICAMENTO (MATRIX) --- */
|
||||
#loading-screen {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: #000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 9999;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#matrix-canvas {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.loader-content {
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
width: 80%;
|
||||
max-width: 500px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.eco-title {
|
||||
font-family: 'Courier New', monospace;
|
||||
color: var(--green-bright);
|
||||
font-size: 1.5rem;
|
||||
font-weight: bold;
|
||||
letter-spacing: 5px;
|
||||
margin-bottom: 30px;
|
||||
text-shadow: 0 0 10px var(--green-glow);
|
||||
}
|
||||
|
||||
.bar-container {
|
||||
width: 100%;
|
||||
background: #222 !important;
|
||||
height: 10px;
|
||||
border-radius: 5px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
z-index: 20;
|
||||
border: 1px solid rgba(255,255,255,0.1);
|
||||
}
|
||||
|
||||
#loading-bar {
|
||||
width: 0%;
|
||||
height: 100%;
|
||||
background-color: var(--green-bright) !important;
|
||||
box-shadow: 0 0 20px var(--green-bright);
|
||||
transition: width 0.3s ease-out;
|
||||
}
|
||||
|
||||
#loading-text {
|
||||
color: var(--green-bright);
|
||||
font-family: monospace;
|
||||
font-size: 0.9rem;
|
||||
letter-spacing: 2px;
|
||||
opacity: 0.8;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
/* --- POPUP INSERIMENTO USERNAME --- */
|
||||
/* Overlay con sfocatura profonda */
|
||||
#name-popup-overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 9999;
|
||||
background: radial-gradient(circle, rgba(0, 20, 10, 0.7) 0%, rgba(0, 0, 0, 0.95) 100%);
|
||||
backdrop-filter: blur(12px);
|
||||
display: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
}
|
||||
|
||||
/* Contenitore Popup */
|
||||
.name-popup {
|
||||
background: rgba(10, 15, 12, 0.85);
|
||||
border: 2px solid var(--green-bright);
|
||||
padding: 3rem;
|
||||
border-radius: 30px;
|
||||
text-align: center;
|
||||
box-shadow: 0 0 40px rgba(46, 204, 113, 0.2), inset 0 0 20px rgba(46, 204, 113, 0.1);
|
||||
max-width: 450px;
|
||||
width: 90%;
|
||||
transform: translateY(20px);
|
||||
animation: popupFadeIn 0.6s ease forwards;
|
||||
border-top: 5px solid var(--green-bright); /* Accento superiore */
|
||||
}
|
||||
|
||||
@keyframes popupFadeIn {
|
||||
to { transform: translateY(0); opacity: 1; }
|
||||
}
|
||||
|
||||
.name-popup h3 {
|
||||
color: var(--green-bright);
|
||||
margin-bottom: 10px;
|
||||
letter-spacing: 3px;
|
||||
text-transform: uppercase;
|
||||
font-weight: 900;
|
||||
text-shadow: 0 0 10px var(--green-glow);
|
||||
}
|
||||
|
||||
.name-popup p {
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
font-size: 0.9rem;
|
||||
margin-bottom: 2rem;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* Input stilizzato */
|
||||
#username-input {
|
||||
width: 100%;
|
||||
padding: 15px;
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
border: 1px solid rgba(46, 204, 113, 0.4);
|
||||
border-radius: 12px;
|
||||
color: #fff;
|
||||
font-size: 1.2rem;
|
||||
margin-bottom: 25px;
|
||||
outline: none;
|
||||
text-align: center;
|
||||
transition: all 0.3s ease;
|
||||
box-sizing: border-box;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
#username-input:focus {
|
||||
border-color: var(--green-bright);
|
||||
box-shadow: 0 0 15px var(--green-glow);
|
||||
background: rgba(46, 204, 113, 0.05);
|
||||
}
|
||||
|
||||
/* Pulsante di conferma */
|
||||
#confirm-name-btn {
|
||||
width: 100%;
|
||||
background: var(--green-bright);
|
||||
color: #002b12;
|
||||
border: none;
|
||||
padding: 15px;
|
||||
font-weight: 800;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
cursor: pointer;
|
||||
border-radius: 12px;
|
||||
transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
}
|
||||
|
||||
#confirm-name-btn:hover {
|
||||
background: #fff;
|
||||
color: #000;
|
||||
box-shadow: 0 0 25px #fff;
|
||||
transform: scale(1.03);
|
||||
}
|
||||
|
||||
/* Effetto errore (scuotimento) */
|
||||
.shake {
|
||||
animation: shakeAnim 0.4s ease;
|
||||
}
|
||||
|
||||
@keyframes shakeAnim {
|
||||
0%, 100% { transform: translateX(0); }
|
||||
25% { transform: translateX(-10px); }
|
||||
75% { transform: translateX(10px); }
|
||||
}
|
||||
|
||||
/* --- SCHERMATA INIZIALE (START) --- */
|
||||
/* L'overlay serve come ulteriore strato di colore per far leggere bene i testi */
|
||||
.overlay {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: radial-gradient(circle, rgba(0,0,0,0) 0%, rgba(0,0,0,0.6) 100%);
|
||||
z-index: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Assicurati che il contenitore start non mostri lo scale dell'immagine fuori dai bordi */
|
||||
#start {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
color: white;
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
/* Queste 4 righe garantiscono la centratura totale */
|
||||
inset: 0;
|
||||
overflow: hidden; /* Fondamentale per il trucco dello scale */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 100; /* Assicurati che sia sopra al renderer di Three.js */
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
/* Video a tutto schermo */
|
||||
#bg-video {
|
||||
#bg-island {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
z-index: -1;
|
||||
object-fit: cover; /* Riempie lo schermo senza deformare */
|
||||
/* Effetto sfocatura e luminosità ridotta */
|
||||
filter: blur(6px) brightness(0.5);
|
||||
/* Lo scale(1.1) serve a "ingrandire" l'immagine quel tanto che basta
|
||||
per nascondere i bordi sfocati che altrimenti diventerebbero bianchi */
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
inset: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
z-index: 0;
|
||||
pointer-events: none; /* Il click attraversa l'overlay e arriva a #start */
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.content {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
height: 100%;
|
||||
width: 100%; /* Aggiunto */
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* Divisione 50% Sopra */
|
||||
/* Titolo Missione */
|
||||
.top-section {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding-top: 40px;
|
||||
}
|
||||
|
||||
.main-title {
|
||||
width: 25%;
|
||||
height: auto;
|
||||
filter: drop-shadow(0 0 15px var(--green-bright));
|
||||
}
|
||||
|
||||
|
||||
/* Divisione 50% Sotto */
|
||||
/* Layout a Tre Colonne */
|
||||
.bottom-section {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100%; /* Forza l'espansione orizzontale */
|
||||
align-items: flex-start;
|
||||
padding-top: 20px;
|
||||
flex: 1.5;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
align-items: center;
|
||||
padding: 0 5%;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.item {
|
||||
/* flex: 1 0 33%; significa: cresci, non restringerti, base 33% */
|
||||
flex: 1 0 33.33%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Styling dei Controlli */
|
||||
.controls-box {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* Box con effetto Vetro (Glassmorphism) */
|
||||
.controls-box, .instructions-box {
|
||||
background: var(--glass-bg);
|
||||
backdrop-filter: blur(10px);
|
||||
border: 1px solid var(--glass-border);
|
||||
padding: 25px;
|
||||
border-radius: 15px;
|
||||
color: white;
|
||||
text-shadow: 2px 2px 4px rgba(0,0,0,0.8);
|
||||
font-family: 'Press Start 2P', cursive;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
|
||||
width: 100%;
|
||||
max-width: 350px;
|
||||
}
|
||||
|
||||
.controls-box h3 {
|
||||
margin-bottom: 10px;
|
||||
font-size: 1.4rem;
|
||||
.controls-box h3, .instructions-box h3 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 15px;
|
||||
font-size: 1.3rem;
|
||||
text-transform: uppercase;
|
||||
color: var(--green-bright);
|
||||
text-align: center;
|
||||
border-bottom: 1px solid var(--glass-border);
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.controls-box p {
|
||||
margin: 6px 0;
|
||||
font-size: 1.1rem;
|
||||
.controls-box p, .instructions-box p {
|
||||
margin: 8px 0;
|
||||
font-size: 1rem;
|
||||
text-align: center;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* Stile dei tasti */
|
||||
.controls-box kbd {
|
||||
background-color: #5e5d5d;
|
||||
color: #fff;
|
||||
padding: 4px 8px;
|
||||
/* Tasti Tastiera */
|
||||
kbd {
|
||||
background-color: #333;
|
||||
border: 1px solid var(--green-bright);
|
||||
color: var(--green-bright);
|
||||
padding: 3px 6px;
|
||||
border-radius: 4px;
|
||||
font-family: monospace;
|
||||
font-weight: bold;
|
||||
margin: 6px 0;
|
||||
box-shadow: 0 0 5px var(--green-glow);
|
||||
}
|
||||
|
||||
/* Box delle istruzioni */
|
||||
.instructions-box {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
color: white;
|
||||
text-shadow: 2px 2px 4px rgba(0,0,0,0.8);
|
||||
font-family: 'Press Start 2P', cursive;
|
||||
}
|
||||
|
||||
.instructions-box h3 {
|
||||
margin-bottom: 10px;
|
||||
font-size: 1.4rem;
|
||||
text-transform: uppercase;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.instructions-box p {
|
||||
margin: 6px 0;
|
||||
font-size: 1.1rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Animazione per "Clicca per giocare" */
|
||||
/* Testo Pulsante Centrale */
|
||||
.pulse-text {
|
||||
font-size: 1.5rem;
|
||||
font-size: 2rem;
|
||||
font-weight: 800;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
letter-spacing: 4px;
|
||||
color: #fff;
|
||||
text-shadow: 0 0 15px var(--green-bright);
|
||||
cursor: pointer;
|
||||
animation: pulse 2s infinite;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0% { opacity: 1; }
|
||||
50% { opacity: 0.4; }
|
||||
100% { opacity: 1; }
|
||||
0% { opacity: 1; transform: scale(1); }
|
||||
50% { opacity: 0.5; transform: scale(0.95); }
|
||||
100% { opacity: 1; transform: scale(1); }
|
||||
}
|
||||
|
||||
/* Responsive per schermi piccoli */
|
||||
@media (max-width: 900px) {
|
||||
.bottom-section {
|
||||
grid-template-columns: 1fr;
|
||||
overflow-y: auto;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
.main-title { width: 50%; }
|
||||
}
|
||||
+96
-63
@@ -1,123 +1,156 @@
|
||||
/* --- VARIABILI GLOBALI --- */
|
||||
:root {
|
||||
--bg-light: #f8fafc;
|
||||
--text-dark: #1e293b;
|
||||
--green-eco: #10b981;
|
||||
--red-alert: #ef4444;
|
||||
--counter-top: #334155;
|
||||
}
|
||||
|
||||
/* --- RESET BASE --- */
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #f0f0f0;
|
||||
padding: 0;
|
||||
font-family: 'Inter', -apple-system, sans-serif;
|
||||
background-color: var(--bg-light);
|
||||
color: var(--text-dark);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* --- UI SUPERIORE (Punti e Tempo) --- */
|
||||
#ui {
|
||||
margin-top: 20px;
|
||||
padding: 12px 40px;
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
font-size: 1.1rem;
|
||||
font-weight: 700;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
border: 1px solid #e2e8f0;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
#ui span {
|
||||
color: var(--green-eco);
|
||||
}
|
||||
|
||||
/* --- CONTAINER GIOCO --- */
|
||||
#game-container {
|
||||
width: 1000px;
|
||||
height: 600px;
|
||||
background-color: #000;
|
||||
width: 92vw;
|
||||
height: 82vh;
|
||||
background-color: #000; /* Fondo nero per il mix-blend-mode */
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border: 5px solid #333;
|
||||
margin: 0 auto;
|
||||
cursor: default;
|
||||
border-radius: 24px;
|
||||
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
|
||||
margin: 20px auto;
|
||||
border: 8px solid white; /* Cornice stile tablet */
|
||||
}
|
||||
|
||||
/* Area dei bidoni */
|
||||
/* --- AREA DEI BIDONI (Ingranditi) --- */
|
||||
#bins-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 20px 10px;
|
||||
justify-content: center; /* Centra i bidoni */
|
||||
gap: 12px; /* Spazio tra i bidoni */
|
||||
align-items: flex-end;
|
||||
padding: 30px 20px;
|
||||
width: 100%;
|
||||
height: 72%; /* Più spazio verticale per cestini grandi */
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* Effetto bagliore per risposta corretta (Verde) */
|
||||
.glow-success {
|
||||
box-shadow: 0 0 30px 15px rgba(0, 255, 0, 0.6);
|
||||
border-radius: 50%; /* Rende l'effetto ovale/circolare */
|
||||
transition: box-shadow 0.2s ease-in-out;
|
||||
.bin {
|
||||
position: relative;
|
||||
/* Ingrandimento: ora i bidoni occupano fino al 20% della larghezza */
|
||||
width: 20%;
|
||||
max-width: 200px;
|
||||
min-width: 140px;
|
||||
transition: transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
}
|
||||
|
||||
/* Effetto bagliore per risposta errata (Rosso) */
|
||||
.glow-error {
|
||||
box-shadow: 0 0 30px 15px rgba(255, 0, 0, 0.6);
|
||||
border-radius: 50%;
|
||||
transition: box-shadow 0.2s ease-in-out;
|
||||
.bin:hover {
|
||||
transform: scale(1.08) translateY(-10px);
|
||||
}
|
||||
|
||||
/* Gestione immagini con sfondo nero e scritta interna */
|
||||
.bin img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
mix-blend-mode: screen; /* Rende il nero dell'immagine trasparente */
|
||||
pointer-events: none;
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
|
||||
/* Questa riga è la magia: */
|
||||
mix-blend-mode: screen;
|
||||
|
||||
/* 'screen' mantiene i colori chiari e rende invisibile il nero.
|
||||
In questo modo il bagliore dietro passerà attraverso le zone nere. */
|
||||
/* Aumentiamo luminosità e contrasto per far leggere meglio le scritte nere */
|
||||
filter: brightness(1.25) contrast(1.1);
|
||||
}
|
||||
|
||||
|
||||
/* Modifica leggera al bagliore per renderlo più visibile sotto il bidone */
|
||||
/* --- EFFETTI FEEDBACK (Bagliore sotto) --- */
|
||||
.bin::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 60%; /* Abbassato un po' per centrarsi meglio sulla base del bidone */
|
||||
bottom: 5%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 150px;
|
||||
height: 100px; /* Più largo che alto per un effetto ovale perfetto */
|
||||
transform: translateX(-50%);
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
border-radius: 50%;
|
||||
opacity: 0;
|
||||
filter: blur(10px); /* Sfuma i bordi della luce */
|
||||
transition: opacity 0.3s;
|
||||
z-index: -1;
|
||||
filter: blur(25px);
|
||||
transition: opacity 0.3s ease;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* Stato Successo (Verde) */
|
||||
.glow-success::after {
|
||||
opacity: 1;
|
||||
box-shadow: 0 0 40px 20px rgba(0, 255, 0, 0.7);
|
||||
background-color: rgba(0, 255, 0, 0.2); /* Opzionale: un leggero centro colorato */
|
||||
opacity: 0.8;
|
||||
background: var(--green-eco);
|
||||
box-shadow: 0 0 60px 30px var(--green-eco);
|
||||
}
|
||||
|
||||
/* Stato Errore (Rosso) */
|
||||
.glow-error::after {
|
||||
opacity: 1;
|
||||
box-shadow: 0 0 40px 20px rgba(255, 0, 0, 0.7);
|
||||
background-color: rgba(255, 0, 0, 0.2);
|
||||
opacity: 0.8;
|
||||
background: var(--red-alert);
|
||||
box-shadow: 0 0 60px 30px var(--red-alert);
|
||||
}
|
||||
|
||||
.bin img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
pointer-events: none; /* Impedisce che il mouse "prenda" l'immagine del bidone */
|
||||
}
|
||||
|
||||
/* I rifiuti */
|
||||
/* --- I RIFIUTI (Trash) --- */
|
||||
.trash {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
object-fit: contain;
|
||||
position: absolute;
|
||||
z-index: 100;
|
||||
z-index: 500;
|
||||
cursor: grab;
|
||||
/* Ombra per farli sembrare sollevati */
|
||||
filter: drop-shadow(0 12px 10px rgba(0,0,0,0.4));
|
||||
}
|
||||
|
||||
.trash:active {
|
||||
cursor: grabbing;
|
||||
}
|
||||
/* Il bancone marrone in basso */
|
||||
|
||||
/* --- IL BANCONE (Counter) --- */
|
||||
#counter {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
background-color: #5d4037;
|
||||
/* Colore marrone bancone */
|
||||
height: 120px;
|
||||
background: var(--counter-top);
|
||||
border-top: 3px solid rgba(255,255,255,0.1);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* Area UI (Punti e Tempo) */
|
||||
#ui {
|
||||
margin-top: 10px;
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
/* Effetto profondità sul bordo del bancone */
|
||||
#counter::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 8px;
|
||||
background: linear-gradient(to bottom, rgba(0,0,0,0.3), transparent);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #f0f0f0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#game-container {
|
||||
/*width: 1000px;
|
||||
height: 600px;*/
|
||||
width: 90vw;
|
||||
height: 90vh;
|
||||
background-color: #000;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border: 5px solid #333;
|
||||
margin: 0 auto;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/* Area dei bidoni */
|
||||
#bins-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 20px 10px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* Effetto bagliore per risposta corretta (Verde) */
|
||||
.glow-success {
|
||||
box-shadow: 0 0 30px 15px rgba(0, 255, 0, 0.6);
|
||||
border-radius: 50%; /* Rende l'effetto ovale/circolare */
|
||||
transition: box-shadow 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
/* Effetto bagliore per risposta errata (Rosso) */
|
||||
.glow-error {
|
||||
box-shadow: 0 0 30px 15px rgba(255, 0, 0, 0.6);
|
||||
border-radius: 50%;
|
||||
transition: box-shadow 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.bin img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
pointer-events: none;
|
||||
|
||||
/* Questa riga è la magia: */
|
||||
mix-blend-mode: screen;
|
||||
|
||||
/* 'screen' mantiene i colori chiari e rende invisibile il nero.
|
||||
In questo modo il bagliore dietro passerà attraverso le zone nere. */
|
||||
}
|
||||
|
||||
|
||||
/* Modifica leggera al bagliore per renderlo più visibile sotto il bidone */
|
||||
.bin::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 60%; /* Abbassato un po' per centrarsi meglio sulla base del bidone */
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 150px;
|
||||
height: 100px; /* Più largo che alto per un effetto ovale perfetto */
|
||||
border-radius: 50%;
|
||||
opacity: 0;
|
||||
filter: blur(10px); /* Sfuma i bordi della luce */
|
||||
transition: opacity 0.3s;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
/* Stato Successo (Verde) */
|
||||
.glow-success::after {
|
||||
opacity: 1;
|
||||
box-shadow: 0 0 40px 20px rgba(0, 255, 0, 0.7);
|
||||
background-color: rgba(0, 255, 0, 0.2); /* Opzionale: un leggero centro colorato */
|
||||
}
|
||||
|
||||
/* Stato Errore (Rosso) */
|
||||
.glow-error::after {
|
||||
opacity: 1;
|
||||
box-shadow: 0 0 40px 20px rgba(255, 0, 0, 0.7);
|
||||
background-color: rgba(255, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.bin img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
pointer-events: none; /* Impedisce che il mouse "prenda" l'immagine del bidone */
|
||||
}
|
||||
|
||||
/* I rifiuti */
|
||||
.trash {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
object-fit: contain;
|
||||
position: absolute;
|
||||
z-index: 100;
|
||||
}
|
||||
.trash:active {
|
||||
cursor: grabbing;
|
||||
}
|
||||
/* Il bancone marrone in basso */
|
||||
#counter {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
background-color: #5d4037;
|
||||
/* Colore marrone bancone */
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* Area UI (Punti e Tempo) */
|
||||
#ui {
|
||||
margin-top: 10px;
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
/* --- VARIABILI GLOBALI --- */
|
||||
:root {
|
||||
--green-bright: #2ecc71;
|
||||
--green-glow: rgba(46, 204, 113, 0.4);
|
||||
--glass-bg: rgba(255, 255, 255, 0.05);
|
||||
--glass-border: rgba(46, 204, 113, 0.2);
|
||||
--top: 10px;
|
||||
--text-base: 1.1rem;
|
||||
}
|
||||
|
||||
/* --- RESET E BASE --- */
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
background-color: #000; /* Sfondo di sicurezza */
|
||||
}
|
||||
|
||||
/* --- SCHERMATA FASE 2 --- */
|
||||
#start-fase2 {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 500;
|
||||
color: white;
|
||||
font-family: 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
||||
|
||||
/* Sfondo Sfumato Base */
|
||||
background: radial-gradient(circle at center, #0a2f1a 0%, #000000 100%);
|
||||
transition: opacity 0.5s ease;
|
||||
}
|
||||
|
||||
/* Overlay per dare texture allo sfondo */
|
||||
.overlay-gradient {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: linear-gradient(180deg, transparent 0%, rgba(46, 204, 113, 0.05) 100%);
|
||||
pointer-events: none;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
/* --- CONTENUTO --- */
|
||||
.content {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* Sezione Titolo (50% sopra) */
|
||||
.top-section {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.top-section h1 {
|
||||
font-size: 3.5rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 5px;
|
||||
color: var(--green-bright);
|
||||
text-shadow: 0 0 20px var(--green-glow);
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
/* Sezione Box (50% sotto) */
|
||||
.bottom-section {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
align-items: flex-start;
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.item {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
/* --- BOX STILIZZATI (Glassmorphism) --- */
|
||||
.controls-box, .instructions-box {
|
||||
background: var(--glass-bg);
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
border: 1px solid var(--glass-border);
|
||||
border-top: 4px solid var(--green-bright);
|
||||
padding: 30px;
|
||||
border-radius: 20px;
|
||||
box-shadow: 0 15px 35px rgba(0,0,0,0.6);
|
||||
width: 100%;
|
||||
max-width: 350px;
|
||||
min-height: 200px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.controls-box h3, .instructions-box h3 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 20px;
|
||||
font-size: 1.4rem;
|
||||
text-transform: uppercase;
|
||||
color: var(--green-bright);
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.controls-box p, .instructions-box p {
|
||||
font-size: var(--text-base);
|
||||
line-height: 1.6;
|
||||
margin: 10px 0;
|
||||
text-shadow: 1px 1px 2px rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
/* --- ELEMENTI SPECIALI --- */
|
||||
kbd {
|
||||
background: #222;
|
||||
color: var(--green-bright);
|
||||
border: 1px solid var(--green-bright);
|
||||
padding: 3px 10px;
|
||||
border-radius: 5px;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-weight: bold;
|
||||
box-shadow: 0 0 5px var(--green-glow);
|
||||
}
|
||||
|
||||
b, i {
|
||||
color: var(--green-bright);
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* --- PULSANTE CENTRALE --- */
|
||||
.item.center {
|
||||
align-items: center; /* Il pulsante centrale lo vogliamo a metà altezza */
|
||||
height: 50%;
|
||||
}
|
||||
|
||||
.pulse-text {
|
||||
display: inline-block;
|
||||
padding: 20px 40px;
|
||||
font-size: 1.5rem;
|
||||
font-weight: 800;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
color: white;
|
||||
border: 2px solid var(--green-bright);
|
||||
border-radius: 50px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
animation: pulse 2s infinite;
|
||||
background: rgba(46, 204, 113, 0.1);
|
||||
}
|
||||
|
||||
.pulse-text:hover {
|
||||
background: var(--green-bright);
|
||||
color: black;
|
||||
box-shadow: 0 0 30px var(--green-glow);
|
||||
transform: scale(1.1);
|
||||
animation-play-state: paused; /* Si ferma quando ci passi sopra */
|
||||
}
|
||||
|
||||
/* --- ANIMAZIONI --- */
|
||||
@keyframes pulse {
|
||||
0% { transform: scale(1); opacity: 1; box-shadow: 0 0 0 0 rgba(46, 204, 113, 0.7); }
|
||||
50% { transform: scale(1.05); opacity: 0.7; box-shadow: 0 0 20px 10px rgba(46, 204, 113, 0); }
|
||||
100% { transform: scale(1); opacity: 1; box-shadow: 0 0 0 0 rgba(46, 204, 113, 0); }
|
||||
}
|
||||
|
||||
/* --- RESPONSIVE VELOCE --- */
|
||||
@media (max-width: 900px) {
|
||||
.bottom-section {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
.item {
|
||||
margin-bottom: 20px;
|
||||
width: 80%;
|
||||
}
|
||||
.top-section h1 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
:root {
|
||||
--green-bright: #2ecc71;
|
||||
--green-glow: #27ae60;
|
||||
--bg-overlay: rgba(0, 0, 0, 0.6);
|
||||
--panel-bg: rgba(0, 0, 0, 0.3);
|
||||
--text-main: 1.2rem;
|
||||
}
|
||||
|
||||
body, html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
color: white;
|
||||
background: url('../assets/media/img/sfondo_finale.png') no-repeat center center fixed;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
/* Overlay per scurire leggermente lo sfondo e far risaltare il testo */
|
||||
.overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: var(--bg-overlay);
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
/* Layout Principale (Diviso in Sinistra e Destra) */
|
||||
#start {
|
||||
position: relative;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* --- SEZIONE SINISTRA (60% del totale) --- */
|
||||
.left1 {
|
||||
flex: 1.5;
|
||||
display: flex;
|
||||
flex-direction: column; /* Divide in Alto e Basso */
|
||||
border-right: 1px solid rgba(46, 204, 113, 0.2);
|
||||
}
|
||||
|
||||
/* Parte in ALTO a sinistra (Titolo) */
|
||||
.left1 .top {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.left1 .top h1 {
|
||||
font-size: 4.5rem;
|
||||
margin: 0;
|
||||
color: #fff;
|
||||
text-shadow: 0 0 20px var(--green-bright), 0 0 30px var(--green-glow);
|
||||
letter-spacing: 5px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Parte in BASSO a sinistra (Divisa in Bottoni e Punteggi) */
|
||||
.left1 .bottom {
|
||||
flex: 1;
|
||||
display: flex; /* Divide in Sinistra (left2) e Destra (right2) */
|
||||
padding: 40px;
|
||||
gap: 30px;
|
||||
}
|
||||
|
||||
/* Bottoni (Basso-Sinistra) */
|
||||
.left2 {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
button {
|
||||
width: 280px;
|
||||
padding: 18px;
|
||||
font-size: 1.1rem;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
background: transparent;
|
||||
border: 2px solid var(--green-bright);
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
text-transform: uppercase;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background: var(--green-bright);
|
||||
color: black;
|
||||
box-shadow: 0 0 25px var(--green-bright);
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
/* Riepilogo Punteggi (Basso-Destra) */
|
||||
.right2 {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: var(--panel-bg);
|
||||
border: 1px solid rgba(46, 204, 113, 0.3);
|
||||
border-radius: 20px;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.right2 p {
|
||||
font-size: 1.4rem;
|
||||
line-height: 2;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.right2 b {
|
||||
color: var(--green-bright);
|
||||
font-size: 1.6rem;
|
||||
display: block;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.right2 i {
|
||||
color: #ccc;
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* --- SEZIONE DESTRA (40% del totale - Classifica) --- */
|
||||
.right1 {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 40px 20px;
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.right1 h2 {
|
||||
font-size: 2.5rem;
|
||||
color: var(--green-bright);
|
||||
margin-bottom: 30px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
/* Tabella Classifica */
|
||||
table.container {
|
||||
width: 90%;
|
||||
border-collapse: collapse;
|
||||
background: rgba(255, 255, 255, 0.03);
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
table.container th {
|
||||
background: rgba(46, 204, 113, 0.5);
|
||||
padding: 15px;
|
||||
text-align: center;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
table.container td {
|
||||
padding: 12px;
|
||||
text-align: center;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
table.container tr:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
table.container tr:hover {
|
||||
background: rgba(46, 204, 113, 0.1);
|
||||
}
|
||||
|
||||
/* Supporto per Mobile/Schermi piccoli */
|
||||
@media (max-width: 1000px) {
|
||||
.content {
|
||||
flex-direction: column;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.left1 .bottom {
|
||||
flex-direction: column;
|
||||
}
|
||||
.left1 .top h1 {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
}
|
||||
@@ -15,3 +15,12 @@ CREATE TABLE punteggi (
|
||||
-- precisione = score2 / score1
|
||||
-- punteggio finale = 10000 * ( (score1 / MAX_SCORE) + (score2 / MAX_SCORE) ) / 2
|
||||
-- MAX_SCORE = 180 (numero massimo possibile di rifiuti raccolti in 1 minuto)
|
||||
|
||||
|
||||
-- DATI DI TEST
|
||||
INSERT INTO punteggi (data_partita, score1, score2, scoreT, nome) VALUES
|
||||
('2024-06-01', 150, 120, 7500, 'Simone'),
|
||||
('2024-06-02', 180, 160, 9444, 'Luca'),
|
||||
('2024-06-03', 120, 100, 6111, 'Giulia'),
|
||||
('2024-06-04', 90, 70, 4444, 'Marco'),
|
||||
('2024-06-05', 60, 50, 3055, 'Sara');
|
||||
@@ -1,9 +1,17 @@
|
||||
<head>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
|
||||
<script>
|
||||
const MAX_SCORE = 180;
|
||||
</script>
|
||||
</head>
|
||||
<?php
|
||||
$route = [
|
||||
'start' => 'fase1.html',
|
||||
'mid' => 'istruzioniFase2.html',
|
||||
'sep' => 'fase2.html',
|
||||
'end' => 'risultatiFinali.html',
|
||||
'end' => 'risultatiFinali.php',
|
||||
'leaderboard' => 'classifica.php',
|
||||
'error' => 'error.html'
|
||||
];
|
||||
|
||||
+80
-13
@@ -2,29 +2,79 @@ import * as THREE from 'three';
|
||||
import { PointerLockControls } from 'three/addons/controls/PointerLockControls.js';
|
||||
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
|
||||
|
||||
// 0. IMPOSTAZIONE FPS
|
||||
let lastTime = performance.now();
|
||||
let frameCount = 0;
|
||||
let fps = 0;
|
||||
const fpsDisplay = document.getElementById('fps-counter');
|
||||
|
||||
// 1a. INIZIALIZZAZIONE CARICAMENTO ASSETS
|
||||
const manager = new THREE.LoadingManager();
|
||||
manager.onStart = function (url, itemsLoaded, itemsTotal) {
|
||||
document.getElementById("loading-text").innerHTML = `Inizio caricamento: ${url}`;
|
||||
console.log(`Inizio caricamento: ${url}`);
|
||||
// Testo iniziale
|
||||
document.getElementById("loading-text").innerHTML = "IDENTIFICAZIONE RISORSE...";
|
||||
};
|
||||
manager.onLoad = function () {
|
||||
document.getElementById('loading-screen').style.display = 'none';
|
||||
animate(); // avvia il rendering
|
||||
const loadingText = document.getElementById("loading-text");
|
||||
// Testo in italiano, tecnico e pulito
|
||||
loadingText.innerHTML = "CARICAMENTO COMPLETATO CON SUCCESSO";
|
||||
// Estetica finale: testo fisso e brillante
|
||||
loadingText.style.animation = "none";
|
||||
loadingText.style.color = "#ffffff";
|
||||
loadingText.style.textShadow = "0 0 15px var(--green-bright)";
|
||||
loadingText.style.opacity = "1";
|
||||
// Timeout per lasciare all'utente il tempo di leggere il successo
|
||||
setTimeout(() => {
|
||||
const loadingScreen = document.getElementById('loading-screen');
|
||||
loadingScreen.style.opacity = '0';
|
||||
loadingScreen.style.transition = 'opacity 0.8s ease';
|
||||
setTimeout(() => {
|
||||
loadingScreen.style.display = 'none';
|
||||
// MOSTRA IL POPUP DEL NOME
|
||||
document.getElementById('name-popup-overlay').style.display = 'flex';
|
||||
}, 800);
|
||||
}, 500);
|
||||
animate(); // Parte il loop di Three.js
|
||||
};
|
||||
manager.onProgress = function (url, itemsLoaded, itemsTotal) {
|
||||
// Calcola la percentuale
|
||||
const percent = (itemsLoaded / itemsTotal) * 100;
|
||||
document.getElementById('loading-bar').style.width = percent + '%';
|
||||
|
||||
// Aggiorna il testo
|
||||
document.getElementById("loading-text").innerHTML = `Caricamento: ${itemsLoaded} di ${itemsTotal} - ${url}`;
|
||||
console.log(`Caricamento: ${itemsLoaded} di ${itemsTotal} - ${url}`);
|
||||
const percent = Math.round((itemsLoaded / itemsTotal) * 100);
|
||||
// Estraiamo solo il nome del file dall'URL per pulizia
|
||||
// Esempio: "assets/models/bottiglia.glb" diventa "bottiglia.glb"
|
||||
const fileName = url.split('/').pop().toUpperCase();
|
||||
// Aggiorniamo la barra
|
||||
const bar = document.getElementById('loading-bar');
|
||||
if (bar) bar.style.width = percent + '%';
|
||||
// Nuovo formato del testo: NOME_FILE [XX%]
|
||||
document.getElementById("loading-text").innerHTML = `${fileName} [${percent}%]`;
|
||||
};
|
||||
manager.onError = function (url) {
|
||||
document.getElementById("loading-text").innerHTML = `Errore nel caricamento: ${url}`;
|
||||
console.log(`Errore nel caricamento: ${url}`);
|
||||
document.getElementById("loading-text").innerHTML = `ERRORE CARICAMENTO: ${url.split('/').pop()}`;
|
||||
document.getElementById("loading-text").style.color = "#ff4d4d";
|
||||
};
|
||||
// GESTIONE CONFERMA NOME
|
||||
document.getElementById('confirm-name-btn').addEventListener('click', function() {
|
||||
const input = document.getElementById('username-input');
|
||||
const name = input.value.trim();
|
||||
localStorage.setItem("username", name);
|
||||
// 1. Nascondi il Popup
|
||||
const popup = document.getElementById('name-popup-overlay');
|
||||
popup.style.opacity = '0';
|
||||
popup.style.transition = 'opacity 0.5s ease';
|
||||
|
||||
setTimeout(() => {
|
||||
popup.style.display = 'none';
|
||||
|
||||
// 2. MOSTRA LA SCHERMATA INIZIALE (Controlli e Titolo)
|
||||
const mainContent = document.getElementById('main-start-content');
|
||||
mainContent.style.display = 'flex';
|
||||
// Piccolo trucco per l'animazione di entrata (fade in)
|
||||
setTimeout(() => {
|
||||
mainContent.style.opacity = '1';
|
||||
mainContent.style.transition = 'opacity 1s ease';
|
||||
}, 50);
|
||||
|
||||
}, 500);
|
||||
});
|
||||
|
||||
// 1b. SCENA E CAMERA
|
||||
const scene = new THREE.Scene();
|
||||
@@ -150,6 +200,7 @@ function lock() {
|
||||
document.getElementById('punti').style.display = 'block';
|
||||
document.getElementById('tempo').style.display = 'block';
|
||||
document.getElementById('crosshair').style.display = 'block';
|
||||
document.getElementById('fps-counter').style.display = 'block';
|
||||
}
|
||||
function unlock() {
|
||||
timer.pause();
|
||||
@@ -157,6 +208,7 @@ function unlock() {
|
||||
document.getElementById('punti').style.display = 'none';
|
||||
document.getElementById('tempo').style.display = 'none';
|
||||
document.getElementById('crosshair').style.display = 'none';
|
||||
document.getElementById('fps-counter').style.display = 'none';
|
||||
}
|
||||
const controls = new PointerLockControls(camera, document.body);
|
||||
document.getElementById('start').addEventListener('click', () => {
|
||||
@@ -255,6 +307,21 @@ let lastSafePosition = camera.position.clone();
|
||||
|
||||
function animate() {
|
||||
requestAnimationFrame(animate);
|
||||
// --- Calcolo FPS ---
|
||||
frameCount++;
|
||||
const currentTime = performance.now();
|
||||
// Ogni secondo (1000ms) aggiorniamo il contatore visivo
|
||||
if (currentTime >= lastTime + 1000) {
|
||||
fps = frameCount;
|
||||
fpsDisplay.innerText = `FPS: ${fps}`;
|
||||
// Colore dinamico: verde se fluido, giallo/rosso se lagga
|
||||
if (fps < 30) fpsDisplay.style.color = "#ff4d4d";
|
||||
else if (fps < 55) fpsDisplay.style.color = "#f1c40f";
|
||||
else fpsDisplay.style.color = "var(--green-bright)";
|
||||
|
||||
frameCount = 0;
|
||||
lastTime = currentTime;
|
||||
}
|
||||
|
||||
if (controls.isLocked) {
|
||||
// 1. Salva la posizione attuale prima del movimento
|
||||
|
||||
+38
-36
@@ -14,8 +14,7 @@ const listaRifiuti = [
|
||||
{ img: 'assets/media/img/fase2/rifiuti/pannolino.png', tipo: 'indifferenziata' }
|
||||
];
|
||||
|
||||
let punteggio = 0;
|
||||
let tempo = 60;
|
||||
let rifiutiTotali = 0;
|
||||
const counter = document.getElementById('counter');
|
||||
const scoreDisplay = document.getElementById('score');
|
||||
|
||||
@@ -143,6 +142,7 @@ function controllaCollisione(rifiuto) {
|
||||
// PORTIAMO IL BIDONE IN PRIMO PIANO
|
||||
bidone.style.zIndex = "2000";
|
||||
|
||||
rifiutiTotali++;
|
||||
if (rifiuto.dataset.tipo === bidone.dataset.type) {
|
||||
// CORRETTO
|
||||
punteggio += 1;
|
||||
@@ -164,7 +164,9 @@ function controllaCollisione(rifiuto) {
|
||||
bidone.style.zIndex = "1"; // Ritorna al suo posto dopo l'effetto
|
||||
}, 400);
|
||||
}
|
||||
|
||||
if (rifiutiTotali >= localStorage.getItem('punteggioFase1')) {
|
||||
mostraFineGioco();
|
||||
}
|
||||
document.getElementById('score').innerText = punteggio;
|
||||
rifiuto.remove();
|
||||
setTimeout(generaRifiuto, 500);
|
||||
@@ -181,23 +183,27 @@ let timerIntervallo;
|
||||
let tempoRimanente;
|
||||
|
||||
function avviaTimer(secondiIniziali) {
|
||||
const displayTimer = document.getElementById('timer');
|
||||
const minuti = document.getElementById('minuti');
|
||||
const secondi = document.getElementById('secondi');
|
||||
|
||||
// Inizializziamo la variabile globale con il valore ricevuto
|
||||
tempoRimanente = secondiIniziali;
|
||||
displayTimer.innerText = tempoRimanente;
|
||||
minuti.innerText = String(Math.floor(tempoRimanente / 60)).padStart(2, '0');
|
||||
secondi.innerText = String(tempoRimanente % 60).padStart(2, '0');
|
||||
|
||||
// Puliamo timer precedenti
|
||||
clearInterval(timerIntervallo);
|
||||
|
||||
timerIntervallo = setInterval(() => {
|
||||
tempoRimanente--; // Sottraiamo un secondo alla variabile globale
|
||||
displayTimer.innerText = tempoRimanente; // Aggiorniamo lo schermo
|
||||
minuti.innerText = String(Math.floor(tempoRimanente / 60)).padStart(2, '0');
|
||||
secondi.innerText = String(tempoRimanente % 60).padStart(2, '0');
|
||||
|
||||
if (tempoRimanente <= 0) {
|
||||
clearInterval(timerIntervallo);
|
||||
tempoRimanente = 0;
|
||||
displayTimer.innerText = "0";
|
||||
minuti.innerText = "00";
|
||||
secondi.innerText = "00";
|
||||
mostraFineGioco();//LISA E' COMPITO TUO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1
|
||||
}
|
||||
}, 1000);
|
||||
@@ -236,36 +242,32 @@ function riposizionaSulBancone(rifiuto) {
|
||||
function mostraFineGioco() {
|
||||
// Blocca la generazione di nuovi rifiuti
|
||||
clearInterval(timerIntervallo);
|
||||
|
||||
// Mostra un messaggio finale più gradevole
|
||||
const messaggio = document.createElement('div');
|
||||
messaggio.id = 'fine-gioco';
|
||||
messaggio.innerHTML = `
|
||||
<h2>Tempo scaduto!</h2>
|
||||
<p>Il tuo punteggio finale è: <strong>${punteggio}</strong></p>
|
||||
<button id="restart-btn">Gioca di nuovo</button>
|
||||
`;
|
||||
messaggio.style.position = 'absolute';
|
||||
messaggio.style.top = '50%';
|
||||
messaggio.style.left = '50%';
|
||||
messaggio.style.transform = 'translate(-50%, -50%)';
|
||||
messaggio.style.backgroundColor = 'rgba(255, 255, 255, 0.9)';
|
||||
messaggio.style.padding = '20px';
|
||||
messaggio.style.borderRadius = '10px';
|
||||
messaggio.style.textAlign = 'center';
|
||||
messaggio.style.zIndex = '3000';
|
||||
|
||||
document.body.appendChild(messaggio);
|
||||
|
||||
// Salva il punteggio nel localStorage
|
||||
localStorage.setItem('punteggioFase2', punteggio);
|
||||
|
||||
// Aggiunge il pulsante per ricominciare
|
||||
document.getElementById('restart-btn').addEventListener('click', () => {
|
||||
document.body.removeChild(messaggio);
|
||||
punteggio = 0;
|
||||
scoreDisplay.innerText = punteggio;
|
||||
avviaTimer(60); // o il tempo che vuoi
|
||||
generaRifiuto();
|
||||
const username = localStorage.getItem('username') || 'Anonimo';
|
||||
const score1 = parseInt(localStorage.getItem('punteggioFase1')) || 0;
|
||||
const score2 = parseInt(localStorage.getItem('punteggioFase2')) || 0;
|
||||
const scoreT = 10_000 * ((score1 / MAX_SCORE) + (score2 / MAX_SCORE)) / 2;
|
||||
const data_partita = new Date().toISOString().split('T')[0]; // Formato YYYY-MM-DD
|
||||
fetch('http://localhost:8888/php/save_score.php', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
},
|
||||
body: new URLSearchParams({
|
||||
nome: username,
|
||||
score1: score1,
|
||||
score2: score2,
|
||||
scoreT: scoreT,
|
||||
data_partita: data_partita
|
||||
})
|
||||
})
|
||||
.then(response => response.text())
|
||||
.then(result => {
|
||||
console.log("Punteggio salvato con successo:", result);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error("Errore nella richiesta:", error);
|
||||
});
|
||||
window.location = "?pagina=end";
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
const canvas = document.getElementById('matrix-canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
|
||||
const symbols = '♻☘01RECYCLE-EARTH-SAVE-FUTURE';
|
||||
const fontSize = 16;
|
||||
const columns = canvas.width / fontSize;
|
||||
const drops = Array(Math.floor(columns)).fill(1);
|
||||
|
||||
function drawMatrix() {
|
||||
// Sfondo semi-trasparente per creare l'effetto scia
|
||||
ctx.fillStyle = 'rgba(0, 0, 0, 0.05)';
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
ctx.fillStyle = '#2ecc71'; // Il tuo verde brillante
|
||||
ctx.font = fontSize + 'px monospace';
|
||||
|
||||
for (let i = 0; i < drops.length; i++) {
|
||||
const text = symbols.charAt(Math.floor(Math.random() * symbols.length));
|
||||
ctx.fillText(text, i * fontSize, drops[i] * fontSize);
|
||||
|
||||
if (drops[i] * fontSize > canvas.height && Math.random() > 0.975) {
|
||||
drops[i] = 0;
|
||||
}
|
||||
drops[i]++;
|
||||
}
|
||||
}
|
||||
|
||||
// Avvia l'animazione
|
||||
setInterval(drawMatrix, 35);
|
||||
|
||||
// Adatta se l'utente ridimensiona la finestra
|
||||
window.addEventListener('resize', () => {
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
});
|
||||
Binary file not shown.
+58
-13
@@ -1,32 +1,77 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="it">
|
||||
<head>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Classifica completa</title>
|
||||
<link rel="stylesheet" href="classifica.css">
|
||||
</head>
|
||||
<body>
|
||||
<link rel="stylesheet" href="css/classifica.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Classifica</h1>
|
||||
|
||||
<?php
|
||||
require 'php/leaderboard_utils.php';
|
||||
$sort = $_GET['sort'] ?? 'score';
|
||||
|
||||
// Carico la mappa delle posizioni (logica ID -> Posizione)
|
||||
$rankMap = getRankMap();
|
||||
|
||||
// Carico i dati in base all'ordinamento scelto
|
||||
if ($sort === 'data') {
|
||||
$leaderboard = getSortedLeaderboardByDate();
|
||||
} else {
|
||||
$leaderboard = getSortedLeaderboardByScore();
|
||||
}
|
||||
?>
|
||||
|
||||
<div class="sorting-buttons">
|
||||
<a href="?pagina=leaderboard&sort=data" class="sort-button <?php echo $sort === 'data' ? 'active' : ''; ?>">Ordina per data</a>
|
||||
<a href="?pagina=leaderboard&sort=score" class="sort-button <?php echo $sort === 'score' ? 'active' : ''; ?>">Ordina per punteggio</a>
|
||||
</div>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Posizione</th>
|
||||
<th>Nome</th>
|
||||
<th>Punteggio 1° fase</th>
|
||||
<th>Punteggio 2° fase</th>
|
||||
<th>Punteggio totale</th>
|
||||
<th>Data di gioco</th>
|
||||
<th>1° Fase (RPS)</th>
|
||||
<th>2° Fase (%)</th>
|
||||
<th>Punteggio Totale (% isola pulita)</th>
|
||||
<th>Data</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if (empty($leaderboard)): ?>
|
||||
<tr><td colspan="6" style="text-align:center;">Nessun punteggio registrato.</td></tr>
|
||||
<?php else: ?>
|
||||
<?php foreach ($leaderboard as $entry): ?>
|
||||
<?php
|
||||
require 'db.php';
|
||||
foreach ($db_test as $posizione => $record) {
|
||||
riga($posizione, $record);
|
||||
}
|
||||
// Recupero la posizione reale (1, 2, 3...)
|
||||
$posizioneReale = $rankMap[$entry['id']] + 1;
|
||||
|
||||
// Determiniamo la classe del podio
|
||||
$classePodio = '';
|
||||
if ($posizioneReale === 1) $classePodio = 'rank-gold';
|
||||
elseif ($posizioneReale === 2) $classePodio = 'rank-silver';
|
||||
elseif ($posizioneReale === 3) $classePodio = 'rank-bronze';
|
||||
|
||||
// Formattazione dati (tua logica esistente)
|
||||
$rps = number_format(intval($entry['score1']) / 60, 2);
|
||||
$fase2_perc = (intval($entry['score1']) > 0) ? intval(intval($entry['score2']) / intval($entry['score1']) * 100) : 0;
|
||||
$punteggio_finale = number_format(intval($entry['scoreT']) / 100, 2);
|
||||
$data_formattata = date("d/m/Y", strtotime($entry['data_partita']));
|
||||
?>
|
||||
<tr class="<?php echo $classePodio; ?>">
|
||||
<td><strong><?php echo $posizioneReale; ?>°</strong></td>
|
||||
<td><?php echo htmlspecialchars($entry['nome']); ?></td>
|
||||
<td><?php echo $rps; ?> rps</td>
|
||||
<td><?php echo $fase2_perc; ?>%</td>
|
||||
<td><?php echo $punteggio_finale; ?>%</td>
|
||||
<td><?php echo $data_formattata; ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</body>
|
||||
</body>
|
||||
</html>
|
||||
+37
-22
@@ -7,28 +7,40 @@
|
||||
</head>
|
||||
<body>
|
||||
<!-- SCHERMATA DI CARICAMENTO -->
|
||||
<div id="loading-screen" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: #000; display: flex; flex-direction: column; align-items: center; justify-content: center; z-index: 9999;">
|
||||
<div style="width: 80%; max-width: 600px; background: #222; height: 20px; border-radius: 10px; overflow: hidden; margin-bottom: 10px;">
|
||||
<div id="loading-bar" style="width: 0%; height: 100%; background: #4CAF50; transition: width 0.3s;"></div>
|
||||
<div id="loading-screen">
|
||||
<canvas id="matrix-canvas"></canvas>
|
||||
<div class="loader-content">
|
||||
<div class="eco-title">SAVE THE ISLAND</div>
|
||||
<div class="bar-container">
|
||||
<div id="loading-bar"></div>
|
||||
</div>
|
||||
<div id="loading-text">Caricamento delle risorse...</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- POPUP INSERIMENTO USERNAME -->
|
||||
<div id="name-popup-overlay">
|
||||
<div class="name-popup">
|
||||
<h3>IDENTIFICAZIONE GIOCATORE</h3>
|
||||
<p>Inserisci il tuo nome per iniziare a giocare:</p>
|
||||
<input type="text" id="username-input" placeholder="Nome Giocatore..." maxlength="15">
|
||||
<button id="confirm-name-btn">ACCEDI AL GIOCO</button>
|
||||
</div>
|
||||
<div id="loading-text" style="color: #fff; font-family: monospace; font-size: 14px;">Loading...</div>
|
||||
</div>
|
||||
|
||||
<!-- SCHERMATA INIZIALE -->
|
||||
<div id="start">
|
||||
<video autoplay muted loop id="bg-video">
|
||||
<source src="assets/media/video/background.mp4" type="video/mp4">
|
||||
</video>
|
||||
<img src="assets/media/img/sfondo_iniziale.png" alt="Sfondo Isola" id="bg-island">
|
||||
<div class="overlay"></div>
|
||||
<div class="content">
|
||||
<div class="top-section">
|
||||
<img src="assets/media/img/titolo.png" alt="titolo" class="main-title" />
|
||||
</div>
|
||||
<div class="container bottom-section">
|
||||
<div class="item left">
|
||||
<div class="controls-box">
|
||||
<header class="top-section">
|
||||
<img src="assets/media/img/titolo.png" alt="Eco-Mission" class="main-title" />
|
||||
</header>
|
||||
<main class="bottom-section">
|
||||
<section class="item side-panel">
|
||||
<div class="glass-box">
|
||||
<h3>Controlli</h3>
|
||||
<p>Movimento</p>
|
||||
<div class="control-list">
|
||||
<p><kbd>Freccia su / W</kbd> Avanti</p>
|
||||
<p><kbd>Freccia giù / S</kbd> Indietro</p>
|
||||
<p><kbd>Freccia destra / D</kbd> Destra</p>
|
||||
@@ -36,23 +48,25 @@
|
||||
<p><kbd>Mouse</kbd> Punto di vista</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item center">
|
||||
<span class="pulse-text">Clicca per giocare</span>
|
||||
</div>
|
||||
<div class="item right">
|
||||
<div class="instructions-box">
|
||||
</section>
|
||||
<section class="item center-panel">
|
||||
<div class="pulse-text" id="btn-start">Clicca per giocare</div>
|
||||
</section>
|
||||
<section class="item side-panel">
|
||||
<div class="glass-box">
|
||||
<h3>Istruzioni</h3>
|
||||
<p>Obiettivo: raccogliere tutti i rifiuti sull’isola</p>
|
||||
<p><strong>Obiettivo:</strong> raccogliere tutti i rifiuti sull’isola</p>
|
||||
<p>Attenzione allo scadere del tempo!</p>
|
||||
<p>Usa i comandi per esplorare e ripulire</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- INTERFACCIA GRAFICA DEL GIOCO -->
|
||||
<div id="punti">Rifiuti: <span id="score">0</span></div>
|
||||
<div id="fps-counter">FPS: 0</div>
|
||||
<div id="tempo">Tempo: <span id="minuti">XX</span>:<span id="secondi">XX</span></div>
|
||||
<div id="crosshair">+</div>
|
||||
<script type="importmap">
|
||||
@@ -64,5 +78,6 @@
|
||||
}
|
||||
</script>
|
||||
<script type="module" src="js/fase1.js"></script>
|
||||
<script src="js/loadingScreen.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
</head>
|
||||
<body>
|
||||
<div id="ui">
|
||||
Punti: <span id="score">0</span> | Tempo: <span id="timer"></span>s
|
||||
Punti: <span id="score">0</span> | Tempo: <span id="minuti"></span>:<span id="secondi"></span>
|
||||
</div>
|
||||
|
||||
<div id="game-container">
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="it">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Istruzioni fase 2</title>
|
||||
<link rel="stylesheet" href="css/istruzioniFase2.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="start-fase2">
|
||||
<div class="overlay-gradient"></div>
|
||||
<div class="content">
|
||||
<div class="top-section">
|
||||
<h1>Istruzioni fase 2</h1>
|
||||
</div>
|
||||
<div class="container bottom-section">
|
||||
<div class="item left">
|
||||
<div class="controls-box">
|
||||
<h3>Controlli</h3>
|
||||
<p><kbd>Mouse</kbd> Per trascinare i rifiuti nei cestini</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item center">
|
||||
<span class="pulse-text" id="btn-start-f2">Clicca per giocare</span>
|
||||
</div>
|
||||
<div class="item right">
|
||||
<div class="instructions-box">
|
||||
<h3>Istruzioni</h3>
|
||||
<p>
|
||||
Hai <b><i id="tempo-f2-val">--</i></b> secondi per completare il livello
|
||||
<br>
|
||||
Hai raccolto <b><i id="punti-f2-val">--</i></b> rifiuti nella fase precedente
|
||||
<br>
|
||||
<b>Obiettivo:</b> separare correttamente i rifiuti nei cestini corrispondenti
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script defer>
|
||||
const punti = localStorage.getItem('punteggioFase1') || 0;
|
||||
document.getElementById('punti-f2-val').textContent = punti;
|
||||
document.getElementById('tempo-f2-val').textContent = punti * 5; // 5 secondi per ogni rifiuto raccolto nella fase 1
|
||||
document.getElementById('btn-start-f2').style.cursor = 'pointer';
|
||||
const schermata = document.getElementById('start-fase2');
|
||||
schermata.style.display = 'flex';
|
||||
|
||||
// Listener per il pulsante centrale
|
||||
document.getElementById('btn-start-f2').onclick = function() {
|
||||
schermata.style.opacity = '0';
|
||||
schermata.style.transition = 'opacity 0.5s ease';
|
||||
setTimeout(() => {
|
||||
schermata.style.display = 'none';
|
||||
window.location = '?pagina=sep';
|
||||
}, 500);
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
require 'php/leaderboard_utils.php';
|
||||
$sort = $_GET['sort'] ?? 'data';
|
||||
|
||||
// Carico la mappa delle posizioni (logica ID -> Posizione)
|
||||
$rankMap = getRankMap();
|
||||
// Carico i dati in base all'ordinamento scelto
|
||||
$leaderboard = getTop10byScore();
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="it">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Schermata Finale</title>
|
||||
<link rel="stylesheet" href="css/risultatiFinali.css">
|
||||
</head>
|
||||
<body>
|
||||
<!-- Fase 2: separazione dei rifiuti tramite drag&drop -->
|
||||
<!-- Layout simile a div#start in pages/fase1.html -->
|
||||
<div id="start">
|
||||
<div class="overlay"></div>
|
||||
<div class="content">
|
||||
<div class="left1">
|
||||
<div class="top">
|
||||
<h1>MISSIONE COMPIUTA</h1>
|
||||
</div>
|
||||
<div class="bottom">
|
||||
<div class="left2">
|
||||
<button type="button" onclick="window.open('?pagina=leaderboard', '_blank')">Classifica Completa</button>
|
||||
<button type="button" onclick="localStorage.clear(); window.location = '?pagina=start'">Gioca Ancora</button>
|
||||
</div>
|
||||
<div class="right2">
|
||||
<p>
|
||||
<b>Punteggi:</b>
|
||||
<br>
|
||||
Prima fase: <i><span id="score1a"></span>/180</i>
|
||||
<br>
|
||||
Seconda fase: <i><span id="score2"></span>/<span id="score1b"></span></i>
|
||||
<br>
|
||||
Totale: <i><span id="scoreTotale"></span>/100</i>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right1">
|
||||
<h2>Top 10</h2>
|
||||
<table class="container">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>N°</th>
|
||||
<th>Nome</th>
|
||||
<th>Punteggio</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if (empty($leaderboard)): ?>
|
||||
<tr><td colspan="3" style="text-align:center;">Nessun punteggio registrato.</td></tr>
|
||||
<?php else: ?>
|
||||
<?php foreach ($leaderboard as $entry): ?>
|
||||
<?php
|
||||
// Recupero la posizione reale dalla mappa tramite l'ID
|
||||
$posizioneReale = $rankMap[$entry['id']] + 1;
|
||||
$punteggio_finale = number_format(intval($entry['scoreT']) / 100, 2);
|
||||
?>
|
||||
<tr>
|
||||
<td><strong><?php echo $posizioneReale; ?>°</strong></td>
|
||||
<td><?php echo htmlspecialchars($entry['nome']); ?></td>
|
||||
<td><?php echo $punteggio_finale; ?>%</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script defer>
|
||||
const score1 = localStorage.getItem('punteggioFase1') || 0;
|
||||
const score2 = localStorage.getItem('punteggioFase2') || 0;
|
||||
const scoreT = 10_000 * ((score1 / MAX_SCORE) + (score2 / MAX_SCORE)) / 2;
|
||||
document.getElementById('score1a').textContent = score1;
|
||||
document.getElementById('score1b').textContent = score1;
|
||||
document.getElementById('score2').textContent = score2;
|
||||
document.getElementById('scoreTotale').textContent = scoreT.toFixed(0) / 100;
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
+7
-32
@@ -1,35 +1,10 @@
|
||||
<?php
|
||||
$debug = false;
|
||||
function setDebug($val) {
|
||||
$debug = $val;
|
||||
if ($debug) {
|
||||
echo "db";
|
||||
$servername = "localhost";
|
||||
$username = "root";
|
||||
$password = "root";
|
||||
$dbname = "save-the-island";
|
||||
$conn = new mysqli($servername, $username, $password, $dbname);
|
||||
if ($conn->connect_error) {
|
||||
die("Connection failed: " . $conn->connect_error);
|
||||
}
|
||||
}
|
||||
$db_test = [
|
||||
[
|
||||
'nome' => 's1',
|
||||
'p1' => 95,
|
||||
'p2' => 90,
|
||||
'pt' => 50,
|
||||
'g' => '24-11-2025'
|
||||
],
|
||||
[
|
||||
'nome' => 's1',
|
||||
'p1' => 95,
|
||||
'p2' => 90,
|
||||
'pt' => 50,
|
||||
'g' => '24-11-2025'
|
||||
]
|
||||
];
|
||||
$classifica = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||
function riga($pos, $data) {
|
||||
$pos++;
|
||||
$nome = $data['nome'];
|
||||
$p1 = $data['p1'];
|
||||
$p2 = $data['p2'];
|
||||
$pt = $data['pt'];
|
||||
$g = $data['g'];
|
||||
echo '<tr><td>'.$pos.'</td><td>'.$nome.'</td><td>'.$p1.'</td><td>'.$p2.'</td><td>'.$pt.'</td><td>'.$g.'</td></tr>';
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
/*
|
||||
database schema:
|
||||
CREATE TABLE punteggi (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
data_partita DATE NOT NULL,
|
||||
score1 INT NOT NULL,
|
||||
score2 INT NOT NULL,
|
||||
scoreT INT NOT NULL,
|
||||
nome VARCHAR(100) NOT NULL
|
||||
);
|
||||
*/
|
||||
|
||||
define('TABLE_NAME', 'punteggi_test'); // Cambia in 'punteggi_test' se necessario
|
||||
require 'db.php';
|
||||
|
||||
/**
|
||||
* Crea una mappa [ID => Posizione] basata sullo scoreT
|
||||
* Utile per sapere la posizione di una partita a prescindere dall'ordinamento visivo
|
||||
*/
|
||||
function getRankMap() {
|
||||
global $conn;
|
||||
$result = $conn->query("SELECT id FROM " . TABLE_NAME . " ORDER BY scoreT DESC");
|
||||
$orderedIds = array_column($result->fetch_all(MYSQLI_ASSOC), 'id');
|
||||
// array_flip trasforma [0 => id1, 1 => id2] in [id1 => 0, id2 => 1]
|
||||
$rankMap = array_flip($orderedIds);
|
||||
return $rankMap;
|
||||
}
|
||||
|
||||
function getSortedLeaderboardByDate() {
|
||||
global $conn;
|
||||
$result = $conn->query("SELECT * FROM " . TABLE_NAME . " ORDER BY data_partita DESC, id DESC");
|
||||
return $result->fetch_all(MYSQLI_ASSOC);
|
||||
}
|
||||
|
||||
function getSortedLeaderboardByScore() {
|
||||
global $conn;
|
||||
$result = $conn->query("SELECT * FROM " . TABLE_NAME . " ORDER BY scoreT DESC");
|
||||
return $result->fetch_all(MYSQLI_ASSOC);
|
||||
}
|
||||
|
||||
// Altre funzioni di utility se necessarie...
|
||||
function getTop10byScore() {
|
||||
global $conn;
|
||||
$result = $conn->query("SELECT * FROM " . TABLE_NAME . " ORDER BY scoreT DESC LIMIT 10");
|
||||
return $result->fetch_all(MYSQLI_ASSOC);
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
require 'db.php';
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$data_partita = $_POST['data_partita'];
|
||||
$score1 = $_POST['score1'];
|
||||
$score2 = $_POST['score2'];
|
||||
$scoreT = $_POST['scoreT'];
|
||||
$nome = $_POST['nome'];
|
||||
|
||||
$stmt = $conn->prepare("INSERT INTO punteggi_test (data_partita, score1, score2, scoreT, nome) VALUES (?, ?, ?, ?, ?)");
|
||||
$stmt->bind_param("siiis", $data_partita, $score1, $score2, $scoreT, $nome);
|
||||
$stmt->execute();
|
||||
$stmt->close();
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
// file per testare save_score.php
|
||||
// richiesta post a save_score.php con i seguenti dati:
|
||||
// nome: "Simone"
|
||||
// score1: 120
|
||||
// score2: 118
|
||||
// scoreT: 80
|
||||
$data = [
|
||||
'nome' => 'TEST',
|
||||
'score1' => 120,
|
||||
'score2' => 118,
|
||||
'scoreT' => 6611,
|
||||
'data_partita' => date("Y-m-d")
|
||||
];
|
||||
// richiesta post a save_score.php con i dati richiesti
|
||||
$options = [
|
||||
'http' => [
|
||||
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
|
||||
'method' => 'POST',
|
||||
'content' => http_build_query($data),
|
||||
],
|
||||
];
|
||||
$context = stream_context_create($options);
|
||||
$result = file_get_contents('http://localhost:8888/php/save_score.php', false, $context);
|
||||
if ($result === FALSE) {
|
||||
echo "Errore nella richiesta";
|
||||
} else {
|
||||
echo "Punteggio salvato con successo";
|
||||
}
|
||||
?>
|
||||
Reference in New Issue
Block a user