项目使用纯前端代码html,css,js,jquery实现,只需要下载到本地双击index.html文件即可运行查看效果。
项目展示
进入游戏
游戏开始
游戏结束
代码展示
html文件
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>跳一跳游戏</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="game-container">
<div class="ui-layer">
<div class="score">得分:<span id="score">0</span></div>
<div class="power-hint">
<div class="hint-text">建议按压时间:<span id="suggestTime">0</span>秒</div>
<div class="power-bar">
<div class="power-progress"></div>
</div>
<div class="current-power">当前按压:<span id="currentTime">0</span>秒</div>
</div>
</div>
<div class="game-area">
<div class="player"></div>
</div>
<div class="control">
<button id="jumpBtn" disabled class="disabled">按住跳跃</button>
</div>
</div>
<div class="game-intro" id="gameIntro">
<div class="intro-content">
<h1>跳一跳小游戏</h1>
<div class="intro-text">
<h2>游戏说明:</h2>
<ul>
<li>🎮 按住按钮蓄力,松开进行跳跃</li>
<li>⏱️ 按住时间越长,跳跃距离越远</li>
<li>🎯 成功落在平台上可得1分</li>
<li>⚠️ 没有落在平台上则游戏结束</li>
<li>🏆 挑战最高分,超越自我!</li>
</ul>
<h2>操作方法:</h2>
<ul>
<li>电脑:鼠标按住按钮</li>
<li>手机:手指按住按钮</li>
</ul>
</div>
<button id="startGame" class="start-btn">开始游戏</button>
</div>
</div>
<div class="game-over" id="gameOver">
<div class="over-content">
<h2>游戏结束</h2>
<p>得分:<span id="finalScore">0</span></p>
<button id="restartGame" class="start-btn">再玩一次</button>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="game.js"></script>
</body>
</html>
css文件
.game-container {
width: 100%;
height: 100vh;
background: #87CEEB;
position: relative;
overflow: hidden;
}
.ui-layer {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 1000;
}
.score {
position: absolute;
top: 20px;
left: 20px;
font-size: 24px;
color: white;
}
.game-area {
width: 100%;
height: 70vh;
position: relative;
background: linear-gradient(to bottom, #87CEEB, #5F9EA0);
}
.player {
width: 30px;
height: 30px;
position: absolute;
bottom: 150px;
left: 50px;
border-radius: 50%;
transition: transform 0.1s;
/* 方案1:渐变色 */
background: linear-gradient(135deg, #FF6B6B, #FF8E53);
box-shadow: 0 2px 8px rgba(255, 107, 107, 0.4);
/* 或者使用这些替代方案: */
/* 方案2:天蓝色系 */
/*
background: linear-gradient(135deg, #4FC3F7, #2196F3);
box-shadow: 0 2px 8px rgba(33, 150, 243, 0.4);
*/
/* 方案3:紫色系 */
/*
background: linear-gradient(135deg, #B39DDB, #673AB7);
box-shadow: 0 2px 8px rgba(103, 58, 183, 0.4);
*/
/* 方案4:绿色系 */
/*
background: linear-gradient(135deg, #81C784, #4CAF50);
box-shadow: 0 2px 8px rgba(76, 175, 80, 0.4);
*/
/* 方案5:金色系 */
/*
background: linear-gradient(135deg, #FFD700, #FFA000);
box-shadow: 0 2px 8px rgba(255, 160, 0, 0.4);
*/
}
.platform {
width: 80px;
height: 20px;
background: linear-gradient(to bottom, #888, #666);
position: absolute;
bottom: 120px;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
}
.current {
left: 40px;
}
.next {
left: 200px;
}
.control {
position: fixed;
bottom: 50px;
left: 0;
width: 100%;
text-align: center;
padding: 20px;
z-index: 1000;
backdrop-filter: blur(5px);
background: rgba(255, 255, 255, 0.1);
}
#jumpBtn {
padding: 15px 40px;
font-size: 18px;
color: white;
background: linear-gradient(135deg, #4CAF50, #45a049);
border: none;
border-radius: 25px;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 4px 15px rgba(76, 175, 80, 0.3);
position: relative;
overflow: hidden;
font-family: 'Arial', sans-serif;
font-weight: bold;
letter-spacing: 1px;
text-transform: uppercase;
transform-style: preserve-3d;
perspective: 1000px;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2);
}
#jumpBtn:not(.disabled):hover {
transform: translateY(-2px) rotateX(5deg);
box-shadow: 0 6px 20px rgba(76, 175, 80, 0.4);
background: linear-gradient(135deg, #45a049, #3d8b40);
}
#jumpBtn:not(.disabled):active {
transform: translateY(1px);
box-shadow: 0 2px 10px rgba(76, 175, 80, 0.3);
}
#jumpBtn.disabled {
background: linear-gradient(135deg, #cccccc, #bbbbbb);
cursor: not-allowed;
opacity: 0.7;
box-shadow: none;
transform: none;
}
#jumpBtn::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 5px;
height: 5px;
background: rgba(255, 255, 255, 0.5);
opacity: 0;
border-radius: 100%;
transform: scale(1, 1) translate(-50%);
transform-origin: 50% 50%;
}
#jumpBtn:not(.disabled):active::after {
animation: ripple 1s ease-out;
}
@keyframes ripple {
0% {
transform: scale(0, 0);
opacity: 0.5;
}
100% {
transform: scale(20, 20);
opacity: 0;
}
}
#jumpBtn::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(
120deg,
transparent,
rgba(255, 255, 255, 0.2),
transparent
);
transition: 0.5s;
}
#jumpBtn:not(.disabled):hover::before {
left: 100%;
}
.game-intro {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.8);
z-index: 999;
display: flex;
justify-content: center;
align-items: center;
}
.intro-content {
background: white;
padding: 30px;
border-radius: 15px;
max-width: 500px;
text-align: center;
}
.intro-content h1 {
color: #4CAF50;
margin-bottom: 20px;
}
.intro-text {
text-align: left;
margin: 20px 0;
}
.intro-text h2 {
color: #333;
margin: 15px 0;
font-size: 1.2em;
}
.intro-text ul {
list-style: none;
padding: 0;
}
.intro-text li {
margin: 10px 0;
color: #666;
font-size: 1.1em;
}
.start-btn {
background: #4CAF50;
color: white;
border: none;
padding: 15px 30px;
font-size: 18px;
border-radius: 5px;
cursor: pointer;
transition: background 0.3s;
}
.start-btn:hover {
background: #45a049;
}
.game-over {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.8);
z-index: 1001;
display: none;
justify-content: center;
align-items: center;
}
.over-content {
background: white;
padding: 30px;
border-radius: 15px;
text-align: center;
animation: popIn 0.3s ease-out;
}
.over-content h2 {
color: #ff4444;
margin-bottom: 20px;
}
.over-content p {
font-size: 24px;
margin-bottom: 20px;
}
.power-hint {
position: absolute;
top: 20px;
right: 20px;
background: rgba(255, 255, 255, 0.9);
padding: 15px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
pointer-events: none;
animation: fadeIn 0.3s ease-out;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.2);
}
.hint-text {
color: #333;
margin-bottom: 10px;
font-size: 16px;
}
.power-bar {
width: 200px;
height: 20px;
background: #eee;
border-radius: 10px;
overflow: hidden;
margin: 10px 0;
transition: all 0.1s ease-out;
}
.power-progress {
width: 0%;
height: 100%;
background: linear-gradient(to right, #4CAF50, #ff4444);
transition: width 0.1s linear, background-color 0.2s ease;
}
.current-power {
color: #666;
font-size: 14px;
}
.background-layer {
position: absolute;
top: 0;
left: 0;
width: 200%;
height: 100%;
background: linear-gradient(to bottom, #87CEEB, #5F9EA0);
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* 添加提示框的响应式样式 */
@media (max-width: 768px) {
.power-hint {
top: 10px;
right: 10px;
padding: 10px;
font-size: 14px;
}
.power-bar {
width: 150px;
}
#jumpBtn {
padding: 12px 30px;
font-size: 16px;
}
.control {
bottom: 30px;
padding: 15px;
}
}
/* 添加禁用状态的样式 */
#jumpBtn.disabled {
background: #cccccc !important;
cursor: not-allowed;
opacity: 0.7;
pointer-events: none; /* 完全禁止点击 */
}
/* 确保禁用状态下不会有hover效果 */
#jumpBtn.disabled:hover {
background: #cccccc;
}
@keyframes popIn {
from {
transform: scale(0.8);
opacity: 0;
}
to {
transform: scale(1);
opacity: 1;
}
}
/* 添加完美时机的视觉效果 */
.perfect-timing {
animation: pulse 0.5s infinite;
}
@keyframes pulse {
0% {
box-shadow: 0 0 0 0 rgba(76, 175, 80, 0.4);
}
70% {
box-shadow: 0 0 0 10px rgba(76, 175, 80, 0);
}
100% {
box-shadow: 0 0 0 0 rgba(76, 175, 80, 0);
}
}
/* 添加跳跃时的光晕效果 */
.player.jumping {
animation: glow 0.6s ease-in-out infinite alternate;
}
@keyframes glow {
from {
box-shadow: 0 2px 8px rgba(255, 107, 107, 0.4);
}
to {
box-shadow: 0 2px 12px rgba(255, 107, 107, 0.8);
}
}
/* 添加蓄力时的效果 */
.player.charging {
animation: pulse 0.5s ease-in-out infinite alternate;
}
@keyframes pulse {
from {
transform: scale(1);
}
to {
transform: scale(1.1);
}
}
/* 添加轨迹效果 */
.player::after {
content: '';
position: absolute;
width: 100%;
height: 100%;
border-radius: 50%;
background: inherit;
filter: blur(8px);
opacity: 0.3;
transform: scale(1.2);
z-index: -1;
}
/* 添加内部光晕 */
.player::before {
content: '';
position: absolute;
width: 60%;
height: 60%;
top: 20%;
left: 20%;
background: rgba(255, 255, 255, 0.3);
border-radius: 50%;
filter: blur(2px);
}
js文件
$(document).ready(function() {
let score = 0;
let isPressed = false;
let pressTime = 0;
let jumping = false;
let gameActive = false;
let viewportOffset = 0;
let chargeInterval = null;
const GAME_CONFIG = {
chargeSpeed: 3,
maxCharge: 1000,
scaleFactor: 0.3,
jumpFactor: 0.3,
jumpHeight: 120,
jumpDuration: 600,
fallDuration: 400,
platformWidth: 80,
landingThreshold: 40
};
initGame();
$('#startGame').click(function() {
gameActive = true;
$('#gameIntro').fadeOut();
$('#jumpBtn').prop('disabled', false);
$('#jumpBtn').removeClass('disabled');
resetGame();
});
function initGame() {
if (chargeInterval) {
clearInterval(chargeInterval);
chargeInterval = null;
}
gameActive = false;
isPressed = false;
pressTime = 0;
jumping = false;
$('#jumpBtn').prop('disabled', true);
$('#jumpBtn').addClass('disabled');
$('#gameIntro').show();
$('.platform').remove();
$('<div>').addClass('platform current').appendTo('.game-area');
$('<div>').addClass('platform next').css('left', '200px').appendTo('.game-area');
$('.player').css({
'left': '50px',
'transform': 'scale(1)'
});
score = 0;
$('#score').text('0');
calculateSuggestedTime();
}
function resetGame() {
score = 0;
$('#score').text(score);
isPressed = false;
pressTime = 0;
jumping = false;
gameActive = true;
if (chargeInterval) {
clearInterval(chargeInterval);
chargeInterval = null;
}
$('#jumpBtn').prop('disabled', false);
$('#jumpBtn').removeClass('disabled');
$('.player').css({
'left': '50px',
'transform': 'scale(1)'
});
$('.platform').remove();
$('<div>').addClass('platform current').appendTo('.game-area');
$('<div>').addClass('platform next').css('left', '200px').appendTo('.game-area');
viewportOffset = 0;
$('.game-area').css('transform', 'translateX(0)');
$('.power-progress').css('width', '0%');
$('#currentTime').text('0.0');
calculateSuggestedTime();
}
function gameOver() {
gameActive = false;
isPressed = false;
jumping = false;
if (chargeInterval) {
clearInterval(chargeInterval);
chargeInterval = null;
}
$('#jumpBtn').prop('disabled', true);
$('#jumpBtn').addClass('disabled');
$('#finalScore').text(score);
$('#gameOver').css('display', 'flex').fadeIn();
}
$('#restartGame').click(function() {
$('#gameOver').fadeOut(function() {
resetGame();
});
});
$('#jumpBtn').on('mousedown touchstart', function(e) {
e.preventDefault();
if (!gameActive || jumping || isPressed) return;
isPressed = true;
pressTime = 0;
if (chargeInterval) {
clearInterval(chargeInterval);
}
chargeInterval = setInterval(chargePower, 10);
});
$('#jumpBtn').on('mouseup touchend', function(e) {
e.preventDefault();
if (!gameActive || jumping || !isPressed) return;
if (chargeInterval) {
clearInterval(chargeInterval);
chargeInterval = null;
}
isPressed = false;
jump();
});
$('#jumpBtn').on('mouseleave touchcancel', function(e) {
if (isPressed) {
if (chargeInterval) {
clearInterval(chargeInterval);
chargeInterval = null;
}
isPressed = false;
if (!jumping) {
jump();
}
}
});
function chargePower() {
if (!isPressed || jumping) return;
pressTime += GAME_CONFIG.chargeSpeed;
if (pressTime >= GAME_CONFIG.maxCharge) {
isPressed = false;
if (chargeInterval) {
clearInterval(chargeInterval);
chargeInterval = null;
}
jump();
return;
}
let scale = 1 + (pressTime/GAME_CONFIG.maxCharge) * GAME_CONFIG.scaleFactor;
$('.player').css('transform', `scale(${scale})`);
updatePowerBar();
$('.player').addClass('charging');
}
function jump() {
if (jumping) return;
jumping = true;
let power = Math.min(pressTime, GAME_CONFIG.maxCharge);
let jumpDistance = power * GAME_CONFIG.jumpFactor;
pressTime = 0;
$('.power-progress').css('width', '0%');
$('#currentTime').text('0.0');
let startPos = $('.player').position();
let time = 0;
let interval = 10;
let animationDuration = GAME_CONFIG.jumpDuration;
let jumpInterval = setInterval(function() {
time += interval;
if (time >= animationDuration) {
clearInterval(jumpInterval);
$('.player').css({
'bottom': '150px'
});
checkLanding();
return;
}
let progress = time / animationDuration;
let horizontalPos = startPos.left + (jumpDistance * progress);
let verticalPos = 150 + GAME_CONFIG.jumpHeight * Math.sin(progress * Math.PI);
$('.player').css({
'left': horizontalPos,
'bottom': verticalPos
});
updateViewport();
}, interval);
$('.player').css('transform', 'scale(1)');
$('.player').removeClass('charging').addClass('jumping');
}
function checkLanding() {
let playerPos = $('.player').position().left + 15;
let nextPlatform = $('.next');
let platformLeft = nextPlatform.position().left;
let platformRight = platformLeft + GAME_CONFIG.platformWidth;
if (playerPos >= platformLeft - GAME_CONFIG.landingThreshold &&
playerPos <= platformRight + GAME_CONFIG.landingThreshold) {
score += 1;
$('#score').text(score);
generateNewPlatform();
} else {
gameOver();
}
jumping = false;
isPressed = false;
if (chargeInterval) {
clearInterval(chargeInterval);
chargeInterval = null;
}
$('.player').removeClass('jumping charging');
}
function generateNewPlatform() {
$('.current').remove();
$('.next').addClass('current').removeClass('next');
let currentPlatformLeft = $('.current').position().left;
let minJumpDistance = GAME_CONFIG.jumpFactor * 300;
let maxJumpDistance = GAME_CONFIG.jumpFactor * 1000;
let jumpDistance = minJumpDistance + Math.random() * (maxJumpDistance - minJumpDistance);
let newPlatformLeft = currentPlatformLeft + jumpDistance;
$('<div>')
.addClass('platform next')
.css('left', newPlatformLeft)
.appendTo('.game-area');
$('.player').css('left', $('.current').position().left + 10);
calculateSuggestedTime();
}
jQuery.easing.easeOutQuad = function (x, t, b, c, d) {
return -c *(t/=d)*(t-2) + b;
};
jQuery.easing.easeInQuad = function (x, t, b, c, d) {
return c*(t/=d)*t + b;
};
function calculateSuggestedTime() {
let currentPlatform = $('.current').position().left;
let nextPlatform = $('.next').position().left;
let distance = nextPlatform - currentPlatform;
let suggestedTime = (distance / (GAME_CONFIG.jumpFactor * 1000));
suggestedTime = Math.min(Math.max(suggestedTime, 0.3), 1.0);
suggestedTime = Math.round(suggestedTime * 10) / 10;
$('#suggestTime').text(suggestedTime.toFixed(1));
return suggestedTime;
}
calculateSuggestedTime();
function updateViewport() {
let playerPos = $('.player').position().left;
let viewportWidth = $(window).width();
if (playerPos - viewportOffset > viewportWidth * 0.5) {
viewportOffset = playerPos - viewportWidth * 0.5;
}
$('.game-area').css('transform', `translateX(-${viewportOffset}px)`);
updateParallax();
cleanupPlatforms();
}
$('.game-area').css({
'position': 'relative',
'transition': 'transform 0.1s ease-out'
});
function updateParallax() {
$('.background-layer').css('transform', `translateX(-${viewportOffset * 0.5}px)`);
}
function preGeneratePlatforms() {
let lastPlatform = $('.next');
for (let i = 0; i < 3; i++) {
let lastLeft = lastPlatform.position().left;
let gap = GAME_CONFIG.minPlatformGap +
Math.random() * (GAME_CONFIG.maxPlatformGap - GAME_CONFIG.minPlatformGap);
let newLeft = lastLeft + gap + GAME_CONFIG.platformWidth;
lastPlatform = $('<div>')
.addClass('platform future')
.css('left', newLeft)
.appendTo('.game-area');
}
}
function cleanupPlatforms() {
$('.platform').each(function() {
if ($(this).position().left < viewportOffset - GAME_CONFIG.platformWidth) {
$(this).remove();
}
});
}
$(document).on('keydown', function(e) {
if (e.code === 'Space' && gameActive) {
e.preventDefault();
$('#jumpBtn').trigger('mousedown');
}
});
$(document).on('keyup', function(e) {
if (e.code === 'Space' && gameActive) {
e.preventDefault();
$('#jumpBtn').trigger('mouseup');
}
});
let gamePaused = false;
$(document).on('keydown', function(e) {
if (e.code === 'Escape' && gameActive) {
gamePaused = !gamePaused;
if (gamePaused) {
showPauseScreen();
} else {
hidePauseScreen();
}
}
});
function updatePowerBar() {
let currentTime = pressTime / 1000;
let suggestedTime = parseFloat($('#suggestTime').text());
let progress = (pressTime / GAME_CONFIG.maxCharge) * 100;
progress = Math.min(progress, 100);
let timeRatio = Math.abs(currentTime - suggestedTime);
if (timeRatio < 0.1) {
$('.power-progress').css('background', '#4CAF50');
} else if (currentTime > suggestedTime) {
$('.power-progress').css('background', '#ff4444');
} else {
$('.power-progress').css('background', '#FFA500');
}
$('.power-progress').css('width', `${progress}%`);
$('#currentTime').text(currentTime.toFixed(1));
if (Math.abs(currentTime - suggestedTime) < 0.1) {
$('.power-hint').addClass('perfect-timing');
} else {
$('.power-hint').removeClass('perfect-timing');
}
}
function debugInfo() {
let currentPlatform = $('.current').position().left;
let nextPlatform = $('.next').position().left;
let distance = nextPlatform - currentPlatform;
let suggestedTime = (distance / (GAME_CONFIG.jumpFactor * 1000));
console.log({
distance: distance,
suggestedTime: suggestedTime,
jumpFactor: GAME_CONFIG.jumpFactor
});
}
});
总结
可以直接下载代码到本地,双击index.html文件即可运行查看效果并体验游戏。