better deploy
Some checks failed
Dynamic Branch Deploy / build-and-deploy (push) Has been cancelled
Some checks failed
Dynamic Branch Deploy / build-and-deploy (push) Has been cancelled
This commit is contained in:
@@ -10,7 +10,7 @@ const CHUNK_SIZE = 60;
|
||||
const TARGET_FPS = 60;
|
||||
const MS_PER_TICK = 1000 / TARGET_FPS;
|
||||
|
||||
const DEBUG_SYNC = false;
|
||||
const DEBUG_SYNC = true;
|
||||
const SYNC_TOLERANCE = 5.0;
|
||||
|
||||
// RNG Klasse
|
||||
|
||||
@@ -5,26 +5,20 @@ function updateGameLogic() {
|
||||
}
|
||||
|
||||
// 2. Geschwindigkeit (Basiert auf ZEIT/Ticks, nicht Score!)
|
||||
// Formel: Start bei 5, erhöht sich alle 3000 Ticks (ca. 50 Sek) um 0.5
|
||||
let currentSpeed = 5 + (currentTick / 3000.0) * 0.5;
|
||||
if (currentSpeed > 20.0) currentSpeed = 20.0; // Max Speed Cap
|
||||
if (currentSpeed > 12.0) currentSpeed = 12.0;
|
||||
|
||||
// 3. Spieler Physik & Größe
|
||||
const originalHeight = 50;
|
||||
const crouchHeight = 25;
|
||||
|
||||
player.h = isCrouching ? crouchHeight : originalHeight;
|
||||
|
||||
// Visuelle Korrektur Y (damit Füße am Boden bleiben)
|
||||
let drawY = isCrouching ? player.y + (originalHeight - crouchHeight) : player.y;
|
||||
|
||||
// Schwerkraft
|
||||
player.vy += GRAVITY;
|
||||
if (isCrouching && !player.grounded) player.vy += 2.0; // Schneller fallen (Fast Fall)
|
||||
|
||||
if (isCrouching && !player.grounded) player.vy += 2.0; // Fast Fall
|
||||
player.y += player.vy;
|
||||
|
||||
// Boden-Kollision
|
||||
if (player.y + originalHeight >= GROUND_Y) {
|
||||
player.y = GROUND_Y - originalHeight;
|
||||
player.vy = 0;
|
||||
@@ -35,43 +29,54 @@ function updateGameLogic() {
|
||||
|
||||
// 4. Hindernisse Bewegen & Kollision
|
||||
let nextObstacles = [];
|
||||
let rightmostX = 0;
|
||||
|
||||
for (let obs of obstacles) {
|
||||
obs.x -= currentSpeed;
|
||||
|
||||
// Hitbox für aktuellen Frame
|
||||
// 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. MÜNZE (+2000 Punkte)
|
||||
// A. COIN
|
||||
if (obs.def.type === "coin") {
|
||||
score += 2000;
|
||||
continue; // Entfernen (Eingesammelt)
|
||||
continue; // Entfernen
|
||||
}
|
||||
// B. POWERUP (Aktivieren)
|
||||
// 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;
|
||||
continue; // Entfernen (Eingesammelt)
|
||||
lastPowerupTick = currentTick; // Für Sync merken
|
||||
continue; // Entfernen
|
||||
}
|
||||
// C. GEGNER / HINDERNIS
|
||||
// C. GEGNER
|
||||
else {
|
||||
// Schläger vs Lehrer
|
||||
if (hasBat && obs.def.type === "teacher") {
|
||||
hasBat = false; // Schläger kaputt
|
||||
continue; // Lehrer weg
|
||||
hasBat = false;
|
||||
continue; // Zerstört
|
||||
}
|
||||
// Godmode vs Alles
|
||||
if (godModeLives > 0) {
|
||||
godModeLives--; // Ein Leben weg
|
||||
continue; // Hindernis ignoriert
|
||||
godModeLives--;
|
||||
continue; // Geschützt
|
||||
}
|
||||
|
||||
// Tod
|
||||
player.color = "darkred";
|
||||
if (!isGameOver) {
|
||||
sendChunk();
|
||||
@@ -80,53 +85,54 @@ function updateGameLogic() {
|
||||
}
|
||||
}
|
||||
|
||||
// Objekt behalten wenn noch im Bild
|
||||
if (obs.x + obs.def.width > -100) {
|
||||
nextObstacles.push(obs);
|
||||
if (obs.x + obs.def.width > rightmostX) rightmostX = obs.x + obs.def.width;
|
||||
}
|
||||
nextObstacles.push(obs);
|
||||
}
|
||||
obstacles = nextObstacles;
|
||||
|
||||
// 5. Spawning (Basiert auf ZEIT/Ticks)
|
||||
if (rightmostX < GAME_WIDTH - 10 && gameConfig) {
|
||||
const gap = Math.floor(400 + rng.nextRange(0, 500));
|
||||
let spawnX = rightmostX + gap;
|
||||
if (spawnX < GAME_WIDTH) spawnX = GAME_WIDTH;
|
||||
// 5. Spawning (Zeitbasiert & Synchron)
|
||||
|
||||
// Boss Phase abhängig von Zeit (nicht Score, wegen Münzen!)
|
||||
// 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) {
|
||||
// Boss Phase: Nur Principal und Trashcan
|
||||
if (def.id === "principal" || def.id === "trashcan") possibleObs.push(def);
|
||||
} else {
|
||||
// Normal Phase
|
||||
if (def.id === "principal") return;
|
||||
// Eraser erst ab Tick 3000 (ca. 50 Sek)
|
||||
// Eraser erst ab Tick 3000
|
||||
if (def.id === "eraser" && currentTick < 3000) return;
|
||||
possibleObs.push(def);
|
||||
}
|
||||
});
|
||||
|
||||
// Zufälliges Objekt wählen
|
||||
let def = rng.pick(possibleObs);
|
||||
|
||||
// RNG Sync: Sprechblasen
|
||||
// RNG Sync: Speech
|
||||
let speech = null;
|
||||
if (def && def.canTalk) {
|
||||
// WICHTIG: Reihenfolge muss 1:1 wie in Go sein
|
||||
if (rng.nextFloat() > 0.7) speech = rng.pick(def.speechLines);
|
||||
}
|
||||
|
||||
// RNG Sync: Powerup Seltenheit (nur 10% Chance)
|
||||
// RNG Sync: Powerup Rarity
|
||||
if (def && def.type === "powerup") {
|
||||
if (rng.nextFloat() > 0.1) def = null;
|
||||
}
|
||||
|
||||
// Hinzufügen
|
||||
if (def) {
|
||||
const yOffset = def.yOffset || 0;
|
||||
obstacles.push({
|
||||
@@ -141,23 +147,12 @@ function updateGameLogic() {
|
||||
|
||||
function checkCollision(p, obs) {
|
||||
const paddingX = 10;
|
||||
|
||||
|
||||
const realRightEdge = obs.x + obs.def.width - paddingX;
|
||||
|
||||
if (realRightEdge < p.x + 5) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
const paddingY_Top = (obs.def.type === "teacher") ? 25 : 10;
|
||||
const paddingY_Bottom = 5;
|
||||
|
||||
// Geschwindigkeit schätzen (oder global holen) für CCD
|
||||
let currentSpeed = 5 + (score / 5000.0) * 0.5; // /5000 weil score hier /10 ist?
|
||||
// Moment, in main.js ist 'score' der rohe Wert. Also /500.
|
||||
// Da wir score global haben:
|
||||
currentSpeed = 5 + (score / 500.0) * 0.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;
|
||||
@@ -166,8 +161,10 @@ function checkCollision(p, obs) {
|
||||
const pBottom = p.y + p.h - paddingY_Bottom;
|
||||
|
||||
const oLeft = obs.x + paddingX;
|
||||
// CCD Erweiterung
|
||||
// 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;
|
||||
|
||||
|
||||
@@ -42,6 +42,13 @@ async function sendChunk() {
|
||||
}
|
||||
}
|
||||
|
||||
// Sync Spawning Timer
|
||||
if (data.nextSpawnTick) {
|
||||
if (Math.abs(nextSpawnTick - data.nextSpawnTick) > 5) {
|
||||
nextSpawnTick = data.nextSpawnTick;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (data.status === "dead") {
|
||||
|
||||
@@ -25,6 +25,7 @@ let maxRawBgIndex = 0;
|
||||
let lastTime = 0;
|
||||
let accumulator = 0;
|
||||
let lastPowerupTick = -9999;
|
||||
let nextSpawnTick = 0;
|
||||
|
||||
// Grafiken
|
||||
let sprites = {};
|
||||
|
||||
Reference in New Issue
Block a user