Pong för tanter

<!DOCTYPE html> <html> <head> <title>Pong från AINNOVA</title> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> <style> body { margin: 0; padding: 10px; background: #f0f4f8; /* Ljus och vänlig bakgrundsfärg / font-family: Arial, sans-serif; display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 100vh; touch-action: manipulation; / Tillåt vissa systemgester utanför canvas / overflow: hidden; / Förhindra scrollbars om innehållet skulle råka bli för stort / } .game-container { position: relative; width: 100%; max-width: 600px; / Maxbredd för spelet på större skärmar / display: flex; flex-direction: column; align-items: center; } .logo-small { width: 80px; height: auto; margin-bottom: 5px; } canvas { border: 2px solid #007BBF; / Tydlig blå ram / background: #000; / Klassisk svart bakgrund för Pong / width: 100%; max-height: 70vh; / Begränsa höjden för att passa på skärmen / touch-action: none; / Inaktivera webbläsarens touch-gester på canvas (t.ex. scroll) / } #startScreen { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); background: rgba(255, 255, 255, 0.95); / Lätt genomskinlig vit bakgrund / padding: 15px; border-radius: 8px; text-align: center; width: 90%; max-width: 400px; / Maxbredd för startrutan / box-shadow: 0 2px 10px rgba(0,0,0,0.2); z-index: 10; / Se till att startskärmen är överst / } .button-container { display: flex; flex-direction: column; / Knappar under varandra på små skärmar / width: 100%; margin-top: 10px; } button { padding: 12px; / Lite större knappar för enklare tryck / margin: 5px 0; background: #007BBF; / Blå bakgrundsfärg / color: white; border: none; border-radius: 5px; font-size: 16px; / Tydlig textstorlek / width: 100%; cursor: pointer; transition: background-color 0.3s; / Mjuk övergång vid hover / } button:hover { background: #005FA3; / Mörkare blå vid hover / } .score-display { font-size: 22px; / Större poängtext / margin: 8px 0; font-weight: bold; color: #007BBF; } h1 { / Stil för huvudrubrik på startskärmen / font-size: 22px; color: #333; margin-bottom: 10px; } h2 { / Stil för spelets titel under loggan / font-size: 18px; margin: 5px 0 10px 0; / Lite mer marginal under titeln / color: #333; text-align: center; } #status { color: #007BBF; font-size: 16px; margin-top: 8px; text-align: center; min-height: 20px; / Ge lite utrymme även om texten är tom / } / Media query för större skärmar, t.ex. surfplattor och datorer / @media (min-width: 400px) { .button-container { flex-direction: row; / Knappar bredvid varandra / justify-content: center; } button { margin: 0 5px; width: auto; / Automatisk bredd baserat på innehåll / min-width: 120px; / Minsta bredd för knapparna */ } } </style> </head> <body>

<div class="game-container"> <img class="logo-small" src="https://valingeveckan.wordpress.com/wp-content/uploads/2025/04/namnlos-design-4-1.png" alt="AINNOVA Logo"> <h2>Pong – En demo från AINNOVA</h2> <div class="score-display" id="scoreDisplay">0 - 0</div> <canvas id="pong"></canvas> <div id="status"></div>

<div id="startScreen">
    <h1>Välkommen till Pong!</h1>
    <p>På dator: Använd W/S eller upp/ner-pil för vänster paddel.<br>
       På mobil: Tryck och dra upp/ner på vänster sida.<br>
       Två spelare? Höger paddel använder I/K (dator) eller dra på höger sida.<br>
       Mot datorn? Din paddel är större för att göra det lättare!<br>
       Första till 5 poäng vinner!</p>
    <div class="button-container">
        <button onclick="startGame(false)">2 Spelare</button>
        <button onclick="startGame(true)">Mot datorn</button>
    </div>
</div>

</div>

<script> const canvas = document.getElementById('pong'); const ctx = canvas.getContext('2d'); const startScreen = document.getElementById('startScreen'); const scoreDisplay = document.getElementById('scoreDisplay'); const status = document.getElementById('status');

// Spelinställningar const PADDLE_WIDTH = 10; // Basbredd för paddlar const WINNING_SCORE = 5; let scale = 1; // Skalningsfaktor för responsivitet

// Spelobjekt let leftPaddle = { x: 0, y: 0, height: 80, speed: 5 }; // Vänster paddel (Spelare 1 / "Tanten") let rightPaddle = { x: 0, y: 0, height: 60, speed: 4 }; // Höger paddel (Spelare 2 / Dator) let ball = { x: 0, y: 0, size: 8, dx: 4, dy: 4 }; // Bollens egenskaper

let leftScore = 0; let rightScore = 0; let gameState = 'start'; // Möjliga tillstånd: 'start', 'playing', 'paused', 'gameover' let vsComputer = false; // Spelar man mot datorn? let animationFrameId = null; // För att kunna avbryta gameLoop

let lastTime = 0; const frameRate = 60; // Önskad bildfrekvens const frameDelay = 1000 / frameRate; // Tid i ms per bildruta

// Tangentnedtryckningar let keys = { up: false, // W eller Pil Upp down: false, // S eller Pil Ned i: false, // I (för spelare 2) k: false // K (för spelare 2) };

// Initiera spelet function initGame() { setCanvasSize(); // Anpassa canvas storlek direkt window.addEventListener('resize', setCanvasSize); // Anpassa vid fönsterstorleksändring

// Tangentbordsstyrning
document.addEventListener('keydown', function(e) {
    const key = e.key.toLowerCase();
    if (gameState === 'playing' || gameState === 'paused') {
        if (key === 'w' || key === 'arrowup') { keys.up = true; e.preventDefault(); }
        if (key === 's' || key === 'arrowdown') { keys.down = true; e.preventDefault(); }
        if (key === 'i') { keys.i = true; e.preventDefault(); }
        if (key === 'k') { keys.k = true; e.preventDefault(); }

        if (key === ' ') { // Mellanslag för paus/fortsätt
            e.preventDefault();
            if (gameState === 'playing') {
                gameState = 'paused';
                status.textContent = 'Pausad. Tryck mellanslag eller på skärmen för att fortsätta.';
            } else if (gameState === 'paused') {
                gameState = 'playing';
                status.textContent = 'Spelet fortsätter!';
                lastTime = performance.now(); // Återställ tiden för jämnare återupptagning
                gameLoop(lastTime);
            }
        }
    }
});

document.addEventListener('keyup', function(e) {
    const key = e.key.toLowerCase();
    if (key === 'w' || key === 'arrowup') keys.up = false;
    if (key === 's' || key === 'arrowdown') keys.down = false;
    if (key === 'i') keys.i = false;
    if (key === 'k') keys.k = false;
});

// Touchkontroller
canvas.addEventListener('touchstart', handleTouch, { passive: false });
canvas.addEventListener('touchmove', handleTouch, { passive: false });
// 'touchend' behövs inte för kontinuerlig rörelse baserat på 'touchmove'

// Muskontroller (bra för testning på dator och för de som föredrar mus)
canvas.addEventListener('mousedown', handleMouse, { passive: false });
canvas.addEventListener('mousemove', handleMouse, { passive: false });

}

