Private
Public Access
1
0
Files
it232Abschied/static/js/logic.js
Sebastian Unterschütz 0412168c4e
Some checks failed
Dynamic Branch Deploy / build-and-deploy (push) Has been cancelled
better deploy
2025-11-27 19:42:08 +01:00

172 lines
5.5 KiB
JavaScript

function updateGameLogic() {
// 1. Input Logging (Ducken)
if (isCrouching) {
inputLog.push({ t: currentTick - lastSentTick, act: "DUCK" });
}
// 2. Geschwindigkeit (Basiert auf ZEIT/Ticks, nicht Score!)
let currentSpeed = 5 + (currentTick / 3000.0) * 0.5;
if (currentSpeed > 12.0) currentSpeed = 12.0;
// 3. Spieler Physik & Größe
const originalHeight = 50;
const crouchHeight = 25;
player.h = isCrouching ? crouchHeight : originalHeight;
let drawY = isCrouching ? player.y + (originalHeight - crouchHeight) : player.y;
player.vy += GRAVITY;
if (isCrouching && !player.grounded) player.vy += 2.0; // Fast Fall
player.y += player.vy;
if (player.y + originalHeight >= GROUND_Y) {
player.y = GROUND_Y - originalHeight;
player.vy = 0;
player.grounded = true;
} else {
player.grounded = false;
}
// 4. Hindernisse Bewegen & Kollision
let nextObstacles = [];
for (let obs of obstacles) {
obs.x -= currentSpeed;
// Aufräumen, wenn links raus
if (obs.x + obs.def.width < -50.0) continue;
// --- PASSED CHECK (Wichtig!) ---
// Wenn das Hindernis den Spieler schon passiert hat, ignorieren wir Kollisionen.
// Das verhindert "Geister-Treffer" von hinten durch CCD.
const paddingX = 10;
const realRightEdge = obs.x + obs.def.width - paddingX;
// Spieler ist bei 50. Wir geben 5px Puffer.
if (realRightEdge < 55) {
nextObstacles.push(obs); // Behalten, aber keine Kollisionsprüfung mehr
continue;
}
// -------------------------------
// Kollisionsprüfung
const playerHitbox = { x: player.x, y: drawY, w: player.w, h: player.h };
if (checkCollision(playerHitbox, obs)) {
// A. COIN
if (obs.def.type === "coin") {
score += 2000;
continue; // Entfernen
}
// B. POWERUP
else if (obs.def.type === "powerup") {
if (obs.def.id === "p_god") godModeLives = 3;
if (obs.def.id === "p_bat") hasBat = true;
if (obs.def.id === "p_boot") bootTicks = 600;
lastPowerupTick = currentTick; // Für Sync merken
continue; // Entfernen
}
// C. GEGNER
else {
if (hasBat && obs.def.type === "teacher") {
hasBat = false;
continue; // Zerstört
}
if (godModeLives > 0) {
godModeLives--;
continue; // Geschützt
}
player.color = "darkred";
if (!isGameOver) {
sendChunk();
gameOver("Kollision");
}
}
}
nextObstacles.push(obs);
}
obstacles = nextObstacles;
// 5. Spawning (Zeitbasiert & Synchron)
// Fallback für Init
if (typeof nextSpawnTick === 'undefined' || nextSpawnTick === 0) {
nextSpawnTick = currentTick + 50;
}
if (currentTick >= nextSpawnTick && gameConfig) {
// A. Nächsten Termin berechnen
const gapPixel = Math.floor(400 + rng.nextRange(0, 500));
const ticksToWait = Math.floor(gapPixel / currentSpeed);
nextSpawnTick = currentTick + ticksToWait;
// B. Position setzen (Fix rechts außen)
let spawnX = GAME_WIDTH + 50;
// C. Objekt auswählen
const isBossPhase = (currentTick % 1500) > 1200;
let possibleObs = [];
gameConfig.obstacles.forEach(def => {
if (isBossPhase) {
if (def.id === "principal" || def.id === "trashcan") possibleObs.push(def);
} else {
if (def.id === "principal") return;
// Eraser erst ab Tick 3000
if (def.id === "eraser" && currentTick < 3000) return;
possibleObs.push(def);
}
});
let def = rng.pick(possibleObs);
// RNG Sync: Speech
let speech = null;
if (def && def.canTalk) {
if (rng.nextFloat() > 0.7) speech = rng.pick(def.speechLines);
}
// RNG Sync: Powerup Rarity
if (def && def.type === "powerup") {
if (rng.nextFloat() > 0.1) def = null;
}
if (def) {
const yOffset = def.yOffset || 0;
obstacles.push({
x: spawnX,
y: GROUND_Y - def.height - yOffset,
def: def,
speech: speech
});
}
}
}
function checkCollision(p, obs) {
const paddingX = 10;
const paddingY_Top = (obs.def.type === "teacher") ? 25 : 10;
const paddingY_Bottom = 5;
// Speed-basierte Hitbox-Erweiterung (CCD)
// Wir schätzen den Speed hier, damit er ungefähr dem Server entspricht
let currentSpeed = 5 + (currentTick / 3000.0) * 0.5;
if (currentSpeed > 12.0) currentSpeed = 12.0;
const pLeft = p.x + paddingX;
const pRight = p.x + p.w - paddingX;
const pTop = p.y + paddingY_Top;
const pBottom = p.y + p.h - paddingY_Bottom;
const oLeft = obs.x + paddingX;
// Wir erweitern die Hitbox nach rechts um die Geschwindigkeit,
// um schnelle Durchschüsse zu verhindern.
const oRight = obs.x + obs.def.width - paddingX + currentSpeed;
const oTop = obs.y + paddingY_Top;
const oBottom = obs.y + obs.def.height - paddingY_Bottom;
return (pRight > oLeft && pLeft < oRight && pBottom > oTop && pTop < oBottom);
}