<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>马年跳跳乐 - 新春小游戏</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Arial', 'Microsoft YaHei', sans-serif;
}
body {
background: linear-gradient(to bottom, #0a1f3d, #1a0b2e);
color: #fff;
display: flex;
flex-direction: column;
align-items: center;
min-height: 100vh;
padding: 20px;
overflow-x: hidden;
}
.header {
text-align: center;
margin-bottom: 20px;
width: 100%;
}
h1 {
color: #ffcc00;
font-size: 2.5rem;
text-shadow: 0 0 10px rgba(255, 204, 0, 0.7);
margin-bottom: 10px;
background: linear-gradient(to right, #ff9900, #ffcc00);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
.subtitle {
color: #ff9966;
font-size: 1.2rem;
margin-bottom: 15px;
}
.game-info {
display: flex;
justify-content: space-between;
width: 800px;
max-width: 90%;
margin-bottom: 15px;
background-color: rgba(0, 0, 0, 0.3);
padding: 15px;
border-radius: 10px;
border: 2px solid #ffcc00;
}
.info-box {
text-align: center;
}
.info-label {
font-size: 0.9rem;
color: #aaa;
}
.info-value {
font-size: 1.8rem;
font-weight: bold;
color: #ffcc00;
}
.game-container {
position: relative;
width: 800px;
max-width: 90%;
height: 400px;
background-color: #111;
border: 4px solid #ffcc00;
border-radius: 10px;
overflow: hidden;
box-shadow: 0 0 30px rgba(255, 204, 0, 0.5);
margin-bottom: 20px;
}
#game-canvas {
width: 100%;
height: 100%;
background: linear-gradient(to bottom, #0c2d5e, #0a1f3d);
}
.controls {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 15px;
margin-bottom: 20px;
width: 800px;
max-width: 90%;
}
button {
background: linear-gradient(to bottom, #ff9900, #cc6600);
color: white;
border: none;
padding: 12px 25px;
font-size: 1.1rem;
border-radius: 50px;
cursor: pointer;
transition: all 0.3s;
font-weight: bold;
box-shadow: 0 5px 15px rgba(255, 153, 0, 0.4);
}
button:hover {
transform: translateY(-3px);
box-shadow: 0 8px 20px rgba(255, 153, 0, 0.6);
}
button:active {
transform: translateY(1px);
}
.instructions {
background-color: rgba(0, 0, 0, 0.3);
padding: 20px;
border-radius: 10px;
width: 800px;
max-width: 90%;
margin-bottom: 20px;
border-left: 4px solid #ff9966;
}
.instructions h3 {
color: #ffcc00;
margin-bottom: 10px;
}
.instructions ul {
padding-left: 20px;
}
.instructions li {
margin-bottom: 8px;
line-height: 1.5;
}
.highlight {
color: #ffcc00;
font-weight: bold;
}
.new-year-message {
color: #ff9966;
font-size: 1.1rem;
text-align: center;
margin-top: 10px;
font-style: italic;
}
.footer {
margin-top: 20px;
text-align: center;
color: #888;
font-size: 0.9rem;
width: 100%;
}
.game-over {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.85);
display: none;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 10;
border-radius: 10px;
}
.game-over h2 {
color: #ff3333;
font-size: 3rem;
margin-bottom: 20px;
text-shadow: 0 0 10px rgba(255, 51, 51, 0.7);
}
.game-over p {
font-size: 1.5rem;
margin-bottom: 30px;
color: #ffcc00;
}
@media (max-width: 768px) {
h1 {
font-size: 1.8rem;
}
.game-info, .controls, .instructions {
width: 95%;
}
.game-container {
height: 300px;
}
}
</style>
</head>
<body>
<div class="header">
<h1>🐎 马年跳跳乐 🐎</h1>
<div class="subtitle">农历丙午马年新春特别版</div>
</div>
<div class="game-info">
<div class="info-box">
<div class="info-label">得分</div>
<div id="score" class="info-value">0</div>
</div>
<div class="info-box">
<div class="info-label">最高分</div>
<div id="high-score" class="info-value">0</div>
</div>
<div class="info-box">
<div class="info-label">速度等级</div>
<div id="speed-level" class="info-value">1</div>
</div>
<div class="info-box">
<div class="info-label">状态</div>
<div id="status" class="info-value">准备开始</div>
</div>
</div>
<div class="game-container">
<canvas id="game-canvas" width="800" height="400"></canvas>
<div class="game-over" id="game-over-screen">
<h2>游戏结束</h2>
<p>本次得分: <span id="final-score">0</span></p>
<button id="restart-btn">再来一次</button>
</div>
</div>
<div class="controls">
<button id="start-btn">开始游戏</button>
<button id="pause-btn">暂停游戏</button>
<button id="jump-btn">立即跳跃</button>
<button id="reset-btn">重置游戏</button>
</div>
<div class="instructions">
<h3>游戏说明</h3>
<ul>
<li>控制小马跳过<span class="highlight">鞭炮</span>和<span class="highlight">灯笼</span>,每跳过一个得1分</li>
<li>按<span class="highlight">空格键</span>或<span class="highlight">点击跳跃按钮</span>控制小马跳跃</li>
<li>每得10分,游戏速度提升一个等级</li>
<li>撞到障碍物或地面则游戏结束</li>
<li>游戏最高分会保存在本地,努力刷新记录吧!</li>
</ul>
<div class="new-year-message">新春快乐,马到成功!丙午马年大吉大利!</div>
</div>
<div class="footer">
<p>马年跳跳乐 | 农历丙午马年(2026)新春特别游戏 | 使用HTML5 Canvas制作</p>
</div>
<script>
const canvas = document.getElementById('game-canvas');
const ctx = canvas.getContext('2d');
const scoreElement = document.getElementById('score');
const highScoreElement = document.getElementById('high-score');
const speedLevelElement = document.getElementById('speed-level');
const statusElement = document.getElementById('status');
const finalScoreElement = document.getElementById('final-score');
const gameOverScreen = document.getElementById('game-over-screen');
let gameRunning = false;
let gamePaused = false;
let score = 0;
let highScore = localStorage.getItem('horseJumpHighScore') || 0;
let speedLevel = 1;
let animationId;
const horse = {
x: 100,
y: canvas.height - 100,
width: 60,
height: 50,
velocityY: 0,
gravity: 0.5,
jumpStrength: -12,
isJumping: false,
color: '#8B4513',
draw() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
ctx.fillStyle = '#A0522D';
ctx.fillRect(this.x + this.width - 10, this.y - 20, 25, 30);
ctx.fillStyle = '#8B4513';
ctx.fillRect(this.x + 10, this.y + this.height, 10, 25);
ctx.fillRect(this.x + 40, this.y + this.height, 10, 25);
ctx.fillStyle = '#4A2C2A';
ctx.fillRect(this.x - 10, this.y + 10, 15, 5);
ctx.fillStyle = 'white';
ctx.fillRect(this.x + this.width + 5, this.y - 10, 8, 8);
ctx.fillStyle = 'black';
ctx.fillRect(this.x + this.width + 8, this.y - 7, 4, 4);
ctx.fillStyle = '#A0522D';
ctx.beginPath();
ctx.moveTo(this.x + this.width + 15, this.y - 20);
ctx.lineTo(this.x + this.width + 25, this.y - 30);
ctx.lineTo(this.x + this.width + 15, this.y - 25);
ctx.fill();
},
jump() {
if (!this.isJumping && gameRunning && !gamePaused) {
this.velocityY = this.jumpStrength;
this.isJumping = true;
}
},
update() {
this.velocityY += this.gravity;
this.y += this.velocityY;
if (this.y > canvas.height - 100) {
this.y = canvas.height - 100;
this.velocityY = 0;
this.isJumping = false;
}
if (this.y < 0) {
this.y = 0;
this.velocityY = 0;
}
}
};
let obstacles = [];
class Obstacle {
constructor(type) {
this.type = type;
this.x = canvas.width;
this.width = type === 'firecracker' ? 30 : 40;
this.height = type === 'firecracker' ? 50 : 60;
this.y = canvas.height - 100 - this.height + (type === 'firecracker' ? 10 : 0);
this.speed = 5 + (speedLevel * 0.5);
this.color = type === 'firecracker' ? '#FF3333' : '#FFCC00';
}
draw() {
ctx.fillStyle = this.color;
if (this.type === 'firecracker') {
ctx.fillRect(this.x, this.y, this.width, this.height);
ctx.fillStyle = '#888888';
ctx.fillRect(this.x + this.width/2 - 2, this.y - 10, 4, 10);
ctx.fillStyle = '#FF9900';
ctx.fillRect(this.x, this.y + 10, this.width, 5);
ctx.fillRect(this.x, this.y + 30, this.width, 5);
} else {
ctx.beginPath();
ctx.ellipse(this.x + this.width/2, this.y + this.height/2, this.width/2, this.height/2, 0, 0, Math.PI * 2);
ctx.fill();
ctx.fillStyle = '#CC9900';
ctx.fillRect(this.x + 5, this.y - 5, this.width - 10, 5);
ctx.fillRect(this.x + 5, this.y + this.height, this.width - 10, 5);
ctx.fillStyle = '#FF9900';
for (let i = 0; i < 5; i++) {
ctx.fillRect(this.x + this.width/2 - 1, this.y + this.height + 5 + i*3, 2, 3);
}
ctx.fillStyle = 'red';
ctx.font = 'bold 20px Arial';
ctx.textAlign = 'center';
ctx.fillText('福', this.x + this.width/2, this.y + this.height/2 + 8);
}
}
update() {
this.x -= this.speed;
}
checkCollision() {
return (
horse.x < this.x + this.width &&
horse.x + horse.width > this.x &&
horse.y < this.y + this.height &&
horse.y + horse.height > this.y
);
}
isPassed() {
return this.x + this.width < horse.x && !this.counted;
}
}
function initGame() {
score = 0;
speedLevel = 1;
obstacles = [];
horse.x = 100;
horse.y = canvas.height - 100;
horse.velocityY = 0;
horse.isJumping = false;
updateScore();
updateSpeedLevel();
statusElement.textContent = '准备开始';
gameOverScreen.style.display = 'none';
}
function updateScore() {
scoreElement.textContent = score;
if (score > highScore) {
highScore = score;
localStorage.setItem('horseJumpHighScore', highScore);
highScoreElement.textContent = highScore;
}
}
function updateSpeedLevel() {
speedLevelElement.textContent = speedLevel;
}
function generateObstacle() {
const types = ['firecracker', 'lantern'];
const type = types[Math.floor(Math.random() * types.length)];
const minGap = 300;
const lastObstacle = obstacles[obstacles.length - 1];
if (!lastObstacle || lastObstacle.x < canvas.width - minGap) {
obstacles.push(new Obstacle(type));
}
}
function drawBackground() {
const gradient = ctx.createLinearGradient(0, 0, 0, canvas.height);
gradient.addColorStop(0, '#0c2d5e');
gradient.addColorStop(1, '#0a1f3d');
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'white';
for (let i = 0; i < 50; i++) {
const x = Math.random() * canvas.width;
const y = Math.random() * canvas.height * 0.7;
const size = Math.random() * 2;
ctx.fillRect(x, y, size, size);
}
ctx.fillStyle = '#2d5016';
ctx.fillRect(0, canvas.height - 100, canvas.width, 100);
ctx.fillStyle = '#3a6b1f';
for (let i = 0; i < canvas.width; i += 20) {
ctx.fillRect(i, canvas.height - 100, 10, 10);
}
ctx.fillStyle = '#FF3333';
ctx.fillRect(0, 20, canvas.width, 40);
ctx.fillStyle = '#FFCC00';
ctx.font = 'bold 28px Arial';
ctx.textAlign = 'center';
ctx.fillText('农历丙午马年 新春快乐', canvas.width / 2, 50);
}
function gameLoop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBackground();
horse.update();
horse.draw();
if (Math.random() < 0.02 && gameRunning && !gamePaused) {
generateObstacle();
}
for (let i = obstacles.length - 1; i >= 0; i--) {
const obstacle = obstacles[i];
if (gameRunning && !gamePaused) {
obstacle.update();
}
obstacle.draw();
if (obstacle.checkCollision()) {
gameOver();
return;
}
if (obstacle.isPassed() && !obstacle.counted) {
score++;
obstacle.counted = true;
if (score % 10 === 0) {
speedLevel++;
updateSpeedLevel();
}
updateScore();
}
if (obstacle.x + obstacle.width < 0) {
obstacles.splice(i, 1);
}
}
if (gameRunning && !gamePaused) {
animationId = requestAnimationFrame(gameLoop);
}
}
function startGame() {
if (!gameRunning) {
gameRunning = true;
gamePaused = false;
statusElement.textContent = '游戏中';
gameLoop();
} else if (gamePaused) {
gamePaused = false;
statusElement.textContent = '游戏中';
gameLoop();
}
}
function pauseGame() {
if (gameRunning && !gamePaused) {
gamePaused = true;
statusElement.textContent = '已暂停';
cancelAnimationFrame(animationId);
}
}
function resetGame() {
cancelAnimationFrame(animationId);
initGame();
gameRunning = false;
gamePaused = false;
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBackground();
horse.draw();
statusElement.textContent = '准备开始';
}
function gameOver() {
gameRunning = false;
statusElement.textContent = '游戏结束';
finalScoreElement.textContent = score;
gameOverScreen.style.display = 'flex';
}
document.getElementById('start-btn').addEventListener('click', startGame);
document.getElementById('pause-btn').addEventListener('click', pauseGame);
document.getElementById('reset-btn').addEventListener('click', resetGame);
document.getElementById('restart-btn').addEventListener('click', () => {
initGame();
startGame();
});
document.getElementById('jump-btn').addEventListener('click', () => {
horse.jump();
});
document.addEventListener('keydown', (event) => {
if (event.code === 'Space') {
event.preventDefault();
horse.jump();
}
if (event.key === 's' || event.key === 'S') {
startGame();
} else if (event.key === 'p' || event.key === 'P') {
pauseGame();
} else if (event.key === 'r' || event.key === 'R') {
resetGame();
}
});
window.onload = function() {
highScoreElement.textContent = highScore;
initGame();
drawBackground();
horse.draw();
ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';
ctx.fillRect(canvas.width/2 - 150, canvas.height/2 - 50, 300, 100);
ctx.fillStyle = '#FFCC00';
ctx.font = 'bold 22px Arial';
ctx.textAlign = 'center';
ctx.fillText('点击"开始游戏"按钮', canvas.width/2, canvas.height/2 - 10);
ctx.fillText('或按 S 键开始', canvas.width/2, canvas.height/2 + 20);
};
</script>
</body>
</html>