function drawGame() {
drawNotebookBg();
gameSpeed = baseSpeed + distance / 3000;
lineOffset = (lineOffset + gameSpeed) % 30;
distance++;
for (let i = 0; i < milestones.length; i++) {
if (score >= milestones[i].score && i > lastMilestone) {
milestoneMsg = milestones[i].msg;
milestoneMsgTimer = 120;
lastMilestone = i;
}
}
for (let bg of bgElements) {
bg.x -= gameSpeed * 0.3;
if (bg.x < -50) {
bg.x = width + random(50, 200);
bg.y = random(60, groundY - 100);
bg.type = floor(random(4));
bg.size = random(15, 35);
}
drawDoodle(bg);
}
drawGround();
for (let i = obstacles.length - 1; i >= 0; i--) {
let o = obstacles[i];
o.x -= gameSpeed;
drawObstacle(o);
let px = player.x, py = player.y - player.h / 2;
let pw = player.w * 0.5, ph = player.h * 0.8;
if (px + pw > o.x && px - pw < o.x + o.w && py + ph > o.y && py - ph / 2 < o.y + o.h) {
die();
}
if (o.x + o.w < -20) obstacles.splice(i, 1);
}
let lastObs = obstacles[obstacles.length - 1];
let gap = map(gameSpeed, baseSpeed, baseSpeed + 4, 280, 200);
gap = max(gap, 160);
if (!lastObs || width - lastObs.x > gap + random(-40, 60)) {
spawnObstacle(width + random(20, 80));
}
for (let i = cheeses.length - 1; i >= 0; i--) {
let ch = cheeses[i];
ch.x -= gameSpeed;
ch.bobY = sin(frameCount * 0.08 + ch.phase) * 6;
push();
fill(220, 190, 40);
noStroke();
let cy = ch.y + ch.bobY;
triangle(ch.x, cy - 10, ch.x - 10, cy + 6, ch.x + 10, cy + 6);
fill(240, 210, 60);
ellipse(ch.x - 2, cy - 1, 4, 4);
ellipse(ch.x + 3, cy + 2, 3, 3);
pop();
let d = dist(player.x, player.y - player.h / 2, ch.x, cy);
if (d < 30) {
cheeseCount++;
score += 50;
cheeses.splice(i, 1);
continue;
}
if (ch.x < -20) cheeses.splice(i, 1);
}
if (random() < 0.008) {
cheeses.push({
x: width + 20,
y: groundY - random(60, 150),
phase: random(TWO_PI),
bobY: 0
});
}
player.vy += gravity;
player.y += player.vy;
if (player.y >= groundY) {
if (!player.grounded && player.vy > 2) {
for (let j = 0; j < 5; j++) {
dustParticles.push({
x: player.x + random(-10, 10),
y: groundY,
vx: random(-2, 2),
vy: random(-3, -0.5),
life: 20
});
}
}
player.y = groundY;
player.vy = 0;
player.grounded = true;
jumpsLeft = MAX_JUMPS;
} else {
player.grounded = false;
}
player.runFrame += gameSpeed * 0.15;
drawGreg(player.x, player.y, player.h, player.runFrame, !player.grounded);
for (let i = dustParticles.length - 1; i >= 0; i--) {
let p = dustParticles[i];
p.x += p.vx;
p.y += p.vy;
p.vy += 0.15;
p.life--;
let a = map(p.life, 0, 20, 0, 150);
fill(160, 140, 120, a);
noStroke();
ellipse(p.x, p.y, 5);
if (p.life <= 0) dustParticles.splice(i, 1);
}
let speedBoost = distance / 4000;
rodrick.x += rodrick.speed + speedBoost;
fregley.x += fregley.speed + speedBoost * 0.6;
rodrick.x = min(rodrick.x, player.x - 25);
fregley.x = min(fregley.x, rodrick.x - 25);
rodrick.y = groundY;
fregley.y = groundY;
if (rodrick.x > -10) drawGreg(rodrick.x, rodrick.y, rodrick.size, frameCount * 0.2, false, color(160, 40, 40));
if (fregley.x > -10) drawGreg(fregley.x, fregley.y, fregley.size, frameCount * 0.18, false, color(40, 120, 40));
if (rodrick.x > 5) {
fill(160, 40, 40);
noStroke();
textSize(10);
textAlign(CENTER);
text("Rodrick", rodrick.x, rodrick.y - rodrick.size - 8);
}
if (fregley.x > 5) {
fill(40, 120, 40);
textSize(10);
textAlign(CENTER);
text("Fregley", fregley.x, fregley.y - fregley.size - 8);
}
if (rodrick.x >= player.x - player.w * 0.7) die();
score++;
drawHUD();
}