big refactor
Some checks failed
Dynamic Branch Deploy / build-and-deploy (push) Failing after 48s
Some checks failed
Dynamic Branch Deploy / build-and-deploy (push) Failing after 48s
This commit is contained in:
107
static/js/render.js
Normal file
107
static/js/render.js
Normal file
@@ -0,0 +1,107 @@
|
||||
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() {
|
||||
// Alles löschen
|
||||
ctx.clearRect(0, 0, GAME_WIDTH, GAME_HEIGHT);
|
||||
|
||||
// Background
|
||||
if (bgSprite.complete && bgSprite.naturalHeight !== 0) {
|
||||
// Hintergrundbild exakt auf 800x400 skalieren
|
||||
ctx.drawImage(bgSprite, 0, 0, GAME_WIDTH, GAME_HEIGHT);
|
||||
} else {
|
||||
// Fallback Farbe
|
||||
ctx.fillStyle = "#f0f0f0";
|
||||
ctx.fillRect(0, 0, GAME_WIDTH, GAME_HEIGHT);
|
||||
}
|
||||
|
||||
// Boden
|
||||
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];
|
||||
if (img) {
|
||||
ctx.drawImage(img, obs.x, obs.y, obs.def.width, obs.def.height);
|
||||
} else {
|
||||
ctx.fillStyle = obs.def.color;
|
||||
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)
|
||||
ctx.strokeStyle = isGameOver ? "red" : "lime";
|
||||
ctx.lineWidth = 2;
|
||||
serverObstacles.forEach(srvObs => {
|
||||
ctx.strokeRect(srvObs.x, srvObs.y, srvObs.w, srvObs.h);
|
||||
});
|
||||
|
||||
// Spieler
|
||||
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);
|
||||
}
|
||||
|
||||
// Game Over Overlay (Dunkelheit)
|
||||
if (isGameOver) {
|
||||
ctx.fillStyle = "rgba(0,0,0,0.7)";
|
||||
ctx.fillRect(0,0,GAME_WIDTH, GAME_HEIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
Reference in New Issue
Block a user