继续更新

This commit is contained in:
2025-10-15 11:11:23 +08:00
parent 7786e5f507
commit c147502b4d
89 changed files with 8116 additions and 2505 deletions

View File

@@ -6,28 +6,6 @@ class GameControls {
}
initControls() {
// 方向按钮控制
document.getElementById('upBtn').addEventListener('click', () => {
this.game.changeDirection(0, -1);
});
document.getElementById('downBtn').addEventListener('click', () => {
this.game.changeDirection(0, 1);
});
document.getElementById('leftBtn').addEventListener('click', () => {
this.game.changeDirection(-1, 0);
});
document.getElementById('rightBtn').addEventListener('click', () => {
this.game.changeDirection(1, 0);
});
// 暂停/继续按钮
document.getElementById('pauseBtn').addEventListener('click', () => {
this.game.togglePause();
});
// 重新开始按钮
document.getElementById('restartBtn').addEventListener('click', () => {
this.game.restart();
@@ -46,62 +24,82 @@ class GameControls {
this.game.restart();
}
break;
case 'p':
case 'P':
this.game.togglePause();
break;
case 'Escape':
if (this.game.gameOver) {
document.getElementById('gameOverModal').style.display = 'none';
}
break;
}
});
}
initTouchControls() {
const canvas = document.getElementById('gameCanvas');
let touchStartX = 0;
let touchStartY = 0;
let isDragging = false;
let lastTouchX = 0;
let lastTouchY = 0;
let lastDirectionChange = 0;
const directionChangeDelay = 200; // 防止方向变化过快
// 触摸开始
canvas.addEventListener('touchstart', (e) => {
touchStartX = e.touches[0].clientX;
touchStartY = e.touches[0].clientY;
isDragging = true;
lastTouchX = e.touches[0].clientX;
lastTouchY = e.touches[0].clientY;
e.preventDefault();
}, { passive: false });
// 拖动过程中实时检测方向
canvas.addEventListener('touchmove', (e) => {
e.preventDefault();
}, { passive: false });
canvas.addEventListener('touchend', (e) => {
const touchEndX = e.changedTouches[0].clientX;
const touchEndY = e.changedTouches[0].clientY;
if (!isDragging) return;
const deltaX = touchEndX - touchStartX;
const deltaY = touchEndY - touchStartY;
const minSwipeDistance = 30;
if (Math.abs(deltaX) > Math.abs(deltaY)) {
// 水平滑动
if (Math.abs(deltaX) > minSwipeDistance) {
if (deltaX > 0) {
this.game.changeDirection(1, 0); // 右滑
} else {
this.game.changeDirection(-1, 0); // 左滑
}
}
} else {
// 垂直滑动
if (Math.abs(deltaY) > minSwipeDistance) {
if (deltaY > 0) {
this.game.changeDirection(0, 1); // 下滑
} else {
this.game.changeDirection(0, -1); // 上滑
}
}
const currentTime = Date.now();
if (currentTime - lastDirectionChange < directionChangeDelay) {
e.preventDefault();
return;
}
const currentTouchX = e.touches[0].clientX;
const currentTouchY = e.touches[0].clientY;
const deltaX = currentTouchX - lastTouchX;
const deltaY = currentTouchY - lastTouchY;
const minDragDistance = 20; // 最小拖动距离
// 检查是否达到最小拖动距离
if (Math.abs(deltaX) > minDragDistance || Math.abs(deltaY) > minDragDistance) {
if (Math.abs(deltaX) > Math.abs(deltaY)) {
// 水平拖动
if (deltaX > 0) {
this.game.changeDirection(1, 0); // 向右拖动
} else {
this.game.changeDirection(-1, 0); // 向左拖动
}
} else {
// 垂直拖动
if (deltaY > 0) {
this.game.changeDirection(0, 1); // 向下拖动
} else {
this.game.changeDirection(0, -1); // 向上拖动
}
}
// 更新最后触摸位置和方向变化时间
lastTouchX = currentTouchX;
lastTouchY = currentTouchY;
lastDirectionChange = currentTime;
// 添加触觉反馈
this.vibrate(30);
}
e.preventDefault();
}, { passive: false });
// 触摸结束
canvas.addEventListener('touchend', (e) => {
isDragging = false;
e.preventDefault();
}, { passive: false });
// 触摸取消
canvas.addEventListener('touchcancel', (e) => {
isDragging = false;
e.preventDefault();
}, { passive: false });
@@ -111,8 +109,71 @@ class GameControls {
e.preventDefault();
}
}, { passive: false });
// 添加鼠标拖动支持(用于桌面测试)
this.initMouseDragControls(canvas);
}
// 鼠标拖动控制(用于桌面测试)
initMouseDragControls(canvas) {
let isDragging = false;
let lastMouseX = 0;
let lastMouseY = 0;
let lastDirectionChange = 0;
const directionChangeDelay = 200;
canvas.addEventListener('mousedown', (e) => {
isDragging = true;
lastMouseX = e.clientX;
lastMouseY = e.clientY;
e.preventDefault();
});
canvas.addEventListener('mousemove', (e) => {
if (!isDragging) return;
const currentTime = Date.now();
if (currentTime - lastDirectionChange < directionChangeDelay) {
return;
}
const currentMouseX = e.clientX;
const currentMouseY = e.clientY;
const deltaX = currentMouseX - lastMouseX;
const deltaY = currentMouseY - lastMouseY;
const minDragDistance = 20;
if (Math.abs(deltaX) > minDragDistance || Math.abs(deltaY) > minDragDistance) {
if (Math.abs(deltaX) > Math.abs(deltaY)) {
if (deltaX > 0) {
this.game.changeDirection(1, 0); // 向右拖动
} else {
this.game.changeDirection(-1, 0); // 向左拖动
}
} else {
if (deltaY > 0) {
this.game.changeDirection(0, 1); // 向下拖动
} else {
this.game.changeDirection(0, -1); // 向上拖动
}
}
lastMouseX = currentMouseX;
lastMouseY = currentMouseY;
lastDirectionChange = currentTime;
}
});
canvas.addEventListener('mouseup', () => {
isDragging = false;
});
canvas.addEventListener('mouseleave', () => {
isDragging = false;
});
}
// 震动反馈(移动端)
vibrate(duration = 50) {
if ('vibrate' in navigator) {

View File

@@ -23,8 +23,7 @@ class SnakeGame {
this.dy = 0;
this.score = 0;
this.level = 1;
this.gameSpeed = 10; // 初始速度
this.isPaused = false;
this.gameSpeed = 6.5; // 初始速度 (10 * 0.65)
this.gameOver = false;
this.startTime = Date.now();
this.foodEaten = 0;
@@ -43,7 +42,7 @@ class SnakeGame {
// 监听键盘事件
document.addEventListener('keydown', (e) => {
if (this.isPaused || this.gameOver) return;
if (this.gameOver) return;
switch(e.key) {
case 'ArrowUp':
@@ -201,7 +200,7 @@ class SnakeGame {
const newLevel = Math.floor(this.foodEaten / 5) + 1;
if (newLevel > this.level) {
this.level = newLevel;
this.gameSpeed = Math.min(20, 10 + this.level); // 速度上限20
this.gameSpeed = Math.min(13, 6.5 + this.level * 0.65); // 速度上限13 (20 * 0.65)
}
}
@@ -297,17 +296,10 @@ class SnakeGame {
}
}
togglePause() {
this.isPaused = !this.isPaused;
document.getElementById('pauseBtn').textContent = this.isPaused ? '继续' : '暂停';
if (!this.isPaused && !this.gameOver) {
this.gameLoop();
}
}
changeDirection(dx, dy) {
if (this.isPaused || this.gameOver) return;
if (this.gameOver) return;
// 防止180度转弯
if ((this.dx !== 0 && dx !== 0) || (this.dy !== 0 && dy !== 0)) {
@@ -319,18 +311,13 @@ class SnakeGame {
}
showGameOver() {
const modal = document.getElementById('gameOverModal');
// 游戏结束时只记录最终状态,不显示弹窗
const gameTime = Math.floor((Date.now() - this.startTime) / 1000);
document.getElementById('finalScore').textContent = this.score;
document.getElementById('finalLength').textContent = this.snake.length;
document.getElementById('finalLevel').textContent = this.level;
document.getElementById('gameTime').textContent = gameTime;
document.getElementById('foodEaten').textContent = this.foodEaten;
modal.style.display = 'flex';
console.log(`游戏结束! 分数: ${this.score}, 长度: ${this.snake.length}, 等级: ${this.level}, 时间: ${gameTime}`);
}
restart() {
this.snake = [
{x: 10, y: 10},
@@ -341,8 +328,7 @@ class SnakeGame {
this.dy = 0;
this.score = 0;
this.level = 1;
this.gameSpeed = 10;
this.isPaused = false;
this.gameSpeed = 6.5;
this.gameOver = false;
this.startTime = Date.now();
this.foodEaten = 0;
@@ -351,9 +337,6 @@ class SnakeGame {
this.generateFood();
this.updateUI();
document.getElementById('gameOverModal').style.display = 'none';
document.getElementById('pauseBtn').textContent = '暂停';
this.gameLoop();
}
}

View File

@@ -0,0 +1,62 @@
const playerdata = [
{
"名称":"树萌芽",
"账号":"3205788256@qq.com",
"分数":1568,
"时间":"2025-09-08"
},
{
"名称":"柚大青",
"账号":"2143323382@qq.com",
"分数":245,
"时间":"2025-09-21"
},
{
"名称":"牛马",
"账号":"2973419538@qq.com",
"分数":1123,
"时间":"2025-09-25"
},
{
"名称":"风行者",
"账号":"4456723190@qq.com",
"分数":1987,
"时间":"2025-09-30"
},
{
"名称":"月光骑士",
"账号":"5832197462@qq.com",
"分数":876,
"时间":"2025-10-02"
},
{
"名称":"星河",
"账号":"6724981532@qq.com",
"分数":1345,
"时间":"2025-10-05"
},
{
"名称":"雷霆",
"账号":"7891234567@qq.com",
"分数":2105,
"时间":"2025-10-08"
},
{
"名称":"火焰猫",
"账号":"8912345678@qq.com",
"分数":654,
"时间":"2025-10-10"
},
{
"名称":"冰雪女王",
"账号":"9123456789@qq.com",
"分数":1789,
"时间":"2025-10-12"
},
{
"名称":"😊",
"账号":"1125234890@qq.com",
"分数":1432,
"时间":"2025-10-15"
}
]

View File

@@ -23,37 +23,18 @@
<div class="game-controls">
<div class="control-row">
<button id="upBtn" class="control-btn"></button>
</div>
<div class="control-row">
<button id="leftBtn" class="control-btn"></button>
<button id="pauseBtn" class="control-btn">暂停</button>
<button id="rightBtn" class="control-btn"></button>
</div>
<div class="control-row">
<button id="downBtn" class="control-btn"></button>
<button id="restartBtn" class="control-btn">重新开始</button>
</div>
</div>
<div class="game-instructions">
<p>使用方向键或触摸按钮控制蛇的方向</p>
<p>使用方向键或拖动手势控制蛇的方向</p>
</div>
</div>
<div id="gameOverModal" class="modal">
<div class="modal-content">
<h2>游戏结束!</h2>
<div class="stats">
<p>最终分数: <span id="finalScore">0</span></p>
<p>蛇的长度: <span id="finalLength">0</span></p>
<p>达到等级: <span id="finalLevel">0</span></p>
<p>游戏时间: <span id="gameTime">0</span></p>
<p>吃掉食物: <span id="foodEaten">0</span></p>
</div>
<button id="restartBtn" class="restart-btn">重新开始</button>
</div>
</div>
<script src="gamedata.js"></script>
<script src="game-core.js"></script>
<script src="game-controls.js"></script>
<script src="game-stats.js"></script>

View File

@@ -6,7 +6,7 @@
body {
font-family: 'Arial', sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
background: linear-gradient(135deg, #a8e6cf 0%, #dcedc8 50%, #f1f8e9 100%);
min-height: 100vh;
display: flex;
justify-content: center;
@@ -16,13 +16,14 @@ body {
}
.game-container {
background: rgba(255, 255, 255, 0.95);
background: linear-gradient(135deg, #e8f5e8 0%, #f1f8e9 100%);
border-radius: 20px;
padding: 20px;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
box-shadow: 0 20px 40px rgba(46, 125, 50, 0.3);
max-width: 400px;
width: 95%;
margin: 20px auto;
border: 1px solid rgba(46, 125, 50, 0.2);
}
.game-header {
@@ -31,21 +32,22 @@ body {
}
.game-header h1 {
color: #333;
color: #1b5e20;
font-size: 2.5rem;
margin-bottom: 15px;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1);
text-shadow: 2px 2px 4px rgba(255, 255, 255, 0.5);
}
.score-board {
display: flex;
justify-content: space-around;
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
background: linear-gradient(135deg, #2e7d32 0%, #388e3c 100%);
padding: 12px;
border-radius: 15px;
color: white;
font-weight: bold;
font-size: 1.1rem;
box-shadow: 0 4px 8px rgba(46, 125, 50, 0.2);
}
.score-board span {
@@ -61,10 +63,10 @@ body {
}
#gameCanvas {
border: 3px solid #333;
border: 3px solid #2e7d32;
border-radius: 10px;
background: #222;
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
background: #1b5e20;
box-shadow: 0 8px 16px rgba(46, 125, 50, 0.3);
}
.game-controls {
@@ -83,33 +85,32 @@ body {
margin: 0 10px;
border: none;
border-radius: 50%;
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
background: linear-gradient(135deg, #4caf50 0%, #66bb6a 100%);
color: white;
font-size: 1.5rem;
font-weight: bold;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
box-shadow: 0 4px 8px rgba(46, 125, 50, 0.3);
}
.control-btn:hover {
transform: scale(1.1);
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3);
box-shadow: 0 6px 12px rgba(46, 125, 50, 0.4);
}
.control-btn:active {
transform: scale(0.95);
box-shadow: 0 2px 4px rgba(46, 125, 50, 0.2);
}
#pauseBtn {
background: linear-gradient(135deg, #ff9a9e 0%, #fad0c4 100%);
color: #333;
background: linear-gradient(135deg, #81c784 0%, #a5d6a7 100%);
color: #1b5e20;
font-size: 1.2rem;
}
.game-instructions {
text-align: center;
color: #666;
color: #2e7d32;
font-size: 0.9rem;
margin-top: 15px;
}
@@ -121,41 +122,43 @@ body {
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.8);
background: rgba(46, 125, 50, 0.6);
z-index: 1000;
justify-content: center;
align-items: center;
}
.modal-content {
background: white;
background: linear-gradient(135deg, #e8f5e8 0%, #f1f8e9 100%);
padding: 30px;
border-radius: 20px;
text-align: center;
max-width: 400px;
width: 90%;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.4);
box-shadow: 0 20px 40px rgba(46, 125, 50, 0.4);
border: 1px solid rgba(46, 125, 50, 0.2);
}
.modal-content h2 {
color: #e74c3c;
color: #1b5e20;
margin-bottom: 20px;
font-size: 2rem;
text-shadow: 1px 1px 2px rgba(255, 255, 255, 0.5);
}
.stats p {
margin: 10px 0;
font-size: 1.1rem;
color: #333;
color: #2e7d32;
}
.stats span {
font-weight: bold;
color: #e74c3c;
color: #1b5e20;
}
.restart-btn {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
background: linear-gradient(135deg, #2e7d32 0%, #388e3c 100%);
color: white;
border: none;
padding: 15px 30px;
@@ -165,11 +168,70 @@ body {
cursor: pointer;
margin-top: 20px;
transition: all 0.3s ease;
box-shadow: 0 4px 8px rgba(46, 125, 50, 0.2);
}
.restart-btn:hover {
transform: scale(1.05);
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
box-shadow: 0 8px 16px rgba(46, 125, 50, 0.3);
}
/* 排行榜样式 */
.leaderboard {
margin: 20px 0;
padding: 15px;
background: rgba(255, 255, 255, 0.3);
border-radius: 15px;
border: 1px solid rgba(46, 125, 50, 0.2);
}
.leaderboard h3 {
color: #1b5e20;
margin-bottom: 15px;
font-size: 1.3rem;
text-align: center;
}
.leaderboard-list {
display: flex;
flex-direction: column;
gap: 8px;
}
.leaderboard-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 12px;
background: rgba(255, 255, 255, 0.5);
border-radius: 10px;
font-size: 0.9rem;
transition: all 0.2s ease;
}
.leaderboard-item.current-player {
background: linear-gradient(135deg, #ffeb3b 0%, #fff176 100%);
font-weight: bold;
border: 2px solid #f57f17;
}
.leaderboard-item .rank {
font-weight: bold;
min-width: 30px;
text-align: left;
}
.leaderboard-item .player-name {
flex: 1;
text-align: left;
margin-left: 10px;
color: #2e7d32;
}
.leaderboard-item .player-score {
font-weight: bold;
color: #1b5e20;
min-width: 50px;
text-align: right;
}
/* 手机端优化 */
@@ -246,13 +308,4 @@ body {
-ms-user-select: none;
}
/* 动画效果 */
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.05); }
100% { transform: scale(1); }
}
.score-board {
animation: pulse 2s infinite;
}
/* 动画效果已删除 */