function handleTouch(e) { e.preventDefault(); // Förhindra standard touch-beteenden som scroll if (gameState === 'paused') { gameState = 'playing'; status.textContent = 'Spelet fortsätter!'; lastTime = performance.now(); gameLoop(lastTime); return; } if (gameState !== 'playing') return;

const touch = e.touches[0];
const rect = canvas.getBoundingClientRect();
if (rect.width === 0 || rect.height === 0) return; // Undvik division med noll

// Normalisera touch-koordinater till canvas-koordinater
const touchX = (touch.clientX - rect.left) / rect.width * canvas.width;
const touchY = (touch.clientY - rect.top) / rect.height * canvas.height;

// Vänster halva av skärmen styr vänster paddel
if (touchX < canvas.width / 2) {
    leftPaddle.y = touchY - leftPaddle.height / 2;
} else if (!vsComputer) { // Höger halva styr höger paddel om det är två spelare
    rightPaddle.y = touchY - rightPaddle.height / 2;
}

// Håll paddlarna inom canvas
leftPaddle.y = Math.max(0, Math.min(canvas.height - leftPaddle.height, leftPaddle.y));
if (!vsComputer) {
    rightPaddle.y = Math.max(0, Math.min(canvas.height - rightPaddle.height, rightPaddle.y));
}

}

function handleMouse(e) { // Muskontroller fungerar bara om musknappen är nedtryckt (simulerar "drag") // och spelet är igång. e.buttons === 1 kollar om vänster musknapp är nedtryckt. if (gameState !== 'playing' || e.buttons !== 1) return; e.preventDefault();

const rect = canvas.getBoundingClientRect();
if (rect.width === 0 || rect.height === 0) return;

const mouseX = (e.clientX - rect.left) / rect.width * canvas.width;
const mouseY = (e.clientY - rect.top) / rect.height * canvas.height;

if (mouseX < canvas.width / 2) {
    leftPaddle.y = mouseY - leftPaddle.height / 2;
} else if (!vsComputer) {
    rightPaddle.y = mouseY - rightPaddle.height / 2;
}

leftPaddle.y = Math.max(0, Math.min(canvas.height - leftPaddle.height, leftPaddle.y));
if (!vsComputer) {
    rightPaddle.y = Math.max(0, Math.min(canvas.height - rightPaddle.height, rightPaddle.y));
}