Files
giochino/index.html
T

401 lines
11 KiB
HTML

<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8">
<title>Windjammers Arcade</title>
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{background:#1a1a2e;display:flex;justify-content:center;align-items:center;min-height:100vh;font-family:Courier New,monospace}
#gc{position:relative;width:800px;height:450px;border:4px solid #e94560;border-radius:8px;overflow:hidden;background:#000}
canvas{position:absolute;top:0;left:0;width:100%;height:100%}
.overlay{position:absolute;top:0;left:0;width:100%;height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;background:rgba(0,0,0,.85);z-index:10}
.overlay.hidden{display:none}
.title{color:#e94560;font-size:42px;font-weight:bold;margin-bottom:8px}
.subtitle{color:#F39C12;font-size:16px;margin-bottom:25px}
.btn{display:block;padding:12px 24px;margin:6px;border:2px solid #555;border-radius:5px;background:#1a1a2e;color:#fff;font-size:16px;font-family:Courier New,monospace;cursor:pointer;transition:.2s;min-width:220px;text-align:center}
.btn:hover{border-color:#e94560;background:#222}
.hint{color:#666;font-size:11px;margin-top:15px}
#hud{position:absolute;top:10px;left:50%;transform:translateX(-50%);display:flex;gap:15px;z-index:5;pointer-events:none}
.score{background:rgba(0,0,0,.6);padding:6px 14px;border-radius:4px;border:2px solid #e94560;color:#fff;font-size:16px;font-weight:bold}
#msg{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);color:#fff;font-size:28px;font-weight:bold;text-shadow:2px 2px 4px #000;opacity:0;transition:.3s;pointer-events:none;z-index:5}
</style>
</head>
<body>
<div id="gc">
<canvas id="c" width="800" height="450"></canvas>
<div id="hud">
<div class="score" id="s1">P1: 0</div>
<div class="score" id="st">SET 1</div>
<div class="score" id="s2">CPU: 0</div>
</div>
<div id="msg"></div>
<div id="menu" class="overlay">
<div class="title">WINDJAMMERS</div>
<div class="subtitle">FLYING DISC ARCADE</div>
<button class="btn" onclick="startGame('normal')">VS CPU</button>
<button class="btn" onclick="showToast('2 giocatori - non ancora implementato')">2 GIOCATORI</button>
<button class="btn" onclick="showToast('Impostazioni - non ancora implementato')">IMPOSTAZIONI</button>
<div class="hint">Clicca i pulsanti per selezionare</div>
</div>
<div id="difficulty" class="overlay hidden">
<div class="title">VS CPU</div>
<div class="subtitle">Scegli la difficolta</div>
<button class="btn" onclick="startGame('easy')">FACILE</button>
<button class="btn" onclick="startGame('normal')">NORMALE</button>
<button class="btn" onclick="startGame('hard')">DIFFICILE</button>
<button class="btn" onclick="showMenu()" style="margin-top:20px;border-color:#666;color:#888">INDIETRO</button>
</div>
<div id="playing-ui" class="overlay hidden" style="background:rgba(0,0,0,.3);pointer-events:none">
<div class="hint" style="color:#fff">W/S = muovi | F = tiro | ESC = menu</div>
</div>
</div>
<script>
(function(){
"use strict";
// === ELEMENTI ===
var C = document.getElementById('c');
var X = C.getContext('2d');
var W = C.width, H = C.height;
var menuEl = document.getElementById('menu');
var diffEl = document.getElementById('difficulty');
var playEl = document.getElementById('playing-ui');
var msgEl = document.getElementById('msg');
// === STATO ===
var G = {
state: 'menu', // menu | countdown | playing | paused
score: [0, 0],
p1: null,
p2: null,
disc: null,
ai: null,
countdown: 0,
messageTimer: 0
};
var keys = {};
var lastKey = 'nessuno';
// === INPUT ===
document.addEventListener('keydown', function(e){
keys[e.code] = true;
lastKey = e.code;
if(e.code === 'Escape' && G.state === 'playing'){
showMenu();
}
});
document.addEventListener('keyup', function(e){
keys[e.code] = false;
});
// === FUNZIONI UI ===
function showMenu(){
G.state = 'menu';
menuEl.classList.remove('hidden');
diffEl.classList.add('hidden');
playEl.classList.add('hidden');
}
function showDifficulty(){
G.state = 'difficulty';
menuEl.classList.add('hidden');
diffEl.classList.remove('hidden');
playEl.classList.add('hidden');
}
function showPlaying(){
G.state = 'countdown';
G.countdown = 90;
menuEl.classList.add('hidden');
diffEl.classList.add('hidden');
playEl.classList.remove('hidden');
}
function showMessage(text, duration){
msgEl.textContent = text;
msgEl.style.opacity = '1';
G.messageTimer = duration || 60;
}
function showToast(text){
var toast = document.createElement('div');
toast.textContent = text;
toast.style.cssText = 'position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:rgba(0,0,0,.9);color:#fff;padding:15px 25px;border-radius:8px;border:2px solid #e94560;z-index:100';
document.body.appendChild(toast);
setTimeout(function(){ toast.remove(); }, 2000);
}
// === GIOCO ===
function Player(x, color, side){
this.x = x;
this.y = H / 2;
this.w = 25;
this.h = 70;
this.color = color;
this.side = side; // 'left' o 'right'
this.hasDisc = false;
this.score = 0;
}
Player.prototype.move = function(dy){
this.y += dy;
this.y = Math.max(60, Math.min(H - 60, this.y));
};
Player.prototype.draw = function(){
X.fillStyle = this.color;
X.fillRect(this.x - this.w/2, this.y - this.h/2, this.w, this.h);
// Testa
X.fillStyle = '#FDBCB4';
X.beginPath();
X.arc(this.x, this.y - this.h/2 - 10, 12, 0, Math.PI * 2);
X.fill();
// Braccio se ha il disco
if(this.hasDisc){
X.strokeStyle = this.color;
X.lineWidth = 4;
X.beginPath();
X.moveTo(this.x, this.y);
X.lineTo(this.x + (this.side === 'left' ? 20 : -20), this.y - 15);
X.stroke();
}
};
function Disc(){
this.x = W / 2;
this.y = H / 2;
this.vx = 0;
this.vy = 0;
this.r = 12;
this.inPlay = false;
this.owner = null;
}
Disc.prototype.throw = function(targetX, targetY){
var dx = targetX - this.x;
var dy = targetY - this.y;
var dist = Math.max(1, Math.sqrt(dx*dx + dy*dy));
this.vx = (dx / dist) * 7;
this.vy = (dy / dist) * 7;
this.inPlay = true;
this.owner = null;
};
Disc.prototype.update = function(){
if(!this.inPlay || this.owner) return;
this.x += this.vx;
this.y += this.vy;
// Rimbalzi
if(this.y < 60 || this.y > H - 60) this.vy *= -0.8;
// Rete (semplificata come zona centrale)
if(Math.abs(this.x - W/2) < 15 && this.y > 60 && this.y < H - 60){
this.vx *= -0.7;
this.x += (this.vx > 0 ? 1 : -1) * 2;
}
};
Disc.prototype.draw = function(){
if(this.owner) return; // nascosto se tenuto
X.fillStyle = '#F39C12';
X.beginPath();
X.ellipse(this.x, this.y, this.r, this.r * 0.4, 0, 0, Math.PI * 2);
X.fill();
X.strokeStyle = '#B7950B';
X.lineWidth = 2;
X.stroke();
};
// === CPU ===
function AI(difficulty){
this.difficulty = difficulty;
this.throwChance = difficulty === 'easy' ? 0.01 : (difficulty === 'hard' ? 0.04 : 0.025);
this.speed = difficulty === 'easy' ? 2 : (difficulty === 'hard' ? 4.5 : 3);
}
AI.prototype.update = function(player, disc){
if(player.hasDisc){
if(Math.random() < this.throwChance){
disc.throw(50 + Math.random() * 100, 80 + Math.random() * (H - 160));
player.hasDisc = false;
}
} else if(disc.inPlay && !disc.owner){
// Muovi verso il disco
var dy = disc.y - player.y;
if(Math.abs(dy) > 10){
player.move(Math.sign(dy) * this.speed);
}
}
};
// === START GAME ===
window.startGame = function(difficulty){
showPlaying();
G.state = 'countdown';
G.countdown = 90;
G.score = [0, 0];
G.p1 = new Player(150, '#E74C3C', 'left');
G.p2 = new Player(650, '#3498DB', 'right');
G.disc = new Disc();
G.ai = new AI(difficulty);
G.p1.hasDisc = true;
showMessage('PREPARATI!');
};
function resetPoint(){
G.p1.y = H / 2;
G.p2.y = H / 2;
G.disc.x = W / 2;
G.disc.y = H / 2;
G.disc.vx = 0;
G.disc.vy = 0;
G.disc.inPlay = false;
G.disc.owner = null;
// Chi serve?
if(Math.random() < 0.5){
G.p1.hasDisc = true;
G.disc.x = G.p1.x + 15;
G.disc.y = G.p1.y;
} else {
G.p2.hasDisc = true;
G.disc.x = G.p2.x - 15;
G.disc.y = G.p2.y;
}
}
// === LOOP PRINCIPALE ===
function loop(){
try{
X.clearRect(0, 0, W, H);
// SFONDO
var grad = X.createLinearGradient(0, 0, 0, 60);
grad.addColorStop(0, '#4A90D9');
grad.addColorStop(1, '#87CEEB');
X.fillStyle = grad;
X.fillRect(0, 0, W, 60);
X.fillStyle = '#7DCEA0';
X.fillRect(30, 60, W - 60, H - 120);
X.strokeStyle = '#fff';
X.lineWidth = 3;
X.strokeRect(30, 60, W - 60, H - 120);
// RETE
X.fillStyle = '#fff';
X.fillRect(W/2 - 5, 60, 10, H - 120);
// PORTE
X.fillStyle = '#E74C3C';
X.globalAlpha = 0.6;
X.fillRect(5, H/2 - 50, 25, 100);
X.globalAlpha = 1;
X.fillStyle = '#3498DB';
X.globalAlpha = 0.6;
X.fillRect(W - 30, H/2 - 50, 25, 100);
X.globalAlpha = 1;
// COUNTDOWN
if(G.state === 'countdown'){
G.countdown--;
G.p1.draw();
G.p2.draw();
G.disc.draw();
X.fillStyle = '#fff';
X.font = 'bold 50px Courier New';
X.textAlign = 'center';
X.fillText(Math.ceil(G.countdown / 30), W/2, H/2);
if(G.countdown <= 0){
G.state = 'playing';
showMessage('VIA!');
}
}
// GIOCO
if(G.state === 'playing'){
// Input P1
var p1Speed = 5;
if(keys['KeyW']) G.p1.move(-p1Speed);
if(keys['KeyS']) G.p1.move(p1Speed);
if(keys['KeyF'] && G.p1.hasDisc){
G.disc.throw(W - 50, 80 + Math.random() * (H - 160));
G.p1.hasDisc = false;
}
// CPU
G.ai.update(G.p2, G.disc);
// Disco
G.disc.update();
// Disco segue possessore
if(G.disc.owner === G.p1){
G.disc.x = G.p1.x + 15;
G.disc.y = G.p1.y;
} else if(G.disc.owner === G.p2){
G.disc.x = G.p2.x - 15;
G.disc.y = G.p2.y;
}
// Cattura
if(G.disc.inPlay && !G.disc.owner){
var d1 = Math.hypot(G.disc.x - G.p1.x, G.disc.y - G.p1.y);
var d2 = Math.hypot(G.disc.x - G.p2.x, G.disc.y - G.p2.y);
if(d1 < 30){ G.p1.hasDisc = true; G.disc.inPlay = false; }
if(d2 < 30){ G.p2.hasDisc = true; G.disc.inPlay = false; }
}
// Gol
if(G.disc.x < 30){
G.score[1]++;
showMessage('CPU SEGNA!');
resetPoint();
} else if(G.disc.x > W - 30){
G.score[0]++;
showMessage('P1 SEGNA!');
resetPoint();
}
// Disegna
G.p1.draw();
G.p2.draw();
G.disc.draw();
}
// Messaggio
if(G.messageTimer > 0){
G.messageTimer--;
if(G.messageTimer <= 0) msgEl.style.opacity = '0';
}
// HUD
document.getElementById('s1').textContent = 'P1: ' + G.score[0];
document.getElementById('s2').textContent = 'CPU: ' + G.score[1];
} catch(err){
X.fillStyle = '#ff0000';
X.font = '14px Courier New';
X.textAlign = 'left';
X.fillText('ERRORE: ' + err.message, 10, 20);
}
requestAnimationFrame(loop);
}
// Avvia
loop();
})();
</script>
</body>
</html>