189 lines
5.9 KiB
JavaScript
189 lines
5.9 KiB
JavaScript
function updateGameLogic() {
|
|
let currentSpeed = BASE_SPEED + (currentTick / 1000.0) * 1.5;
|
|
if (currentSpeed > 36.0) currentSpeed = 36.0;
|
|
|
|
updateParticles();
|
|
|
|
|
|
player.prevY = player.y;
|
|
|
|
obstacleBuffer.forEach(o => o.prevX = o.x);
|
|
platformBuffer.forEach(p => p.prevX = p.x);
|
|
|
|
const originalHeight = 50;
|
|
const crouchHeight = 25;
|
|
|
|
player.h = isCrouching ? crouchHeight : originalHeight;
|
|
let drawY = isCrouching ? player.y + (originalHeight - crouchHeight) : player.y;
|
|
|
|
const oldY = player.y;
|
|
|
|
player.vy += GRAVITY;
|
|
if (isCrouching && !player.grounded) player.vy += 2.0;
|
|
|
|
let newY = player.y + player.vy;
|
|
let landed = false;
|
|
|
|
|
|
if (player.vy > 0) {
|
|
for (let plat of platformBuffer) {
|
|
if (plat.x < GAME_WIDTH + 100 && plat.x > -100) {
|
|
if (player.x + 30 > plat.x && player.x < plat.x + plat.w) {
|
|
const feetOld = oldY + originalHeight;
|
|
const feetNew = newY + originalHeight;
|
|
if (feetOld <= plat.y && feetNew >= plat.y) {
|
|
newY = plat.y - originalHeight;
|
|
player.vy = 0;
|
|
landed = true;
|
|
sendPhysicsSync(newY, 0);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (!landed && newY + originalHeight >= GROUND_Y) {
|
|
newY = GROUND_Y - originalHeight;
|
|
player.vy = 0;
|
|
landed = true;
|
|
}
|
|
|
|
if (currentTick % 10 === 0) {
|
|
sendPhysicsSync(player.y, player.vy);
|
|
}
|
|
|
|
player.y = newY;
|
|
player.grounded = landed;
|
|
|
|
|
|
obstacleBuffer.forEach(o => o.x -= currentSpeed);
|
|
platformBuffer.forEach(p => p.x -= currentSpeed);
|
|
|
|
|
|
obstacleBuffer = obstacleBuffer.filter(o => o.x + (o.w||30) > -200); // Muss -200 sein
|
|
platformBuffer = platformBuffer.filter(p => p.x + (p.w||100) > -200); // Muss -200 sein
|
|
|
|
|
|
obstacles = [];
|
|
platforms = [];
|
|
const RENDER_LIMIT = 900;
|
|
|
|
|
|
const pHitbox = { x: player.x, y: drawY, w: player.w, h: player.h };
|
|
|
|
|
|
obstacleBuffer.forEach(obs => {
|
|
|
|
if (obs.x < RENDER_LIMIT) {
|
|
|
|
|
|
if (!obs.def) {
|
|
let baseDef = null;
|
|
if(gameConfig && gameConfig.obstacles) {
|
|
baseDef = gameConfig.obstacles.find(x => x.id === obs.id);
|
|
}
|
|
obs.def = {
|
|
id: obs.id,
|
|
type: obs.type || (baseDef ? baseDef.type : "obstacle"),
|
|
width: obs.w || (baseDef ? baseDef.width : 30),
|
|
height: obs.h || (baseDef ? baseDef.height : 30),
|
|
color: obs.color || (baseDef ? baseDef.color : "red"),
|
|
image: baseDef ? baseDef.image : null,
|
|
imgScale: baseDef ? baseDef.imgScale : 1.0,
|
|
imgOffsetX: baseDef ? baseDef.imgOffsetX : 0,
|
|
imgOffsetY: baseDef ? baseDef.imgOffsetY : 0
|
|
};
|
|
}
|
|
|
|
if (!obs.collected && !isGameOver) {
|
|
if (checkCollision(pHitbox, obs)) {
|
|
|
|
const type = obs.def.type;
|
|
const id = obs.def.id;
|
|
|
|
// 1. COIN
|
|
if (type === "coin") {
|
|
score += 2000;
|
|
obs.collected = true;
|
|
playSound('coin');
|
|
spawnParticles(obs.x + 15, obs.y + 15, 'sparkle', 10);
|
|
}
|
|
// 2. POWERUP
|
|
else if (type === "powerup") {
|
|
if (id === "p_god") godModeLives = 3;
|
|
if (id === "p_bat") hasBat = true;
|
|
if (id === "p_boot") bootTicks = 600;
|
|
playSound('powerup');
|
|
spawnParticles(obs.x + 15, obs.y + 15, 'sparkle', 20); // Mehr Partikel
|
|
|
|
obs.collected = true;
|
|
}
|
|
|
|
else {
|
|
|
|
if (hasBat && type === "teacher") {
|
|
hasBat = false;
|
|
obs.collected = true;
|
|
playSound('hit');
|
|
spawnParticles(obs.x, obs.y, 'explosion', 5);
|
|
|
|
}
|
|
// Godmode (Schild)
|
|
else if (godModeLives > 0) {
|
|
godModeLives--;
|
|
playSound('hit');
|
|
spawnParticles(obs.x, obs.y, 'explosion', 5);
|
|
obs.collected = true;
|
|
}
|
|
// TOT
|
|
else {
|
|
console.log("💥 Kollision!");
|
|
player.color = "darkred";
|
|
gameOver("Kollision");
|
|
playSound('hit');
|
|
spawnParticles(player.x + 15, player.y + 25, 'explosion', 50); // Riesige Explosion
|
|
if (typeof sendInput === "function") sendInput("input", "DEATH");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!obs.collected) {
|
|
obstacles.push(obs);
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
platformBuffer.forEach(plat => {
|
|
if (plat.x < RENDER_LIMIT) {
|
|
platforms.push(plat);
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
function checkCollision(p, obs) {
|
|
const def = obs.def || {};
|
|
const w = def.width || obs.w || 30;
|
|
const h = def.height || obs.h || 30;
|
|
|
|
|
|
const padX = 8;
|
|
const padY = (def.type === "teacher" || def.type === "principal") ? 20 : 5;
|
|
|
|
|
|
const pL = p.x + padX;
|
|
const pR = p.x + p.w - padX;
|
|
const pT = p.y + padY;
|
|
const pB = p.y + p.h - 5;
|
|
|
|
const oL = obs.x + padX;
|
|
const oR = obs.x + w - padX;
|
|
const oT = obs.y + padY;
|
|
const oB = obs.y + h - 5;
|
|
|
|
return (pR > oL && pL < oR && pB > oT && pT < oB);
|
|
} |