Untitled
unknown
plain_text
9 months ago
19 kB
20
Indexable
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Turtle Jump Game</title>
<style>
body {
margin: 0;
padding: 20px;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: linear-gradient(to bottom, #87CEEB 0%, #98FB98 100%);
font-family: Arial, sans-serif;
}
.game-container {
text-align: center;
}
canvas {
border: 2px solid #333;
background: linear-gradient(to bottom, #87CEEB 0%, #90EE90 70%, #228B22 100%);
display: block;
margin: 0 auto;
}
.score {
font-size: 24px;
font-weight: bold;
margin-bottom: 10px;
color: #333;
}
.instructions {
margin-top: 10px;
color: #666;
}
.game-over {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(255, 255, 255, 0.9);
padding: 20px;
border-radius: 10px;
text-align: center;
display: none;
}
</style>
</head>
<body>
<div class="game-container">
<div class="score">Score: <span id="score">0</span></div>
<canvas id="gameCanvas" width="800" height="400"></canvas>
<div class="instructions">
Press SPACEBAR or click to jump! Avoid rocks, plants, and swooping birds!
</div>
<div class="game-over" id="gameOver">
<h2>Game Over!</h2>
<p>Final Score: <span id="finalScore">0</span></p>
<p>Press SPACEBAR or click to restart</p>
</div>
</div>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const scoreElement = document.getElementById('score');
const gameOverElement = document.getElementById('gameOver');
const finalScoreElement = document.getElementById('finalScore');
// Game variables
let gameRunning = true;
let score = 0;
let gameSpeed = 3;
// Turtle object
const turtle = {
x: 50,
y: 300,
width: 40,
height: 30,
velocityY: 0,
jumpPower: -12,
gravity: 0.6,
grounded: true,
color: '#228B22'
};
// Obstacles and birds arrays
let obstacles = [];
let birds = [];
let obstacleTimer = 0;
let birdTimer = 0;
// Ground
const ground = {
y: 330,
height: 70
};
// Draw turtle
function drawTurtle() {
ctx.fillStyle = turtle.color;
// Shell (oval)
ctx.beginPath();
ctx.ellipse(turtle.x + 20, turtle.y + 10, 18, 12, 0, 0, 2 * Math.PI);
ctx.fill();
// Shell pattern
ctx.strokeStyle = '#006400';
ctx.lineWidth = 2;
ctx.beginPath();
ctx.ellipse(turtle.x + 20, turtle.y + 10, 18, 12, 0, 0, 2 * Math.PI);
ctx.stroke();
// Shell segments
ctx.beginPath();
ctx.moveTo(turtle.x + 8, turtle.y + 10);
ctx.lineTo(turtle.x + 32, turtle.y + 10);
ctx.moveTo(turtle.x + 20, turtle.y - 2);
ctx.lineTo(turtle.x + 20, turtle.y + 22);
ctx.stroke();
// Head
ctx.fillStyle = '#32CD32';
ctx.beginPath();
ctx.arc(turtle.x + 40, turtle.y + 15, 8, 0, 2 * Math.PI);
ctx.fill();
// Eye
ctx.fillStyle = '#000';
ctx.beginPath();
ctx.arc(turtle.x + 43, turtle.y + 12, 2, 0, 2 * Math.PI);
ctx.fill();
// Legs
ctx.fillStyle = '#32CD32';
ctx.fillRect(turtle.x + 5, turtle.y + 20, 8, 6);
ctx.fillRect(turtle.x + 27, turtle.y + 20, 8, 6);
}
// Draw bird
function drawBird(bird) {
ctx.save();
ctx.translate(bird.x + bird.width/2, bird.y + bird.height/2);
ctx.rotate(bird.angle);
// Bird body
ctx.fillStyle = bird.color;
ctx.beginPath();
ctx.ellipse(0, 0, 12, 8, 0, 0, 2 * Math.PI);
ctx.fill();
// Bird head
ctx.beginPath();
ctx.arc(8, -2, 6, 0, 2 * Math.PI);
ctx.fill();
// Beak
ctx.fillStyle = '#FFA500';
ctx.beginPath();
ctx.moveTo(12, -2);
ctx.lineTo(18, -1);
ctx.lineTo(12, 1);
ctx.closePath();
ctx.fill();
// Eye
ctx.fillStyle = '#000';
ctx.beginPath();
ctx.arc(10, -3, 1.5, 0, 2 * Math.PI);
ctx.fill();
// Wings (animated)
ctx.fillStyle = bird.color;
const wingFlap = Math.sin(Date.now() * 0.02 + bird.id) * 0.3;
// Left wing
ctx.beginPath();
ctx.ellipse(-5, 0, 8, 4, wingFlap, 0, 2 * Math.PI);
ctx.fill();
// Right wing
ctx.beginPath();
ctx.ellipse(-5, 0, 8, 4, -wingFlap, 0, 2 * Math.PI);
ctx.fill();
// Tail
ctx.beginPath();
ctx.ellipse(-12, 0, 6, 3, 0, 0, 2 * Math.PI);
ctx.fill();
ctx.restore();
}
// Draw obstacle (rock)
function drawRock(obstacle) {
ctx.fillStyle = '#696969';
ctx.beginPath();
ctx.arc(obstacle.x + obstacle.width/2, obstacle.y + obstacle.height/2, obstacle.width/2, 0, 2 * Math.PI);
ctx.fill();
// Rock texture
ctx.fillStyle = '#556B2F';
ctx.beginPath();
ctx.arc(obstacle.x + 8, obstacle.y + 8, 3, 0, 2 * Math.PI);
ctx.fill();
ctx.beginPath();
ctx.arc(obstacle.x + 18, obstacle.y + 12, 2, 0, 2 * Math.PI);
ctx.fill();
}
// Draw plant obstacle
function drawPlant(obstacle) {
// Stem
ctx.fillStyle = '#228B22';
ctx.fillRect(obstacle.x + obstacle.width/2 - 2, obstacle.y + 15, 4, obstacle.height - 15);
// Leaves
ctx.fillStyle = '#32CD32';
// Left leaves
ctx.beginPath();
ctx.ellipse(obstacle.x + 8, obstacle.y + 20, 8, 4, -Math.PI/4, 0, 2 * Math.PI);
ctx.fill();
ctx.beginPath();
ctx.ellipse(obstacle.x + 6, obstacle.y + 30, 7, 3, -Math.PI/6, 0, 2 * Math.PI);
ctx.fill();
// Right leaves
ctx.beginPath();
ctx.ellipse(obstacle.x + 22, obstacle.y + 18, 8, 4, Math.PI/4, 0, 2 * Math.PI);
ctx.fill();
ctx.beginPath();
ctx.ellipse(obstacle.x + 24, obstacle.y + 28, 7, 3, Math.PI/6, 0, 2 * Math.PI);
ctx.fill();
// Top leaves
ctx.beginPath();
ctx.ellipse(obstacle.x + 15, obstacle.y + 10, 6, 8, 0, 0, 2 * Math.PI);
ctx.fill();
// Flower (sometimes)
if (obstacle.hasFlower) {
ctx.fillStyle = '#FF69B4';
ctx.beginPath();
ctx.arc(obstacle.x + 15, obstacle.y + 5, 4, 0, 2 * Math.PI);
ctx.fill();
// Flower center
ctx.fillStyle = '#FFD700';
ctx.beginPath();
ctx.arc(obstacle.x + 15, obstacle.y + 5, 2, 0, 2 * Math.PI);
ctx.fill();
}
}
// Draw cactus obstacle
function drawCactus(obstacle) {
// Main body
ctx.fillStyle = '#228B22';
ctx.fillRect(obstacle.x + 8, obstacle.y + 10, 14, obstacle.height - 10);
// Side arms
ctx.fillRect(obstacle.x + 2, obstacle.y + 20, 10, 6);
ctx.fillRect(obstacle.x + 18, obstacle.y + 25, 10, 6);
// Spikes
ctx.fillStyle = '#8B4513';
ctx.lineWidth = 1;
// Main body spikes
for (let i = 0; i < 6; i++) {
ctx.fillRect(obstacle.x + 10 + i * 2, obstacle.y + 15 + i * 4, 1, 3);
ctx.fillRect(obstacle.x + 18 - i, obstacle.y + 18 + i * 3, 1, 3);
}
// Side arm spikes
ctx.fillRect(obstacle.x + 4, obstacle.y + 21, 1, 2);
ctx.fillRect(obstacle.x + 8, obstacle.y + 22, 1, 2);
ctx.fillRect(obstacle.x + 20, obstacle.y + 26, 1, 2);
ctx.fillRect(obstacle.x + 24, obstacle.y + 27, 1, 2);
}
// Draw ground
function drawGround() {
ctx.fillStyle = '#8B4513';
ctx.fillRect(0, ground.y, canvas.width, ground.height);
// Grass on top
ctx.fillStyle = '#228B22';
ctx.fillRect(0, ground.y, canvas.width, 10);
}
// Update turtle physics
function updateTurtle() {
turtle.velocityY += turtle.gravity;
turtle.y += turtle.velocityY;
// Ground collision
if (turtle.y >= ground.y - turtle.height) {
turtle.y = ground.y - turtle.height;
turtle.velocityY = 0;
turtle.grounded = true;
} else {
turtle.grounded = false;
}
}
// Jump function
function jump() {
if (turtle.grounded && gameRunning) {
turtle.velocityY = turtle.jumpPower;
turtle.grounded = false;
}
}
// Create obstacle
function createObstacle() {
const obstacleTypes = ['rock', 'plant', 'cactus'];
const type = obstacleTypes[Math.floor(Math.random() * obstacleTypes.length)];
let obstacle = {
x: canvas.width,
type: type
};
switch(type) {
case 'rock':
obstacle.y = ground.y - 25;
obstacle.width = 25;
obstacle.height = 25;
break;
case 'plant':
obstacle.y = ground.y - 40;
obstacle.width = 30;
obstacle.height = 40;
obstacle.hasFlower = Math.random() > 0.5;
break;
case 'cactus':
obstacle.y = ground.y - 45;
obstacle.width = 30;
obstacle.height = 45;
break;
}
obstacles.push(obstacle);
}
// Create bird
function createBird() {
const birdColors = ['#8B4513', '#DC143C', '#4169E1', '#32CD32', '#FF8C00'];
const attackPatterns = ['swoop', 'dive', 'circle'];
let bird = {
x: canvas.width + 50,
y: Math.random() * 150 + 50, // Start somewhere in upper area
width: 25,
height: 20,
velocityX: -(gameSpeed + Math.random() * 2 + 1),
velocityY: 0,
color: birdColors[Math.floor(Math.random() * birdColors.length)],
pattern: attackPatterns[Math.floor(Math.random() * attackPatterns.length)],
angle: 0,
id: Math.random(), // For wing animation
phase: 0, // For attack pattern timing
targetY: 0
};
// Set target based on pattern
switch(bird.pattern) {
case 'swoop':
bird.targetY = turtle.y + Math.random() * 40 - 20;
break;
case 'dive':
bird.targetY = ground.y - 30;
break;
case 'circle':
bird.targetY = turtle.y - 50;
break;
}
birds.push(bird);
}
// Update birds
function updateBirds() {
birdTimer++;
// Create new bird
if (birdTimer > 180 - Math.floor(score / 150) * 10) {
createBird();
birdTimer = 0;
}
// Update existing birds
for (let i = birds.length - 1; i >= 0; i--) {
let bird = birds[i];
bird.phase += 0.05;
// Update bird movement based on pattern
switch(bird.pattern) {
case 'swoop':
// Swooping motion - sine wave towards target
bird.x += bird.velocityX;
bird.y += Math.sin(bird.phase * 2) * 2;
if (bird.x < turtle.x + 100 && bird.x > turtle.x - 50) {
bird.velocityY = (bird.targetY - bird.y) * 0.1;
bird.y += bird.velocityY;
}
bird.angle = Math.atan2(bird.velocityY, bird.velocityX);
break;
case 'dive':
// Diving attack
bird.x += bird.velocityX;
if (bird.x < turtle.x + 150) {
bird.velocityY += 0.5; // Accelerate downward
bird.y += bird.velocityY;
}
bird.angle = Math.atan2(bird.velocityY, bird.velocityX);
break;
case 'circle':
// Circling pattern
bird.x += bird.velocityX * 0.7;
bird.y = bird.targetY + Math.sin(bird.phase * 3) * 30;
bird.angle = bird.phase * 3;
break;
}
// Remove birds that are off screen
if (bird.x + bird.width < -50 || bird.y > canvas.height + 50) {
birds.splice(i, 1);
score += 5; // Small bonus for surviving a bird
}
}
}
// Update obstacles
function updateObstacles() {
obstacleTimer++;
// Create new obstacle
if (obstacleTimer > 100 - Math.floor(score / 100) * 8) {
createObstacle();
obstacleTimer = 0;
}
// Move obstacles
for (let i = obstacles.length - 1; i >= 0; i--) {
obstacles[i].x -= gameSpeed;
// Remove off-screen obstacles
if (obstacles[i].x + obstacles[i].width < 0) {
obstacles.splice(i, 1);
score += 10;
}
}
}
// Collision detection
function checkCollisions() {
// Check obstacle collisions
for (let obstacle of obstacles) {
if (turtle.x < obstacle.x + obstacle.width &&
turtle.x + turtle.width > obstacle.x &&
turtle.y < obstacle.y + obstacle.height &&
turtle.y + turtle.height > obstacle.y) {
gameOver();
}
}
// Check bird collisions
for (let bird of birds) {
if (turtle.x < bird.x + bird.width &&
turtle.x + turtle.width > bird.x &&
turtle.y < bird.y + bird.height &&
turtle.y + turtle.height > bird.y) {
gameOver();
}
}
}
// Game over
function gameOver() {
gameRunning = false;
finalScoreElement.textContent = score;
gameOverElement.style.display = 'block';
}
// Restart game
function restart() {
gameRunning = true;
score = 0;
obstacles = [];
birds = [];
obstacleTimer = 0;
birdTimer = 0;
turtle.y = 300;
turtle.velocityY = 0;
turtle.grounded = true;
gameOverElement.style.display = 'none';
}
// Game loop
function gameLoop() {
// Clear canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (gameRunning) {
// Update game objects
updateTurtle();
updateObstacles();
updateBirds();
checkCollisions();
// Increase game speed gradually
gameSpeed = 3 + Math.floor(score / 200) * 0.5;
}
// Draw everything
drawGround();
drawTurtle();
// Draw obstacles
for (let obstacle of obstacles) {
switch(obstacle.type) {
case 'rock':
drawRock(obstacle);
break;
case 'plant':
drawPlant(obstacle);
break;
case 'cactus':
drawCactus(obstacle);
break;
}
}
// Draw birds
for (let bird of birds) {
drawBird(bird);
}
// Update score display
scoreElement.textContent = score;
requestAnimationFrame(gameLoop);
}
// Event listeners
document.addEventListener('keydown', function(event) {
if (event.code === 'Space') {
event.preventDefault();
if (gameRunning) {
jump();
} else {
restart();
}
}
});
canvas.addEventListener('click', function() {
if (gameRunning) {
jump();
} else {
restart();
}
});
// Start the game
gameLoop();
</script>
</body>
</html>
Editor is loading...
Leave a Comment