Files
carrot-hunter/carrot_hunter.html

1277 lines
46 KiB
HTML

<!DOCTYPE html>
<html lang="da">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Carrot Hunter</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: linear-gradient(135deg, #4169E1 0%, #32CD32 100%);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
font-family: 'Arial', sans-serif;
}
#gameContainer {
position: relative;
background: white;
border-radius: 10px;
box-shadow: 0 10px 40px rgba(0,0,0,0.3);
overflow: hidden;
}
canvas {
display: block;
background: linear-gradient(180deg, #87CEEB 0%, #E0F8FF 100%);
}
#ui {
position: absolute;
top: 10px;
left: 10px;
right: 10px;
display: flex;
justify-content: space-between;
align-items: center;
color: white;
font-size: 20px;
font-weight: bold;
text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
z-index: 10;
}
#score, #level {
background: rgba(0,0,0,0.3);
padding: 10px 20px;
border-radius: 5px;
backdrop-filter: blur(5px);
}
#gameOver {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0,0,0,0.9);
color: white;
padding: 40px;
border-radius: 10px;
text-align: center;
z-index: 100;
display: none;
min-width: 300px;
}
#gameOver h1 {
font-size: 40px;
margin-bottom: 20px;
}
#gameOver p {
font-size: 20px;
margin: 10px 0;
}
#gameOver button {
background: #32CD32;
color: white;
border: none;
padding: 10px 30px;
font-size: 16px;
border-radius: 5px;
cursor: pointer;
margin-top: 20px;
}
#gameOver button:hover {
background: #228B22;
}
</style>
</head>
<body>
<div id="gameContainer">
<canvas id="gameCanvas" width="1024" height="576"></canvas>
<div id="ui">
<div id="score">Gulerødder: 0/5</div>
<div id="level">Level: 1</div>
</div>
<div id="gameOver">
<h1 id="gameOverTitle">Level Færdig!</h1>
<p id="gameOverScore">Score: 0</p>
<p id="gameOverMessage"></p>
<button id="restartBtn">Næste Level</button>
</div>
</div>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
// Game objects
let gameState = {
level: 1,
score: 0,
totalCarrots: 0,
carrots: [],
enemies: [],
platforms: [],
player: null,
gameOver: false
};
// Player object
class Player {
constructor(x, y) {
this.x = x;
this.y = y;
this.width = 40;
this.height = 50;
this.velocityX = 0;
this.velocityY = 0;
this.isJumping = false;
this.jumpPower = 12;
this.gravity = 0.5;
this.speed = 5;
this.direction = 1; // 1 for right, -1 for left
}
draw() {
// Draw bunny body
ctx.fillStyle = '#FFFFFF';
ctx.fillRect(this.x, this.y + 15, this.width, 30);
// Draw head
ctx.fillStyle = '#FFFFFF';
ctx.beginPath();
ctx.arc(this.x + this.width/2, this.y + 10, 12, 0, Math.PI * 2);
ctx.fill();
// Draw ears
ctx.fillStyle = '#FFB6D9';
ctx.fillRect(this.x + 12, this.y - 10, 6, 15);
ctx.fillRect(this.x + 22, this.y - 10, 6, 15);
// Ear fill (white)
ctx.fillStyle = '#FFFFFF';
ctx.fillRect(this.x + 13, this.y - 8, 4, 11);
ctx.fillRect(this.x + 23, this.y - 8, 4, 11);
// Draw eyes
ctx.fillStyle = '#000000';
ctx.beginPath();
ctx.arc(this.x + 14, this.y + 8, 2, 0, Math.PI * 2);
ctx.fill();
ctx.beginPath();
ctx.arc(this.x + 26, this.y + 8, 2, 0, Math.PI * 2);
ctx.fill();
// Draw nose
ctx.fillStyle = '#FF1493';
ctx.beginPath();
ctx.arc(this.x + 20, this.y + 12, 2, 0, Math.PI * 2);
ctx.fill();
// Draw mouth
ctx.strokeStyle = '#000000';
ctx.lineWidth = 1;
ctx.beginPath();
ctx.arc(this.x + 20, this.y + 14, 1.5, 0, Math.PI);
ctx.stroke();
}
update(keys) {
// Horizontal movement
this.velocityX = 0;
if (keys['ArrowLeft'] || keys['a']) {
this.velocityX = -this.speed;
this.direction = -1;
}
if (keys['ArrowRight'] || keys['d']) {
this.velocityX = this.speed;
this.direction = 1;
}
this.x += this.velocityX;
// Boundary check
if (this.x < 0) this.x = 0;
if (this.x + this.width > canvas.width) this.x = canvas.width - this.width;
// Apply gravity
this.velocityY += this.gravity;
this.y += this.velocityY;
// Check platform collisions
this.isJumping = true;
for (let platform of gameState.platforms) {
if (this.velocityY >= 0 &&
this.y + this.height >= platform.y &&
this.y + this.height <= platform.y + platform.height + 10 &&
this.x + this.width > platform.x &&
this.x < platform.x + platform.width) {
this.velocityY = 0;
this.y = platform.y - this.height;
this.isJumping = false;
}
}
// Jump
if ((keys['ArrowUp'] || keys['w'] || keys[' ']) && !this.isJumping) {
this.velocityY = -this.jumpPower;
this.isJumping = true;
}
// Check carrot collisions
for (let i = gameState.carrots.length - 1; i >= 0; i--) {
let carrot = gameState.carrots[i];
if (this.checkCollision(carrot)) {
gameState.carrots.splice(i, 1);
gameState.score++;
updateUI();
}
}
// Check enemy collisions
for (let enemy of gameState.enemies) {
if (this.checkCollision(enemy)) {
gameState.gameOver = true;
showGameOver('Du blev taget af en fjende!', 'Prøv igen');
}
}
// Fall off map
if (this.y > canvas.height) {
gameState.gameOver = true;
showGameOver('Du faldt ned!', 'Prøv igen');
}
// Level complete
if (gameState.carrots.length === 0 && gameState.totalCarrots > 0) {
gameState.gameOver = true;
showGameOver('Level Færdig!', 'Næste Level', true);
}
}
checkCollision(obj) {
return this.x < obj.x + obj.width &&
this.x + this.width > obj.x &&
this.y < obj.y + obj.height &&
this.y + this.height > obj.y;
}
}
// Carrot class
class Carrot {
constructor(x, y) {
this.x = x;
this.y = y;
this.width = 25;
this.height = 25;
this.rotation = 0;
}
draw() {
ctx.save();
ctx.translate(this.x + this.width/2, this.y + this.height/2);
ctx.rotate(this.rotation);
// Carrot body (bright orange)
ctx.fillStyle = '#FF8C00';
ctx.beginPath();
ctx.moveTo(0, -12);
ctx.lineTo(8, -4);
ctx.lineTo(8, 4);
ctx.lineTo(0, 12);
ctx.lineTo(-8, 4);
ctx.lineTo(-8, -4);
ctx.fill();
// Carrot outline
ctx.strokeStyle = '#FF6400';
ctx.lineWidth = 1;
ctx.stroke();
// Carrot top (bright green)
ctx.fillStyle = '#32CD32';
ctx.beginPath();
ctx.moveTo(0, -12);
ctx.lineTo(-4, -18);
ctx.lineTo(0, -20);
ctx.lineTo(4, -18);
ctx.fill();
ctx.strokeStyle = '#228B22';
ctx.lineWidth = 1;
ctx.stroke();
ctx.restore();
this.rotation += 0.05;
}
update() {
this.draw();
}
}
// Enemy class
class Enemy {
constructor(x, y, width, speed) {
this.x = x;
this.y = y;
this.width = width;
this.height = 30;
this.speed = speed;
this.direction = 1;
this.minX = x - 100;
this.maxX = x + 100;
}
draw() {
// Enemy body (bright red)
ctx.fillStyle = '#FF4500';
ctx.fillRect(this.x, this.y, this.width, this.height);
// Enemy outline
ctx.strokeStyle = '#CC3300';
ctx.lineWidth = 2;
ctx.strokeRect(this.x, this.y, this.width, this.height);
// Eyes (yellow)
ctx.fillStyle = '#FFD700';
ctx.fillRect(this.x + 5, this.y + 5, 8, 8);
ctx.fillRect(this.x + this.width - 13, this.y + 5, 8, 8);
// Pupils (black)
ctx.fillStyle = '#000000';
ctx.fillRect(this.x + 6, this.y + 6, 6, 6);
ctx.fillRect(this.x + this.width - 12, this.y + 6, 6, 6);
// Eyebrows (angry look)
ctx.strokeStyle = '#000000';
ctx.lineWidth = 1;
ctx.beginPath();
ctx.moveTo(this.x + 5, this.y + 4);
ctx.lineTo(this.x + 12, this.y + 3);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(this.x + this.width - 13, this.y + 4);
ctx.lineTo(this.x + this.width - 6, this.y + 3);
ctx.stroke();
}
update() {
this.x += this.speed * this.direction;
if (this.x <= this.minX || this.x >= this.maxX) {
this.direction *= -1;
}
this.draw();
}
}
// Platform class
class Platform {
constructor(x, y, width, height = 20) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
draw() {
ctx.fillStyle = '#8B7355';
ctx.fillRect(this.x, this.y, this.width, this.height);
// Darker border for depth
ctx.strokeStyle = '#654321';
ctx.lineWidth = 2;
ctx.strokeRect(this.x, this.y, this.width, this.height);
// Wood grain effect
ctx.fillStyle = 'rgba(0, 0, 0, 0.1)';
for (let i = 0; i < this.width; i += 20) {
ctx.fillRect(this.x + i, this.y, 2, this.height);
}
}
update() {
this.draw();
}
}
// Level designs
const levels = [
{
name: 'Level 1: Begyndelse',
platforms: [
new Platform(0, 500, 1024, 76), // Bottom
new Platform(150, 400, 150),
new Platform(400, 350, 150),
new Platform(650, 400, 150),
new Platform(200, 250, 200),
new Platform(600, 250, 200)
],
carrots: [
{x: 170, y: 350},
{x: 420, y: 300},
{x: 670, y: 350},
{x: 300, y: 180},
{x: 700, y: 180}
],
enemies: []
},
{
name: 'Level 2: Fjender',
platforms: [
new Platform(0, 500, 1024, 76),
new Platform(100, 400, 150),
new Platform(350, 350, 150),
new Platform(600, 400, 150),
new Platform(250, 250, 200),
new Platform(550, 250, 200)
],
carrots: [
{x: 120, y: 350},
{x: 370, y: 300},
{x: 620, y: 350},
{x: 350, y: 180},
{x: 650, y: 180}
],
enemies: [
new Enemy(300, 320, 40, 2),
new Enemy(700, 320, 40, 1.5)
]
},
{
name: 'Level 3: Udfordring',
platforms: [
new Platform(0, 500, 1024, 76),
new Platform(50, 420, 80),
new Platform(200, 380, 80),
new Platform(350, 420, 80),
new Platform(500, 380, 80),
new Platform(650, 420, 80),
new Platform(800, 380, 80),
new Platform(150, 280, 200),
new Platform(650, 280, 200),
new Platform(400, 180, 200)
],
carrots: [
{x: 60, y: 370},
{x: 210, y: 330},
{x: 360, y: 370},
{x: 510, y: 330},
{x: 660, y: 370}
],
enemies: [
new Enemy(250, 250, 40, 2),
new Enemy(650, 250, 40, 2),
new Enemy(450, 150, 40, 1.5)
]
}
];
platforms: [
new Platform(0, 500, 1024, 76),
new Platform(80, 420, 100),
new Platform(280, 400, 100),
new Platform(480, 420, 100),
new Platform(680, 400, 100),
new Platform(150, 300, 150),
new Platform(700, 300, 150),
new Platform(400, 200, 200)
],
carrots: [
{x: 100, y: 360},
{x: 300, y: 340},
{x: 500, y: 360},
{x: 700, y: 340},
{x: 200, y: 240},
{x: 650, y: 240},
{x: 430, y: 120},
{x: 370, y: 120},
{x: 500, y: 120},
{x: 300, y: 120}
],
enemies: [
new Enemy(200, 250, 40, 2.5),
new Enemy(600, 250, 40, 2.5),
new Enemy(400, 350, 40, 2)
]
},
{
name: 'Level 5: Fjendekval',
platforms: [
new Platform(0, 500, 1024, 76),
new Platform(100, 420, 80),
new Platform(300, 380, 80),
new Platform(500, 420, 80),
new Platform(700, 380, 80),
new Platform(150, 280, 180),
new Platform(680, 280, 180),
new Platform(400, 180, 180)
],
carrots: [
{x: 120, y: 360},
{x: 320, y: 320},
{x: 520, y: 360},
{x: 720, y: 320},
{x: 220, y: 220},
{x: 750, y: 220},
{x: 350, y: 120},
{x: 450, y: 120}
],
enemies: [
new Enemy(250, 250, 40, 3),
new Enemy(650, 250, 40, 3),
new Enemy(400, 350, 40, 2),
new Enemy(500, 150, 40, 2.5)
]
},
{
name: 'Level 6: Springning',
platforms: [
new Platform(0, 500, 1024, 76),
new Platform(50, 450, 70),
new Platform(150, 420, 70),
new Platform(250, 450, 70),
new Platform(350, 420, 70),
new Platform(450, 450, 70),
new Platform(550, 420, 70),
new Platform(650, 450, 70),
new Platform(750, 420, 70),
new Platform(850, 450, 70),
new Platform(200, 300, 150),
new Platform(650, 300, 150),
new Platform(400, 150, 200)
],
carrots: [
{x: 60, y: 400},
{x: 160, y: 370},
{x: 260, y: 400},
{x: 360, y: 370},
{x: 460, y: 400},
{x: 560, y: 370},
{x: 660, y: 400},
{x: 760, y: 370},
{x: 860, y: 400},
{x: 250, y: 240},
{x: 700, y: 240},
{x: 350, y: 80},
{x: 450, y: 80}
],
enemies: [
new Enemy(300, 270, 40, 2.5),
new Enemy(700, 270, 40, 2.5),
new Enemy(400, 100, 40, 2)
]
},
{
name: 'Level 7: Kombineret',
platforms: [
new Platform(0, 500, 1024, 76),
new Platform(80, 420, 120),
new Platform(350, 400, 100),
new Platform(600, 420, 120),
new Platform(100, 300, 200),
new Platform(750, 300, 200),
new Platform(300, 220, 150),
new Platform(550, 220, 150),
new Platform(400, 100, 200)
],
carrots: [
{x: 120, y: 350},
{x: 370, y: 330},
{x: 640, y: 350},
{x: 180, y: 240},
{x: 800, y: 240},
{x: 350, y: 160},
{x: 600, y: 160},
{x: 300, y: 40},
{x: 450, y: 40},
{x: 550, y: 40},
{x: 650, y: 40},
{x: 380, y: 270},
{x: 620, y: 270}
],
enemies: [
new Enemy(200, 250, 40, 2),
new Enemy(700, 250, 40, 2),
new Enemy(350, 180, 40, 2.5),
new Enemy(550, 180, 40, 2.5),
new Enemy(450, 50, 40, 3)
]
},
{
name: 'Level 8: Mekanisme Intro',
platforms: [
new Platform(0, 500, 1024, 76),
new Platform(50, 420, 100),
new Platform(200, 390, 100),
new Platform(350, 420, 100),
new Platform(500, 390, 100),
new Platform(650, 420, 100),
new Platform(800, 390, 100),
new Platform(100, 300, 180),
new Platform(750, 300, 180),
new Platform(250, 220, 150),
new Platform(600, 220, 150),
new Platform(400, 100, 200)
],
carrots: [
{x: 70, y: 360},
{x: 220, y: 330},
{x: 370, y: 360},
{x: 520, y: 330},
{x: 670, y: 360},
{x: 820, y: 330},
{x: 180, y: 240},
{x: 800, y: 240},
{x: 300, y: 160},
{x: 650, y: 160},
{x: 300, y: 40},
{x: 400, y: 40},
{x: 500, y: 40},
{x: 600, y: 40},
{x: 450, y: 200}
],
enemies: [
new Enemy(250, 250, 40, 2),
new Enemy(650, 250, 40, 2),
new Enemy(300, 170, 40, 2.5),
new Enemy(600, 170, 40, 2.5)
]
},
{
name: 'Level 9: Højdeskræk',
platforms: [
new Platform(0, 500, 1024, 76),
new Platform(450, 470, 100),
new Platform(200, 420, 100),
new Platform(700, 420, 100),
new Platform(450, 370, 100),
new Platform(100, 320, 100),
new Platform(800, 320, 100),
new Platform(450, 270, 100),
new Platform(300, 220, 100),
new Platform(600, 220, 100),
new Platform(450, 170, 100),
new Platform(200, 120, 150),
new Platform(650, 120, 150)
],
carrots: [
{x: 470, y: 410},
{x: 220, y: 360},
{x: 720, y: 360},
{x: 470, y: 310},
{x: 120, y: 260},
{x: 820, y: 260},
{x: 470, y: 210},
{x: 320, y: 160},
{x: 620, y: 160},
{x: 470, y: 110}
],
enemies: [
new Enemy(450, 330, 40, 2),
new Enemy(450, 230, 40, 2)
]
},
{
name: 'Level 10: Faldegruber',
platforms: [
new Platform(0, 500, 1024, 76),
new Platform(50, 420, 150),
new Platform(400, 420, 200),
new Platform(800, 420, 50),
new Platform(150, 340, 80),
new Platform(500, 340, 80),
new Platform(750, 340, 80),
new Platform(100, 280, 150),
new Platform(600, 280, 150),
new Platform(350, 220, 80),
new Platform(700, 220, 80),
new Platform(300, 140, 200)
],
carrots: [
{x: 100, y: 360},
{x: 480, y: 360},
{x: 820, y: 360},
{x: 170, y: 280},
{x: 520, y: 280},
{x: 770, y: 280},
{x: 180, y: 220},
{x: 650, y: 220},
{x: 380, y: 160},
{x: 750, y: 160},
{x: 250, y: 80},
{x: 450, y: 80}
],
enemies: [
new Enemy(300, 290, 40, 2.5),
new Enemy(650, 290, 40, 2.5),
new Enemy(380, 180, 40, 2)
]
},
{
name: 'Level 11: Spring Fest',
platforms: [
new Platform(0, 500, 1024, 76),
new Platform(30, 450, 60),
new Platform(120, 420, 60),
new Platform(210, 450, 60),
new Platform(300, 420, 60),
new Platform(390, 450, 60),
new Platform(480, 420, 60),
new Platform(570, 450, 60),
new Platform(660, 420, 60),
new Platform(750, 450, 60),
new Platform(840, 420, 60),
new Platform(150, 350, 100),
new Platform(450, 350, 100),
new Platform(750, 350, 100),
new Platform(100, 280, 80),
new Platform(400, 280, 80),
new Platform(700, 280, 80),
new Platform(300, 220, 120),
new Platform(600, 220, 120),
new Platform(450, 120, 150)
],
carrots: [
{x: 45, y: 390},
{x: 135, y: 360},
{x: 225, y: 390},
{x: 315, y: 360},
{x: 405, y: 390},
{x: 495, y: 360},
{x: 585, y: 390},
{x: 675, y: 360},
{x: 765, y: 390},
{x: 855, y: 360},
{x: 200, y: 290},
{x: 500, y: 290},
{x: 800, y: 290},
{x: 140, y: 220},
{x: 440, y: 220},
{x: 740, y: 220},
{x: 360, y: 150},
{x: 540, y: 150}
],
enemies: [
new Enemy(250, 310, 40, 2),
new Enemy(550, 310, 40, 2),
new Enemy(800, 310, 40, 2),
new Enemy(400, 180, 40, 2.5)
]
},
{
name: 'Level 12: Tower Climax',
platforms: [
new Platform(0, 500, 1024, 76),
new Platform(100, 450, 100),
new Platform(700, 450, 100),
new Platform(400, 420, 120),
new Platform(150, 380, 80),
new Platform(800, 380, 80),
new Platform(450, 350, 100),
new Platform(200, 310, 100),
new Platform(750, 310, 100),
new Platform(400, 270, 100),
new Platform(100, 240, 120),
new Platform(700, 240, 120),
new Platform(450, 200, 80),
new Platform(250, 160, 100),
new Platform(650, 160, 100),
new Platform(400, 120, 150),
new Platform(200, 80, 80),
new Platform(700, 80, 80),
new Platform(450, 40, 100)
],
carrots: [
{x: 130, y: 390},
{x: 730, y: 390},
{x: 460, y: 360},
{x: 180, y: 320},
{x: 830, y: 320},
{x: 480, y: 290},
{x: 230, y: 250},
{x: 780, y: 250},
{x: 470, y: 210},
{x: 280, y: 100},
{x: 680, y: 100},
{x: 380, y: 50},
{x: 520, y: 50},
{x: 300, y: 30},
{x: 600, y: 30},
{x: 150, y: 200},
{x: 800, y: 200},
{x: 450, y: 140},
{x: 400, y: 0},
{x: 500, y: 0}
],
enemies: [
new Enemy(300, 280, 40, 2.5),
new Enemy(650, 280, 40, 2.5),
new Enemy(450, 180, 40, 2),
new Enemy(250, 130, 40, 2),
new Enemy(700, 130, 40, 2),
new Enemy(450, 70, 40, 3)
]
},
{
name: 'Level 13: Bevægelse Start',
platforms: [
new Platform(0, 500, 1024, 76),
new Platform(150, 420, 150),
new Platform(650, 420, 150),
new Platform(400, 350, 200),
new Platform(100, 280, 180),
new Platform(800, 280, 180),
new Platform(450, 200, 180)
],
carrots: [
{x: 210, y: 360},
{x: 710, y: 360},
{x: 480, y: 290},
{x: 180, y: 220},
{x: 830, y: 220},
{x: 350, y: 140},
{x: 550, y: 140},
{x: 400, y: 120},
{x: 500, y: 120},
{x: 300, y: 100},
{x: 600, y: 100},
{x: 450, y: 80}
],
enemies: [
new Enemy(250, 350, 40, 2),
new Enemy(650, 350, 40, 2),
new Enemy(400, 250, 40, 2.5),
new Enemy(450, 150, 40, 2.5)
]
},
{
name: 'Level 14: Timing Master',
platforms: [
new Platform(0, 500, 1024, 76),
new Platform(80, 440, 100),
new Platform(280, 400, 100),
new Platform(480, 440, 100),
new Platform(680, 400, 100),
new Platform(840, 440, 100),
new Platform(150, 320, 180),
new Platform(700, 320, 180),
new Platform(300, 240, 150),
new Platform(550, 240, 150),
new Platform(400, 140, 200)
],
carrots: [
{x: 100, y: 380},
{x: 300, y: 340},
{x: 500, y: 380},
{x: 700, y: 340},
{x: 860, y: 380},
{x: 220, y: 260},
{x: 750, y: 260},
{x: 350, y: 180},
{x: 600, y: 180},
{x: 300, y: 80},
{x: 400, y: 80},
{x: 500, y: 80},
{x: 600, y: 80},
{x: 350, y: 200},
{x: 550, y: 200}
],
enemies: [
new Enemy(200, 280, 40, 2.5),
new Enemy(700, 280, 40, 2.5),
new Enemy(300, 200, 40, 3),
new Enemy(600, 200, 40, 3),
new Enemy(450, 100, 40, 2)
]
},
{
name: 'Level 15: Vulkan Hede',
platforms: [
new Platform(0, 500, 1024, 76),
new Platform(50, 430, 120),
new Platform(250, 400, 100),
new Platform(500, 430, 120),
new Platform(800, 400, 100),
new Platform(150, 330, 150),
new Platform(700, 330, 150),
new Platform(400, 270, 180),
new Platform(200, 200, 120),
new Platform(650, 200, 120),
new Platform(450, 130, 180),
new Platform(300, 70, 100),
new Platform(650, 70, 100)
],
carrots: [
{x: 100, y: 360},
{x: 270, y: 330},
{x: 540, y: 360},
{x: 820, y: 330},
{x: 220, y: 270},
{x: 750, y: 270},
{x: 460, y: 210},
{x: 260, y: 140},
{x: 710, y: 140},
{x: 350, y: 80},
{x: 500, y: 80},
{x: 650, y: 10},
{x: 700, y: 10},
{x: 380, y: 60},
{x: 550, y: 150},
{x: 450, y: 180},
{x: 400, y: 200},
{x: 300, y: 300}
],
enemies: [
new Enemy(250, 290, 40, 2.5),
new Enemy(650, 290, 40, 2.5),
new Enemy(400, 220, 40, 2.5),
new Enemy(300, 160, 40, 3),
new Enemy(650, 160, 40, 3),
new Enemy(450, 80, 40, 3),
new Enemy(350, 120, 40, 2)
]
},
{
name: 'Level 16: Giga Fjender',
platforms: [
new Platform(0, 500, 1024, 76),
new Platform(100, 430, 150),
new Platform(450, 420, 150),
new Platform(750, 430, 150),
new Platform(200, 340, 120),
new Platform(700, 340, 120),
new Platform(450, 280, 180),
new Platform(150, 220, 150),
new Platform(750, 220, 150),
new Platform(400, 160, 180),
new Platform(300, 100, 120),
new Platform(650, 100, 120),
new Platform(450, 50, 150)
],
carrots: [
{x: 150, y: 360},
{x: 480, y: 350},
{x: 800, y: 360},
{x: 250, y: 280},
{x: 750, y: 280},
{x: 480, y: 220},
{x: 200, y: 160},
{x: 800, y: 160},
{x: 450, y: 100},
{x: 350, y: 50},
{x: 550, y: 50}
],
enemies: [
new Enemy(300, 300, 40, 2.5),
new Enemy(700, 300, 40, 2.5),
new Enemy(400, 230, 40, 2.5),
new Enemy(450, 120, 40, 2.5),
new Enemy(350, 70, 40, 3)
]
},
{
name: 'Level 17: Alt Går',
platforms: [
new Platform(0, 500, 1024, 76),
new Platform(100, 440, 120),
new Platform(350, 410, 100),
new Platform(600, 440, 120),
new Platform(200, 350, 130),
new Platform(700, 350, 130),
new Platform(450, 290, 150),
new Platform(250, 230, 120),
new Platform(700, 230, 120),
new Platform(450, 170, 140),
new Platform(300, 120, 100),
new Platform(650, 120, 100),
new Platform(400, 60, 160)
],
carrots: [
{x: 130, y: 370},
{x: 370, y: 340},
{x: 630, y: 370},
{x: 250, y: 290},
{x: 750, y: 290},
{x: 480, y: 230},
{x: 300, y: 170},
{x: 700, y: 170},
{x: 480, y: 110},
{x: 330, y: 60},
{x: 680, y: 60},
{x: 450, y: 0},
{x: 400, y: 150},
{x: 500, y: 150},
{x: 350, y: 300}
],
enemies: [
new Enemy(300, 310, 40, 2.5),
new Enemy(700, 310, 40, 2.5),
new Enemy(400, 240, 40, 2.5),
new Enemy(450, 130, 40, 2.5)
]
},
{
name: 'Level 18: Ekstrem',
platforms: [
new Platform(0, 500, 1024, 76),
new Platform(80, 460, 90),
new Platform(200, 440, 90),
new Platform(320, 460, 90),
new Platform(440, 440, 90),
new Platform(560, 460, 90),
new Platform(680, 440, 90),
new Platform(800, 460, 90),
new Platform(180, 360, 120),
new Platform(700, 360, 120),
new Platform(450, 300, 140),
new Platform(250, 240, 110),
new Platform(700, 240, 110),
new Platform(450, 180, 130),
new Platform(300, 130, 100),
new Platform(650, 130, 100),
new Platform(400, 70, 150)
],
carrots: [
{x: 100, y: 390},
{x: 220, y: 370},
{x: 340, y: 390},
{x: 460, y: 370},
{x: 580, y: 390},
{x: 700, y: 370},
{x: 820, y: 390},
{x: 230, y: 300},
{x: 750, y: 300},
{x: 480, y: 240},
{x: 300, y: 180},
{x: 700, y: 180},
{x: 480, y: 120},
{x: 330, y: 70},
{x: 680, y: 70},
{x: 450, y: 20},
{x: 400, y: 220},
{x: 500, y: 260}
],
enemies: [
new Enemy(300, 320, 40, 2.5),
new Enemy(700, 320, 40, 2.5),
new Enemy(400, 250, 40, 2.5),
new Enemy(450, 140, 40, 2.5),
new Enemy(350, 100, 40, 2.5)
]
},
{
name: 'Level 19: Kaos',
platforms: [
new Platform(0, 500, 1024, 76),
new Platform(120, 430, 120),
new Platform(380, 400, 110),
new Platform(640, 430, 120),
new Platform(230, 340, 130),
new Platform(700, 340, 130),
new Platform(450, 290, 120),
new Platform(180, 240, 120),
new Platform(750, 240, 120),
new Platform(400, 190, 130),
new Platform(280, 140, 100),
new Platform(680, 140, 100),
new Platform(500, 100, 120),
new Platform(330, 60, 100),
new Platform(700, 60, 100),
new Platform(450, 20, 140)
],
carrots: [
{x: 160, y: 360},
{x: 400, y: 330},
{x: 680, y: 360},
{x: 280, y: 280},
{x: 780, y: 280},
{x: 480, y: 230},
{x: 220, y: 180},
{x: 800, y: 180},
{x: 440, y: 130},
{x: 320, y: 80},
{x: 700, y: 80},
{x: 530, y: 50},
{x: 400, y: 0},
{x: 550, y: 0},
{x: 450, y: 150},
{x: 350, y: 300}
],
enemies: [
new Enemy(300, 300, 40, 2.5),
new Enemy(700, 300, 40, 2.5),
new Enemy(450, 240, 40, 2.5),
new Enemy(250, 180, 40, 2.5),
new Enemy(750, 180, 40, 2.5),
new Enemy(400, 150, 40, 2.5),
new Enemy(500, 80, 40, 2.5)
]
},
{
name: 'Level 20: BOSS NIVEAU!',
platforms: [
new Platform(0, 500, 1024, 76),
new Platform(120, 450, 120),
new Platform(450, 430, 140),
new Platform(800, 450, 120),
new Platform(230, 380, 130),
new Platform(700, 380, 130),
new Platform(450, 320, 150),
new Platform(180, 260, 120),
new Platform(800, 260, 120),
new Platform(400, 200, 160),
new Platform(280, 150, 110),
new Platform(680, 150, 110),
new Platform(500, 100, 130),
new Platform(350, 50, 120),
new Platform(650, 50, 120),
new Platform(450, 10, 160)
],
carrots: [
{x: 160, y: 380},
{x: 480, y: 360},
{x: 820, y: 380},
{x: 280, y: 320},
{x: 780, y: 320},
{x: 480, y: 260},
{x: 220, y: 210},
{x: 830, y: 210},
{x: 440, y: 150},
{x: 320, y: 100},
{x: 720, y: 100},
{x: 530, y: 50},
{x: 380, y: 0},
{x: 680, y: 0},
{x: 400, y: 180},
{x: 350, y: 400},
{x: 600, y: 400},
{x: 450, y: 70},
{x: 250, y: 150},
{x: 750, y: 150},
{x: 400, y: 330},
{x: 500, y: 200},
{x: 300, y: 200},
{x: 700, y: 200},
{x: 450, y: 240}
],
enemies: [
new Enemy(300, 340, 40, 2.5),
new Enemy(700, 340, 40, 2.5),
new Enemy(450, 280, 40, 2.5),
new Enemy(250, 220, 40, 2.5),
new Enemy(800, 220, 40, 2.5),
new Enemy(400, 160, 40, 2.5),
new Enemy(500, 100, 40, 2.5)
]
}
];
let currentLevelIndex = 0;
function loadLevel(levelIndex) {
if (levelIndex >= levels.length) {
showGameOver('Du vandt!', 'Spillet er færdigt!');
return;
}
currentLevelIndex = levelIndex;
const level = levels[levelIndex];
gameState.level = levelIndex + 1;
gameState.platforms = level.platforms;
gameState.carrots = level.carrots.map(c => new Carrot(c.x, c.y));
gameState.totalCarrots = gameState.carrots.length;
gameState.enemies = level.enemies;
gameState.gameOver = false;
gameState.score = 0;
gameState.player = new Player(50, 400);
updateUI();
}
function updateUI() {
document.getElementById('score').textContent = `Gulerødder: ${gameState.score}/${gameState.totalCarrots}`;
document.getElementById('level').textContent = `Level: ${gameState.level}`;
}
function showGameOver(title, message, nextLevel = false) {
const dialog = document.getElementById('gameOver');
document.getElementById('gameOverTitle').textContent = title;
document.getElementById('gameOverScore').textContent = `Score: ${gameState.score}`;
document.getElementById('gameOverMessage').textContent = message;
const btn = document.getElementById('restartBtn');
btn.textContent = nextLevel ? 'Næste Level' : 'Prøv igen';
btn.onclick = function() {
dialog.style.display = 'none';
if (nextLevel) {
loadLevel(currentLevelIndex + 1);
} else {
loadLevel(currentLevelIndex);
}
};
dialog.style.display = 'block';
}
// Input handling
const keys = {};
window.addEventListener('keydown', (e) => {
keys[e.key] = true;
});
window.addEventListener('keyup', (e) => {
keys[e.key] = false;
});
// Game loop
function gameLoop() {
// Clear canvas with gradient
const gradient = ctx.createLinearGradient(0, 0, 0, canvas.height);
gradient.addColorStop(0, '#87CEEB');
gradient.addColorStop(1, '#E0F8FF');
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Update and draw
if (!gameState.gameOver) {
gameState.player.update(keys);
for (let platform of gameState.platforms) {
platform.update();
}
for (let carrot of gameState.carrots) {
carrot.update();
}
for (let enemy of gameState.enemies) {
enemy.update();
}
gameState.player.draw();
}
requestAnimationFrame(gameLoop);
}
// Start game
loadLevel(0);
gameLoop();
</script>
</body>
</html>