Private
Public Access
1
0
Files
it232Abschied/static/js/render.js
Sebastian Unterschütz 93491bd794
All checks were successful
Dynamic Branch Deploy / build-and-deploy (push) Successful in 2m25s
bug fixes
2025-11-25 21:31:04 +01:00

157 lines
5.2 KiB
JavaScript

function resize() {
// 1. INTERNE SPIEL-AUFLÖSUNG ERZWINGEN
// Das behebt den "Zoom/Nur Ecke sichtbar" Fehler
canvas.width = GAME_WIDTH; // 800
canvas.height = GAME_HEIGHT; // 400
// 2. Verfügbaren Platz im Browser berechnen (Minus etwas Rand)
const windowWidth = window.innerWidth - 20;
const windowHeight = window.innerHeight - 20;
const targetRatio = GAME_WIDTH / GAME_HEIGHT; // 2.0
const windowRatio = windowWidth / windowHeight;
let finalWidth, finalHeight;
// 3. Letterboxing berechnen
if (windowRatio < targetRatio) {
// Screen ist schmaler (z.B. Handy Portrait) -> Breite limitiert
finalWidth = windowWidth;
finalHeight = windowWidth / targetRatio;
} else {
// Screen ist breiter (z.B. Desktop) -> Höhe limitiert
finalHeight = windowHeight;
finalWidth = finalHeight * targetRatio;
}
// 4. Größe auf den CONTAINER anwenden
if (container) {
container.style.width = `${Math.floor(finalWidth)}px`;
container.style.height = `${Math.floor(finalHeight)}px`;
}
// Hinweis: Wir setzen KEINE style.width/height auf das Canvas Element selbst.
// Das Canvas erbt "width: 100%; height: 100%" vom CSS und füllt den Container.
}
// Event Listener
window.addEventListener('resize', resize);
// Einmal sofort ausführen
resize();
// --- DRAWING ---
function drawGame() {
// 1. Alles löschen
ctx.clearRect(0, 0, GAME_WIDTH, GAME_HEIGHT);
// --- HINTERGRUND (Level-Wechsel) ---
let currentBg = null;
// Haben wir Hintergründe geladen?
if (bgSprites.length > 0) {
// Wechsel alle 2000 Punkte (Server-Score) = 200 Punkte (Anzeige)
const changeInterval = 2000;
// Berechne Index: 0-1999 -> 0, 2000-3999 -> 1, etc.
// Das % (Modulo) sorgt dafür, dass es wieder von vorne anfängt, wenn die Bilder ausgehen
const bgIndex = Math.floor(score / changeInterval) % bgSprites.length;
currentBg = bgSprites[bgIndex];
}
// Zeichnen (wenn Bild geladen und nicht kaputt)
if (currentBg && currentBg.complete && currentBg.naturalHeight !== 0) {
// Streckt das Bild exakt auf die Spielgröße (800x400)
ctx.drawImage(currentBg, 0, 0, GAME_WIDTH, GAME_HEIGHT);
} else {
// Fallback: Hellgrau, falls Bild fehlt
ctx.fillStyle = "#f0f0f0";
ctx.fillRect(0, 0, GAME_WIDTH, GAME_HEIGHT);
}
// --- BODEN ---
// Halb-transparent, damit er über dem Hintergrund liegt
ctx.fillStyle = "rgba(60, 60, 60, 0.8)";
ctx.fillRect(0, GROUND_Y, GAME_WIDTH, 50);
// --- HINDERNISSE ---
obstacles.forEach(obs => {
const img = sprites[obs.def.id];
// Prüfen ob Bild geladen ist
if (img && img.complete && img.naturalHeight !== 0) {
ctx.drawImage(img, obs.x, obs.y, obs.def.width, obs.def.height);
} else {
// Fallback Farbe (Münzen Gold, Rest aus Config)
if (obs.def.type === "coin") ctx.fillStyle = "gold";
else ctx.fillStyle = obs.def.color || "red";
ctx.fillRect(obs.x, obs.y, obs.def.width, obs.def.height);
}
if(obs.speech) drawSpeechBubble(obs.x, obs.y, obs.speech);
});
/*
// --- DEBUG RAHMEN (Server Hitboxen) ---
// Grün im Spiel, Rot bei Tod
ctx.strokeStyle = isGameOver ? "red" : "lime";
ctx.lineWidth = 2;
serverObstacles.forEach(srvObs => {
ctx.strokeRect(srvObs.x, srvObs.y, srvObs.w, srvObs.h);
});
*/
// --- SPIELER ---
// Y-Position und Höhe anpassen für Ducken
const drawY = isCrouching ? player.y + 25 : player.y;
const drawH = isCrouching ? 25 : 50;
if (playerSprite.complete && playerSprite.naturalHeight !== 0) {
ctx.drawImage(playerSprite, player.x, drawY, player.w, drawH);
} else {
ctx.fillStyle = player.color;
ctx.fillRect(player.x, drawY, player.w, drawH);
}
// --- HUD (Powerup Status oben links) ---
if (isGameRunning && !isGameOver) {
ctx.fillStyle = "black";
ctx.font = "bold 10px monospace";
ctx.textAlign = "left";
let statusText = "";
if(godModeLives > 0) statusText += `🛡️ x${godModeLives} `;
if(hasBat) statusText += `⚾ BAT `;
if(bootTicks > 0) statusText += `👟 ${(bootTicks/60).toFixed(1)}s`;
// Drift Info (nur wenn Objekte da sind)
if (obstacles.length > 0 && serverObstacles.length > 0) {
const drift = Math.abs(obstacles[0].x - serverObstacles[0].x).toFixed(1);
// statusText += ` | Drift: ${drift}px`; // Einkommentieren für Debugging
}
if(statusText !== "") {
ctx.fillText(statusText, 10, 40);
}
}
// --- GAME OVER OVERLAY ---
if (isGameOver) {
// Dunkler Schleier über alles
ctx.fillStyle = "rgba(0,0,0,0.7)";
ctx.fillRect(0,0,GAME_WIDTH, GAME_HEIGHT);
}
}
// Sprechblasen Helper
function drawSpeechBubble(x, y, text) {
const bX = x-20; const bY = y-40; const bW = 120; const bH = 30;
ctx.fillStyle="white"; ctx.fillRect(bX,bY,bW,bH);
ctx.strokeRect(bX,bY,bW,bH);
ctx.fillStyle="black"; ctx.font="10px Arial"; ctx.textAlign="center";
ctx.fillText(text, bX+bW/2, bY+20);
}