继续更新
This commit is contained in:
146
InfoGenie-frontend/public/smallgame/2048/controls.js
vendored
146
InfoGenie-frontend/public/smallgame/2048/controls.js
vendored
@@ -26,7 +26,15 @@ class GameControls {
|
||||
}
|
||||
|
||||
initKeyboardControls() {
|
||||
document.addEventListener('keydown', (e) => {
|
||||
// 确保iframe能够获得焦点并接收键盘事件
|
||||
const gameContainer = document.querySelector('.container');
|
||||
if (gameContainer) {
|
||||
gameContainer.setAttribute('tabindex', '0');
|
||||
gameContainer.focus();
|
||||
}
|
||||
|
||||
// 为document和window都添加键盘事件监听器,确保在iframe中也能工作
|
||||
const handleKeyDown = (e) => {
|
||||
if (!this.isGameActive || !window.game2048) {
|
||||
console.log('Game not ready:', { isGameActive: this.isGameActive, game2048: !!window.game2048 });
|
||||
return;
|
||||
@@ -69,7 +77,18 @@ class GameControls {
|
||||
this.togglePause();
|
||||
break;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 同时监听document和window的键盘事件
|
||||
document.addEventListener('keydown', handleKeyDown);
|
||||
window.addEventListener('keydown', handleKeyDown);
|
||||
|
||||
// 确保游戏容器在点击时获得焦点
|
||||
if (gameContainer) {
|
||||
gameContainer.addEventListener('click', () => {
|
||||
gameContainer.focus();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
initTouchControls() {
|
||||
@@ -389,90 +408,6 @@ class GameControls {
|
||||
enable() {
|
||||
this.isGameActive = true;
|
||||
}
|
||||
|
||||
// 显示控制提示
|
||||
showControlHints() {
|
||||
const hints = document.createElement('div');
|
||||
hints.className = 'control-hints';
|
||||
hints.innerHTML = `
|
||||
<div class="hint-content">
|
||||
<h3>操作说明</h3>
|
||||
<div class="hint-section">
|
||||
<h4>📱 手机操作</h4>
|
||||
<p>在游戏区域滑动手指移动方块</p>
|
||||
<div class="gesture-demo">
|
||||
<span>👆 上滑</span>
|
||||
<span>👇 下滑</span>
|
||||
<span>👈 左滑</span>
|
||||
<span>👉 右滑</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hint-section">
|
||||
<h4>⌨️ 键盘操作</h4>
|
||||
<div class="key-demo">
|
||||
<div class="key-row">
|
||||
<span class="key">↑</span>
|
||||
<span class="key">W</span>
|
||||
<span>上移</span>
|
||||
</div>
|
||||
<div class="key-row">
|
||||
<span class="key">↓</span>
|
||||
<span class="key">S</span>
|
||||
<span>下移</span>
|
||||
</div>
|
||||
<div class="key-row">
|
||||
<span class="key">←</span>
|
||||
<span class="key">A</span>
|
||||
<span>左移</span>
|
||||
</div>
|
||||
<div class="key-row">
|
||||
<span class="key">→</span>
|
||||
<span class="key">D</span>
|
||||
<span>右移</span>
|
||||
</div>
|
||||
<div class="key-row">
|
||||
<span class="key">R</span>
|
||||
<span>重新开始</span>
|
||||
</div>
|
||||
<div class="key-row">
|
||||
<span class="key">ESC</span>
|
||||
<span>暂停/继续</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="close-hints">知道了</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// 添加样式
|
||||
hints.style.cssText = `
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 10000;
|
||||
backdrop-filter: blur(5px);
|
||||
`;
|
||||
|
||||
document.body.appendChild(hints);
|
||||
|
||||
// 关闭按钮事件
|
||||
hints.querySelector('.close-hints').addEventListener('click', () => {
|
||||
hints.remove();
|
||||
});
|
||||
|
||||
// 点击背景关闭
|
||||
hints.addEventListener('click', (e) => {
|
||||
if (e.target === hints) {
|
||||
hints.remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 创建全局控制实例
|
||||
@@ -486,8 +421,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
gameControls = new GameControls();
|
||||
console.log('Game controls initialized successfully');
|
||||
|
||||
// 创建帮助按钮
|
||||
createHelpButton();
|
||||
|
||||
} else {
|
||||
console.log('Waiting for game2048 to initialize...');
|
||||
setTimeout(initControls, 100);
|
||||
@@ -497,41 +431,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
initControls();
|
||||
});
|
||||
|
||||
// 创建帮助按钮函数
|
||||
function createHelpButton() {
|
||||
const helpBtn = document.createElement('button');
|
||||
helpBtn.textContent = '❓';
|
||||
helpBtn.title = '操作说明';
|
||||
helpBtn.style.cssText = `
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
border: none;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.2);
|
||||
z-index: 1000;
|
||||
transition: all 0.3s ease;
|
||||
`;
|
||||
|
||||
helpBtn.addEventListener('click', () => {
|
||||
gameControls.showControlHints();
|
||||
});
|
||||
|
||||
helpBtn.addEventListener('mouseenter', () => {
|
||||
helpBtn.style.transform = 'scale(1.1)';
|
||||
});
|
||||
|
||||
helpBtn.addEventListener('mouseleave', () => {
|
||||
helpBtn.style.transform = 'scale(1)';
|
||||
});
|
||||
|
||||
document.body.appendChild(helpBtn);
|
||||
}
|
||||
|
||||
|
||||
// 导出控制实例
|
||||
window.gameControls = gameControls;
|
||||
@@ -4,7 +4,7 @@ class Game2048 {
|
||||
this.size = 4;
|
||||
this.grid = [];
|
||||
this.score = 0;
|
||||
this.bestScore = parseInt(localStorage.getItem('2048-best-score')) || 0;
|
||||
|
||||
this.gameWon = false;
|
||||
this.gameOver = false;
|
||||
this.moved = false;
|
||||
@@ -98,7 +98,6 @@ class Game2048 {
|
||||
|
||||
// 更新分数
|
||||
document.getElementById('score').textContent = this.score;
|
||||
document.getElementById('best-score').textContent = this.bestScore;
|
||||
|
||||
// 更新统计数据显示
|
||||
if (window.gameStats) {
|
||||
@@ -359,9 +358,7 @@ class Game2048 {
|
||||
this.startTimer();
|
||||
}
|
||||
|
||||
keepPlaying() {
|
||||
document.getElementById('game-message').style.display = 'none';
|
||||
}
|
||||
|
||||
|
||||
startTimer() {
|
||||
this.stats.startTime = Date.now();
|
||||
@@ -381,28 +378,13 @@ class Game2048 {
|
||||
}
|
||||
|
||||
bindEvents() {
|
||||
// 重新开始按钮
|
||||
document.getElementById('restart-btn').addEventListener('click', () => {
|
||||
this.restart();
|
||||
});
|
||||
|
||||
// 继续游戏按钮
|
||||
document.getElementById('keep-playing').addEventListener('click', () => {
|
||||
this.keepPlaying();
|
||||
});
|
||||
|
||||
// 重试按钮
|
||||
document.getElementById('retry-btn').addEventListener('click', () => {
|
||||
this.restart();
|
||||
});
|
||||
}
|
||||
|
||||
updateBestScore() {
|
||||
if (this.score > this.bestScore) {
|
||||
this.bestScore = this.score;
|
||||
localStorage.setItem('2048-best-score', this.bestScore.toString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 游戏实例
|
||||
@@ -412,12 +394,7 @@ let game;
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
game = new Game2048();
|
||||
|
||||
// 监听分数变化以更新最高分
|
||||
const originalUpdateDisplay = game.updateDisplay.bind(game);
|
||||
game.updateDisplay = function() {
|
||||
originalUpdateDisplay();
|
||||
this.updateBestScore();
|
||||
};
|
||||
|
||||
|
||||
// 导出游戏实例供其他模块使用
|
||||
window.game2048 = game;
|
||||
|
||||
20
InfoGenie-frontend/public/smallgame/2048/gamedata.js
Normal file
20
InfoGenie-frontend/public/smallgame/2048/gamedata.js
Normal file
@@ -0,0 +1,20 @@
|
||||
const playerdata = [
|
||||
{
|
||||
"名称":"树萌芽",
|
||||
"账号":"3205788256@qq.com",
|
||||
"分数":1232,
|
||||
"时间":"2025-09-08"
|
||||
},
|
||||
{
|
||||
"名称":"柚大青",
|
||||
"账号":"2143323382@qq.com",
|
||||
"分数":132,
|
||||
"时间":"2025-09-21"
|
||||
},
|
||||
{
|
||||
"名称":"牛马",
|
||||
"账号":"2973419538@qq.com",
|
||||
"分数":876,
|
||||
"时间":"2025-09-25"
|
||||
}
|
||||
]
|
||||
@@ -7,7 +7,7 @@
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="container" tabindex="0">
|
||||
<header class="header">
|
||||
<h1 class="title">2048</h1>
|
||||
<div class="score-container">
|
||||
@@ -15,25 +15,14 @@
|
||||
<div class="score-label">分数</div>
|
||||
<div class="score" id="score">0</div>
|
||||
</div>
|
||||
<div class="score-box">
|
||||
<div class="score-label">最高分</div>
|
||||
<div class="score" id="best-score">0</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="game-intro">
|
||||
<p class="game-explanation">
|
||||
合并相同数字,达到<strong>2048</strong>!
|
||||
</p>
|
||||
<div class="restart-button" id="restart-btn">新游戏</div>
|
||||
</div>
|
||||
|
||||
<div class="game-container">
|
||||
<div class="game-message" id="game-message">
|
||||
<p></p>
|
||||
<div class="lower">
|
||||
<a class="keep-playing-button" id="keep-playing">继续游戏</a>
|
||||
<a class="retry-button" id="retry-btn">重新开始</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -70,96 +59,12 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="game-stats" id="game-stats">
|
||||
<h3>游戏统计</h3>
|
||||
<div class="stats-grid">
|
||||
<div class="stat-item">
|
||||
<span class="stat-label">移动次数:</span>
|
||||
<span class="stat-value" id="moves-count">0</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span class="stat-label">游戏时间:</span>
|
||||
<span class="stat-value" id="game-time">00:00</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span class="stat-label">最大数字:</span>
|
||||
<span class="stat-value" id="max-tile">2</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span class="stat-label">合并次数:</span>
|
||||
<span class="stat-value" id="merge-count">0</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="controls-hint">
|
||||
<p><strong>操作说明:</strong></p>
|
||||
<p>手机: 滑动屏幕移动方块</p>
|
||||
<p>电脑: 使用方向键 ↑↓←→ 或 WASD 键</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- 游戏结束统计弹窗 -->
|
||||
<div class="modal" id="stats-modal">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h2>游戏结束</h2>
|
||||
<span class="close" id="close-modal">×</span>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="final-score">
|
||||
<h3>最终得分: <span id="final-score">0</span></h3>
|
||||
</div>
|
||||
<div class="achievement-section">
|
||||
<h4>成就统计</h4>
|
||||
<div class="achievement-grid">
|
||||
<div class="achievement-item">
|
||||
<span class="achievement-icon">🎯</span>
|
||||
<div class="achievement-info">
|
||||
<div class="achievement-title">总移动次数</div>
|
||||
<div class="achievement-value" id="final-moves">0</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="achievement-item">
|
||||
<span class="achievement-icon">⏱️</span>
|
||||
<div class="achievement-info">
|
||||
<div class="achievement-title">游戏时长</div>
|
||||
<div class="achievement-value" id="final-time">00:00</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="achievement-item">
|
||||
<span class="achievement-icon">🏆</span>
|
||||
<div class="achievement-info">
|
||||
<div class="achievement-title">最大数字</div>
|
||||
<div class="achievement-value" id="final-max-tile">2</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="achievement-item">
|
||||
<span class="achievement-icon">🔥</span>
|
||||
<div class="achievement-info">
|
||||
<div class="achievement-title">合并次数</div>
|
||||
<div class="achievement-value" id="final-merges">0</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="achievement-item">
|
||||
<span class="achievement-icon">📊</span>
|
||||
<div class="achievement-info">
|
||||
<div class="achievement-title">平均每步得分</div>
|
||||
<div class="achievement-value" id="avg-score">0</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-actions">
|
||||
<button class="btn btn-primary" id="new-game-btn">开始新游戏</button>
|
||||
<button class="btn btn-secondary" id="share-btn">分享成绩</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script src="game-logic.js"></script>
|
||||
<script src="controls.js"></script>
|
||||
<script src="statistics.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,381 +0,0 @@
|
||||
// 游戏统计模块
|
||||
class GameStatistics {
|
||||
constructor() {
|
||||
this.achievements = {
|
||||
firstWin: false,
|
||||
speedRunner: false, // 5分钟内达到2048
|
||||
efficient: false, // 少于500步达到2048
|
||||
persistent: false, // 游戏时间超过30分钟
|
||||
merger: false, // 单局合并超过100次
|
||||
highScorer: false // 分数超过50000
|
||||
};
|
||||
|
||||
this.loadAchievements();
|
||||
this.initializeModal();
|
||||
}
|
||||
|
||||
updateDisplay() {
|
||||
if (!window.game2048) return;
|
||||
|
||||
const game = window.game2048;
|
||||
|
||||
// 更新实时统计显示
|
||||
document.getElementById('moves-count').textContent = game.stats.moves;
|
||||
document.getElementById('game-time').textContent = this.formatTime(game.stats.gameTime);
|
||||
document.getElementById('max-tile').textContent = game.stats.maxTile;
|
||||
document.getElementById('merge-count').textContent = game.stats.mergeCount;
|
||||
}
|
||||
|
||||
formatTime(seconds) {
|
||||
const minutes = Math.floor(seconds / 60);
|
||||
const remainingSeconds = seconds % 60;
|
||||
return `${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
showFinalStats() {
|
||||
if (!window.game2048) return;
|
||||
|
||||
const game = window.game2048;
|
||||
const modal = document.getElementById('stats-modal');
|
||||
|
||||
// 更新最终统计数据
|
||||
document.getElementById('final-score').textContent = game.score;
|
||||
document.getElementById('final-moves').textContent = game.stats.moves;
|
||||
document.getElementById('final-time').textContent = this.formatTime(game.stats.gameTime);
|
||||
document.getElementById('final-max-tile').textContent = game.stats.maxTile;
|
||||
document.getElementById('final-merges').textContent = game.stats.mergeCount;
|
||||
|
||||
// 计算平均每步得分
|
||||
const avgScore = game.stats.moves > 0 ? Math.round(game.score / game.stats.moves) : 0;
|
||||
document.getElementById('avg-score').textContent = avgScore;
|
||||
|
||||
// 检查成就
|
||||
this.checkAchievements(game);
|
||||
|
||||
// 显示模态框
|
||||
modal.style.display = 'block';
|
||||
|
||||
// 添加动画效果
|
||||
setTimeout(() => {
|
||||
modal.querySelector('.modal-content').style.transform = 'scale(1)';
|
||||
}, 10);
|
||||
}
|
||||
|
||||
checkAchievements(game) {
|
||||
let newAchievements = [];
|
||||
|
||||
// 首次胜利
|
||||
if (game.gameWon && !this.achievements.firstWin) {
|
||||
this.achievements.firstWin = true;
|
||||
newAchievements.push('🏆 首次胜利!达到了2048!');
|
||||
}
|
||||
|
||||
// 速度跑者 - 5分钟内达到2048
|
||||
if (game.gameWon && game.stats.gameTime <= 300 && !this.achievements.speedRunner) {
|
||||
this.achievements.speedRunner = true;
|
||||
newAchievements.push('⚡ 速度跑者!5分钟内达到2048!');
|
||||
}
|
||||
|
||||
// 高效玩家 - 少于500步达到2048
|
||||
if (game.gameWon && game.stats.moves < 500 && !this.achievements.efficient) {
|
||||
this.achievements.efficient = true;
|
||||
newAchievements.push('🎯 高效玩家!少于500步达到2048!');
|
||||
}
|
||||
|
||||
// 坚持不懈 - 游戏时间超过30分钟
|
||||
if (game.stats.gameTime >= 1800 && !this.achievements.persistent) {
|
||||
this.achievements.persistent = true;
|
||||
newAchievements.push('⏰ 坚持不懈!游戏时间超过30分钟!');
|
||||
}
|
||||
|
||||
// 合并大师 - 单局合并超过100次
|
||||
if (game.stats.mergeCount >= 100 && !this.achievements.merger) {
|
||||
this.achievements.merger = true;
|
||||
newAchievements.push('🔥 合并大师!单局合并超过100次!');
|
||||
}
|
||||
|
||||
// 高分玩家 - 分数超过50000
|
||||
if (game.score >= 50000 && !this.achievements.highScorer) {
|
||||
this.achievements.highScorer = true;
|
||||
newAchievements.push('💎 高分玩家!分数超过50000!');
|
||||
}
|
||||
|
||||
// 保存成就
|
||||
if (newAchievements.length > 0) {
|
||||
this.saveAchievements();
|
||||
this.showAchievementNotifications(newAchievements);
|
||||
}
|
||||
}
|
||||
|
||||
showAchievementNotifications(achievements) {
|
||||
// 在成就区域显示新获得的成就
|
||||
const achievementSection = document.querySelector('.achievement-section');
|
||||
|
||||
achievements.forEach((achievement, index) => {
|
||||
setTimeout(() => {
|
||||
const notification = document.createElement('div');
|
||||
notification.className = 'achievement-notification';
|
||||
notification.innerHTML = `
|
||||
<div class="achievement-popup">
|
||||
<span class="achievement-text">${achievement}</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
achievementSection.appendChild(notification);
|
||||
|
||||
// 添加样式
|
||||
const popup = notification.querySelector('.achievement-popup');
|
||||
popup.style.cssText = `
|
||||
background: linear-gradient(45deg, #ff6b6b, #feca57);
|
||||
color: white;
|
||||
padding: 10px 15px;
|
||||
border-radius: 20px;
|
||||
margin: 5px 0;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
animation: achievementSlide 0.5s ease-out;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.2);
|
||||
`;
|
||||
|
||||
// 添加动画样式
|
||||
if (!document.getElementById('achievement-styles')) {
|
||||
const style = document.createElement('style');
|
||||
style.id = 'achievement-styles';
|
||||
style.textContent = `
|
||||
@keyframes achievementSlide {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
|
||||
// 3秒后移除通知
|
||||
setTimeout(() => {
|
||||
if (notification.parentNode) {
|
||||
notification.remove();
|
||||
}
|
||||
}, 3000);
|
||||
}, index * 500);
|
||||
});
|
||||
}
|
||||
|
||||
saveAchievements() {
|
||||
localStorage.setItem('2048-achievements', JSON.stringify(this.achievements));
|
||||
}
|
||||
|
||||
loadAchievements() {
|
||||
const saved = localStorage.getItem('2048-achievements');
|
||||
if (saved) {
|
||||
this.achievements = { ...this.achievements, ...JSON.parse(saved) };
|
||||
}
|
||||
}
|
||||
|
||||
initializeModal() {
|
||||
const modal = document.getElementById('stats-modal');
|
||||
const closeBtn = document.getElementById('close-modal');
|
||||
const newGameBtn = document.getElementById('new-game-btn');
|
||||
const shareBtn = document.getElementById('share-btn');
|
||||
|
||||
// 关闭模态框
|
||||
closeBtn.addEventListener('click', () => {
|
||||
modal.style.display = 'none';
|
||||
});
|
||||
|
||||
// 点击模态框外部关闭
|
||||
modal.addEventListener('click', (e) => {
|
||||
if (e.target === modal) {
|
||||
modal.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
// 新游戏按钮
|
||||
newGameBtn.addEventListener('click', () => {
|
||||
modal.style.display = 'none';
|
||||
if (window.game2048) {
|
||||
window.game2048.restart();
|
||||
}
|
||||
});
|
||||
|
||||
// 分享按钮
|
||||
shareBtn.addEventListener('click', () => {
|
||||
this.shareScore();
|
||||
});
|
||||
|
||||
// ESC键关闭模态框
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape' && modal.style.display === 'block') {
|
||||
modal.style.display = 'none';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
shareScore() {
|
||||
if (!window.game2048) return;
|
||||
|
||||
const game = window.game2048;
|
||||
const shareText = `我在2048游戏中获得了${game.score}分!\n` +
|
||||
`最大数字: ${game.stats.maxTile}\n` +
|
||||
`移动次数: ${game.stats.moves}\n` +
|
||||
`游戏时间: ${this.formatTime(game.stats.gameTime)}\n` +
|
||||
`来挑战一下吧!`;
|
||||
|
||||
// 尝试使用Web Share API
|
||||
if (navigator.share) {
|
||||
navigator.share({
|
||||
title: '2048游戏成绩',
|
||||
text: shareText,
|
||||
url: window.location.href
|
||||
}).catch(err => {
|
||||
console.log('分享失败:', err);
|
||||
this.fallbackShare(shareText);
|
||||
});
|
||||
} else {
|
||||
this.fallbackShare(shareText);
|
||||
}
|
||||
}
|
||||
|
||||
fallbackShare(text) {
|
||||
// 复制到剪贴板
|
||||
if (navigator.clipboard) {
|
||||
navigator.clipboard.writeText(text).then(() => {
|
||||
this.showToast('成绩已复制到剪贴板!');
|
||||
}).catch(() => {
|
||||
this.showShareModal(text);
|
||||
});
|
||||
} else {
|
||||
this.showShareModal(text);
|
||||
}
|
||||
}
|
||||
|
||||
showShareModal(text) {
|
||||
// 创建分享文本显示框
|
||||
const shareModal = document.createElement('div');
|
||||
shareModal.innerHTML = `
|
||||
<div style="
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
background: white;
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 10px 30px rgba(0,0,0,0.3);
|
||||
z-index: 10000;
|
||||
max-width: 90%;
|
||||
text-align: center;
|
||||
">
|
||||
<h3>分享你的成绩</h3>
|
||||
<textarea readonly style="
|
||||
width: 100%;
|
||||
height: 120px;
|
||||
margin: 10px 0;
|
||||
padding: 10px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 5px;
|
||||
resize: none;
|
||||
">${text}</textarea>
|
||||
<div>
|
||||
<button onclick="this.parentElement.parentElement.parentElement.remove()" style="
|
||||
background: #4ecdc4;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 20px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
margin: 0 5px;
|
||||
">关闭</button>
|
||||
<button onclick="
|
||||
this.parentElement.previousElementSibling.select();
|
||||
document.execCommand('copy');
|
||||
alert('已复制到剪贴板!');
|
||||
" style="
|
||||
background: #ff6b6b;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 20px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
margin: 0 5px;
|
||||
">复制</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
document.body.appendChild(shareModal);
|
||||
}
|
||||
|
||||
showToast(message) {
|
||||
const toast = document.createElement('div');
|
||||
toast.textContent = message;
|
||||
toast.style.cssText = `
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
color: white;
|
||||
padding: 12px 24px;
|
||||
border-radius: 25px;
|
||||
z-index: 10000;
|
||||
font-weight: bold;
|
||||
animation: toastSlide 0.3s ease-out;
|
||||
`;
|
||||
|
||||
document.body.appendChild(toast);
|
||||
|
||||
setTimeout(() => {
|
||||
toast.remove();
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
// 获取游戏统计摘要
|
||||
getStatsSummary() {
|
||||
if (!window.game2048) return null;
|
||||
|
||||
const game = window.game2048;
|
||||
return {
|
||||
score: game.score,
|
||||
bestScore: game.bestScore,
|
||||
moves: game.stats.moves,
|
||||
gameTime: game.stats.gameTime,
|
||||
maxTile: game.stats.maxTile,
|
||||
mergeCount: game.stats.mergeCount,
|
||||
achievements: this.achievements
|
||||
};
|
||||
}
|
||||
|
||||
// 重置所有统计数据
|
||||
resetAllStats() {
|
||||
this.achievements = {
|
||||
firstWin: false,
|
||||
speedRunner: false,
|
||||
efficient: false,
|
||||
persistent: false,
|
||||
merger: false,
|
||||
highScorer: false
|
||||
};
|
||||
|
||||
localStorage.removeItem('2048-achievements');
|
||||
localStorage.removeItem('2048-best-score');
|
||||
|
||||
this.showToast('所有统计数据已重置!');
|
||||
}
|
||||
}
|
||||
|
||||
// 创建全局统计实例
|
||||
window.gameStats = new GameStatistics();
|
||||
|
||||
// 页面加载完成后初始化
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// 确保统计模块正确初始化
|
||||
if (!window.gameStats) {
|
||||
window.gameStats = new GameStatistics();
|
||||
}
|
||||
});
|
||||
@@ -7,8 +7,8 @@
|
||||
|
||||
body {
|
||||
font-family: 'Arial', 'Microsoft YaHei', sans-serif;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: #776e65;
|
||||
background: linear-gradient(135deg, #a8e6cf 0%, #dcedc8 50%, #f1f8e9 100%);
|
||||
color: #2e7d32;
|
||||
font-size: 18px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
@@ -21,6 +21,12 @@ body {
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
position: relative;
|
||||
outline: none; /* 移除默认的焦点轮廓 */
|
||||
}
|
||||
|
||||
.container:focus {
|
||||
/* 当容器获得焦点时的样式,用于iframe环境 */
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* 头部样式 */
|
||||
@@ -35,8 +41,8 @@ body {
|
||||
.title {
|
||||
font-size: 48px;
|
||||
font-weight: bold;
|
||||
color: #ffffff;
|
||||
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
|
||||
color: #1b5e20;
|
||||
text-shadow: 2px 2px 4px rgba(255,255,255,0.5);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@@ -46,17 +52,18 @@ body {
|
||||
}
|
||||
|
||||
.score-box {
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
background: linear-gradient(135deg, #c8e6c9 0%, #e8f5e8 100%);
|
||||
padding: 10px 15px;
|
||||
border-radius: 8px;
|
||||
text-align: center;
|
||||
min-width: 80px;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||||
box-shadow: 0 2px 8px rgba(46,125,50,0.2);
|
||||
border: 1px solid rgba(129,199,132,0.3);
|
||||
}
|
||||
|
||||
.score-label {
|
||||
font-size: 12px;
|
||||
color: #776e65;
|
||||
color: #2e7d32;
|
||||
text-transform: uppercase;
|
||||
font-weight: bold;
|
||||
}
|
||||
@@ -64,54 +71,22 @@ body {
|
||||
.score {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
color: #ffffff;
|
||||
background: linear-gradient(45deg, #ff6b6b, #ee5a24);
|
||||
color: #1b5e20;
|
||||
background: linear-gradient(45deg, #4caf50, #66bb6a);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
/* 游戏介绍区域 */
|
||||
.game-intro {
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
padding: 15px;
|
||||
border-radius: 12px;
|
||||
margin-bottom: 20px;
|
||||
text-align: center;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.game-explanation {
|
||||
margin-bottom: 15px;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.restart-button {
|
||||
background: linear-gradient(45deg, #4ecdc4, #44a08d);
|
||||
color: white;
|
||||
padding: 12px 24px;
|
||||
border-radius: 25px;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
transition: all 0.3s ease;
|
||||
display: inline-block;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.restart-button:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 16px rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
/* 游戏容器 */
|
||||
.game-container {
|
||||
position: relative;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
background: linear-gradient(135deg, #e8f5e8 0%, #f1f8e9 100%);
|
||||
border-radius: 12px;
|
||||
padding: 15px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
||||
box-shadow: 0 4px 12px rgba(46,125,50,0.15);
|
||||
border: 1px solid rgba(129,199,132,0.2);
|
||||
}
|
||||
|
||||
/* 网格样式 */
|
||||
@@ -132,7 +107,7 @@ body {
|
||||
.grid-cell {
|
||||
width: calc(25% - 6px);
|
||||
height: 80px;
|
||||
background: rgba(238, 228, 218, 0.35);
|
||||
background: rgba(200, 230, 201, 0.4);
|
||||
border-radius: 8px;
|
||||
margin-right: 8px;
|
||||
position: relative;
|
||||
@@ -168,17 +143,17 @@ body {
|
||||
}
|
||||
|
||||
/* 不同数字的颜色 */
|
||||
.tile-2 { background: #eee4da; color: #776e65; }
|
||||
.tile-4 { background: #ede0c8; color: #776e65; }
|
||||
.tile-8 { background: #f2b179; color: #f9f6f2; }
|
||||
.tile-16 { background: #f59563; color: #f9f6f2; }
|
||||
.tile-32 { background: #f67c5f; color: #f9f6f2; }
|
||||
.tile-64 { background: #f65e3b; color: #f9f6f2; }
|
||||
.tile-128 { background: #edcf72; color: #f9f6f2; font-size: 28px; }
|
||||
.tile-256 { background: #edcc61; color: #f9f6f2; font-size: 28px; }
|
||||
.tile-512 { background: #edc850; color: #f9f6f2; font-size: 28px; }
|
||||
.tile-1024 { background: #edc53f; color: #f9f6f2; font-size: 24px; }
|
||||
.tile-2048 { background: #edc22e; color: #f9f6f2; font-size: 24px; box-shadow: 0 0 20px rgba(237, 194, 46, 0.5); }
|
||||
.tile-2 { background: #e8f5e8; color: #2e7d32; }
|
||||
.tile-4 { background: #c8e6c9; color: #1b5e20; }
|
||||
.tile-8 { background: #a5d6a7; color: #ffffff; }
|
||||
.tile-16 { background: #81c784; color: #ffffff; }
|
||||
.tile-32 { background: #66bb6a; color: #ffffff; }
|
||||
.tile-64 { background: #4caf50; color: #ffffff; }
|
||||
.tile-128 { background: #43a047; color: #ffffff; font-size: 28px; }
|
||||
.tile-256 { background: #388e3c; color: #ffffff; font-size: 28px; }
|
||||
.tile-512 { background: #2e7d32; color: #ffffff; font-size: 28px; }
|
||||
.tile-1024 { background: #1b5e20; color: #ffffff; font-size: 24px; }
|
||||
.tile-2048 { background: #0d4e14; color: #ffffff; font-size: 24px; box-shadow: 0 0 20px rgba(76, 175, 80, 0.6); }
|
||||
.tile-super { background: #3c3a32; color: #f9f6f2; font-size: 20px; }
|
||||
|
||||
/* 动画效果 */
|
||||
@@ -251,7 +226,6 @@ body {
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.keep-playing-button,
|
||||
.retry-button {
|
||||
background: #8f7a66;
|
||||
color: #f9f6f2;
|
||||
@@ -263,237 +237,16 @@ body {
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.keep-playing-button:hover,
|
||||
.retry-button:hover {
|
||||
background: #9f8a76;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
/* 游戏统计 */
|
||||
.game-stats {
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
padding: 15px;
|
||||
border-radius: 12px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.game-stats h3 {
|
||||
text-align: center;
|
||||
margin-bottom: 15px;
|
||||
color: #776e65;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.stats-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.stat-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 8px 12px;
|
||||
background: rgba(238, 228, 218, 0.3);
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 14px;
|
||||
color: #776e65;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-weight: bold;
|
||||
color: #f67c5f;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
/* 操作提示 */
|
||||
.controls-hint {
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
padding: 15px;
|
||||
border-radius: 12px;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.controls-hint p {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.controls-hint p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* 模态框样式 */
|
||||
.modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 1000;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
backdrop-filter: blur(5px);
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background-color: #fefefe;
|
||||
margin: 5% auto;
|
||||
border-radius: 15px;
|
||||
width: 90%;
|
||||
max-width: 500px;
|
||||
max-height: 90vh;
|
||||
overflow-y: auto;
|
||||
box-shadow: 0 10px 30px rgba(0,0,0,0.3);
|
||||
animation: modalSlideIn 0.3s ease-out;
|
||||
}
|
||||
|
||||
@keyframes modalSlideIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-50px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
padding: 20px;
|
||||
border-bottom: 1px solid #eee;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
border-radius: 15px 15px 0 0;
|
||||
}
|
||||
|
||||
.modal-header h2 {
|
||||
margin: 0;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.close {
|
||||
color: white;
|
||||
font-size: 28px;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
.close:hover {
|
||||
color: #ddd;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.final-score {
|
||||
text-align: center;
|
||||
margin-bottom: 25px;
|
||||
padding: 20px;
|
||||
background: linear-gradient(135deg, #ff9a9e 0%, #fecfef 100%);
|
||||
border-radius: 10px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.final-score h3 {
|
||||
margin: 0;
|
||||
font-size: 28px;
|
||||
text-shadow: 1px 1px 2px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.achievement-section h4 {
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
color: #776e65;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.achievement-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 15px;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.achievement-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 15px;
|
||||
background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%);
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.achievement-item:hover {
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.achievement-icon {
|
||||
font-size: 32px;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.achievement-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.achievement-title {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.achievement-value {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.modal-actions {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 12px 24px;
|
||||
border: none;
|
||||
border-radius: 25px;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: linear-gradient(45deg, #4ecdc4, #44a08d);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: linear-gradient(45deg, #ff9a9e, #fecfef);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 16px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
/* 手机端优化 */
|
||||
@media (max-width: 480px) {
|
||||
@@ -540,18 +293,7 @@ body {
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
margin: 10% auto;
|
||||
width: 95%;
|
||||
}
|
||||
|
||||
.achievement-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.modal-actions {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* 超小屏幕优化 */
|
||||
@@ -590,21 +332,12 @@ body {
|
||||
font-size: 36px;
|
||||
}
|
||||
|
||||
.achievement-grid {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
|
||||
.modal-actions {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* 触摸优化 */
|
||||
@media (hover: none) and (pointer: coarse) {
|
||||
.restart-button,
|
||||
.keep-playing-button,
|
||||
.retry-button,
|
||||
.btn {
|
||||
.retry-button {
|
||||
min-height: 44px;
|
||||
min-width: 44px;
|
||||
}
|
||||
|
||||
@@ -35,24 +35,32 @@ class GameControls {
|
||||
|
||||
switch(key) {
|
||||
case 'ArrowLeft':
|
||||
case 'a':
|
||||
case 'A':
|
||||
e.preventDefault();
|
||||
this.game.moveLeft();
|
||||
this.startKeyRepeat('ArrowLeft', () => this.game.moveLeft());
|
||||
this.startKeyRepeat(key, () => this.game.moveLeft());
|
||||
break;
|
||||
|
||||
case 'ArrowRight':
|
||||
case 'd':
|
||||
case 'D':
|
||||
e.preventDefault();
|
||||
this.game.moveRight();
|
||||
this.startKeyRepeat('ArrowRight', () => this.game.moveRight());
|
||||
this.startKeyRepeat(key, () => this.game.moveRight());
|
||||
break;
|
||||
|
||||
case 'ArrowDown':
|
||||
case 's':
|
||||
case 'S':
|
||||
e.preventDefault();
|
||||
this.game.moveDown();
|
||||
this.startKeyRepeat('ArrowDown', () => this.game.moveDown());
|
||||
this.startKeyRepeat(key, () => this.game.moveDown());
|
||||
break;
|
||||
|
||||
case 'ArrowUp':
|
||||
case 'w':
|
||||
case 'W':
|
||||
e.preventDefault();
|
||||
this.game.rotatePiece();
|
||||
break;
|
||||
|
||||
20
InfoGenie-frontend/public/smallgame/俄罗斯方块/gamedata.js
Normal file
20
InfoGenie-frontend/public/smallgame/俄罗斯方块/gamedata.js
Normal file
@@ -0,0 +1,20 @@
|
||||
const playerdata = [
|
||||
{
|
||||
"名称":"树萌芽",
|
||||
"账号":"3205788256@qq.com",
|
||||
"分数":1232,
|
||||
"时间":"2025-09-08"
|
||||
},
|
||||
{
|
||||
"名称":"柚大青",
|
||||
"账号":"2143323382@qq.com",
|
||||
"分数":132,
|
||||
"时间":"2025-09-21"
|
||||
},
|
||||
{
|
||||
"名称":"牛马",
|
||||
"账号":"2973419538@qq.com",
|
||||
"分数":876,
|
||||
"时间":"2025-09-25"
|
||||
}
|
||||
]
|
||||
@@ -40,30 +40,6 @@
|
||||
</div>
|
||||
|
||||
<div class="game-sidebar">
|
||||
<div class="next-piece">
|
||||
<h3>下一个</h3>
|
||||
<canvas id="nextCanvas" width="120" height="120"></canvas>
|
||||
</div>
|
||||
|
||||
<div class="controls-info">
|
||||
<h3>操作说明</h3>
|
||||
<div class="control-item">
|
||||
<span class="key">←→</span>
|
||||
<span class="desc">移动</span>
|
||||
</div>
|
||||
<div class="control-item">
|
||||
<span class="key">↓</span>
|
||||
<span class="desc">快速下降</span>
|
||||
</div>
|
||||
<div class="control-item">
|
||||
<span class="key">↑</span>
|
||||
<span class="desc">旋转</span>
|
||||
</div>
|
||||
<div class="control-item">
|
||||
<span class="key">空格</span>
|
||||
<span class="desc">暂停/继续</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
|
||||
body {
|
||||
font-family: 'Arial', sans-serif;
|
||||
background: linear-gradient(135deg, #1e3c72, #2a5298);
|
||||
color: white;
|
||||
background: linear-gradient(135deg, #e8f5e8 0%, #f1f8e9 30%, #f9fbe7 70%, #f0f4c3 100%);
|
||||
color: #2e7d32;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
user-select: none;
|
||||
@@ -23,6 +23,10 @@ body {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 10px;
|
||||
background: linear-gradient(135deg, rgba(232, 245, 232, 0.4) 0%, rgba(241, 248, 233, 0.4) 50%, rgba(249, 251, 231, 0.4) 100%);
|
||||
border-radius: 20px;
|
||||
box-shadow: 0 10px 30px rgba(139, 195, 74, 0.2);
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
/* 游戏头部 */
|
||||
@@ -34,7 +38,12 @@ body {
|
||||
.game-header h1 {
|
||||
font-size: 2rem;
|
||||
margin-bottom: 10px;
|
||||
text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
|
||||
background: linear-gradient(135deg, #4caf50 0%, #8bc34a 50%, #cddc39 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
text-shadow: 2px 2px 4px rgba(255, 255, 255, 0.3);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.score-board {
|
||||
@@ -45,16 +54,24 @@ body {
|
||||
}
|
||||
|
||||
.score-item {
|
||||
background: rgba(255,255,255,0.1);
|
||||
background: linear-gradient(135deg, #66bb6a 0%, #8bc34a 50%, #aed581 100%);
|
||||
color: white;
|
||||
padding: 8px 15px;
|
||||
border-radius: 20px;
|
||||
backdrop-filter: blur(10px);
|
||||
border: 1px solid rgba(255,255,255,0.2);
|
||||
border: 1px solid rgba(139, 195, 74, 0.3);
|
||||
box-shadow: 0 4px 12px rgba(139, 195, 74, 0.3);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.score-item:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 16px rgba(139, 195, 74, 0.4);
|
||||
}
|
||||
|
||||
.score-item .label {
|
||||
font-size: 0.9rem;
|
||||
opacity: 0.8;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.score-item span:last-child {
|
||||
@@ -73,15 +90,30 @@ body {
|
||||
|
||||
.game-board {
|
||||
position: relative;
|
||||
border-radius: 10px;
|
||||
border-radius: 15px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 10px 30px rgba(0,0,0,0.3);
|
||||
box-shadow: 0 15px 35px rgba(139, 195, 74, 0.3);
|
||||
background: linear-gradient(135deg, #e8f5e8 0%, #f1f8e9 50%, #f9fbe7 100%);
|
||||
border: 3px solid transparent;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
|
||||
.game-board::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -3px;
|
||||
left: -3px;
|
||||
right: -3px;
|
||||
bottom: -3px;
|
||||
background: linear-gradient(135deg, #66bb6a 0%, #8bc34a 50%, #aed581 100%);
|
||||
border-radius: 15px;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
#gameCanvas {
|
||||
display: block;
|
||||
background: #1a1a1a;
|
||||
border: 2px solid #333;
|
||||
background: linear-gradient(135deg, #2e7d32 0%, #388e3c 50%, #4caf50 100%);
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
/* 游戏覆盖层 */
|
||||
@@ -91,34 +123,44 @@ body {
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0,0,0,0.8);
|
||||
background: rgba(139, 195, 74, 0.8);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
backdrop-filter: blur(5px);
|
||||
backdrop-filter: blur(8px);
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.overlay-content {
|
||||
text-align: center;
|
||||
background: rgba(255,255,255,0.1);
|
||||
background: linear-gradient(135deg, #e8f5e8 0%, #f1f8e9 50%, #f9fbe7 100%);
|
||||
color: #2e7d32;
|
||||
padding: 30px;
|
||||
border-radius: 15px;
|
||||
border: 1px solid rgba(255,255,255,0.2);
|
||||
border-radius: 20px;
|
||||
border: 2px solid rgba(139, 195, 74, 0.4);
|
||||
box-shadow: 0 15px 30px rgba(139, 195, 74, 0.3);
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.overlay-content h2 {
|
||||
margin-bottom: 15px;
|
||||
font-size: 1.8rem;
|
||||
background: linear-gradient(135deg, #4caf50 0%, #8bc34a 50%, #cddc39 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.overlay-content p {
|
||||
margin-bottom: 20px;
|
||||
opacity: 0.8;
|
||||
color: #388e3c;
|
||||
}
|
||||
|
||||
/* 游戏按钮 */
|
||||
.game-btn {
|
||||
background: linear-gradient(45deg, #667eea, #764ba2);
|
||||
background: linear-gradient(45deg, #66bb6a 0%, #8bc34a 50%, #aed581 100%);
|
||||
border: none;
|
||||
color: white;
|
||||
padding: 12px 24px;
|
||||
@@ -127,12 +169,14 @@ body {
|
||||
font-size: 1rem;
|
||||
margin: 5px;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
|
||||
box-shadow: 0 4px 15px rgba(139, 195, 74, 0.3);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.game-btn:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 20px rgba(0,0,0,0.3);
|
||||
box-shadow: 0 6px 20px rgba(139, 195, 74, 0.4);
|
||||
background: linear-gradient(45deg, #8bc34a 0%, #aed581 50%, #c5e1a5 100%);
|
||||
}
|
||||
|
||||
.game-btn:active {
|
||||
@@ -147,58 +191,7 @@ body {
|
||||
min-width: 150px;
|
||||
}
|
||||
|
||||
.next-piece {
|
||||
background: rgba(255,255,255,0.1);
|
||||
padding: 15px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid rgba(255,255,255,0.2);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.next-piece h3 {
|
||||
margin-bottom: 10px;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
#nextCanvas {
|
||||
background: #1a1a1a;
|
||||
border: 1px solid #333;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.controls-info {
|
||||
background: rgba(255,255,255,0.1);
|
||||
padding: 15px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid rgba(255,255,255,0.2);
|
||||
}
|
||||
|
||||
.controls-info h3 {
|
||||
margin-bottom: 15px;
|
||||
font-size: 1.1rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.control-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 8px;
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
.control-item .key {
|
||||
background: rgba(255,255,255,0.2);
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
font-family: monospace;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.control-item .desc {
|
||||
font-size: 0.9rem;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
/* 手机端控制 */
|
||||
.mobile-controls {
|
||||
@@ -234,15 +227,15 @@ body {
|
||||
height: 55px;
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(45deg, #667eea, #764ba2);
|
||||
background: linear-gradient(45deg, #66bb6a 0%, #8bc34a 50%, #aed581 100%);
|
||||
color: white;
|
||||
font-size: 1.4rem;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
box-shadow: 0 4px 15px rgba(0,0,0,0.3);
|
||||
box-shadow: 0 4px 15px rgba(139, 195, 74, 0.3);
|
||||
user-select: none;
|
||||
backdrop-filter: blur(10px);
|
||||
border: 2px solid rgba(255,255,255,0.2);
|
||||
border: 2px solid rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
.control-btn:active {
|
||||
@@ -257,7 +250,7 @@ body {
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0,0,0,0.9);
|
||||
background: rgba(46, 125, 50, 0.9);
|
||||
display: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@@ -266,13 +259,15 @@ body {
|
||||
}
|
||||
|
||||
.stats-content {
|
||||
background: linear-gradient(135deg, #667eea, #764ba2);
|
||||
background: linear-gradient(135deg, #e8f5e8 0%, #f1f8e9 100%);
|
||||
color: #1b5e20;
|
||||
padding: 30px;
|
||||
border-radius: 20px;
|
||||
text-align: center;
|
||||
max-width: 90%;
|
||||
width: 400px;
|
||||
box-shadow: 0 20px 40px rgba(0,0,0,0.3);
|
||||
box-shadow: 0 20px 40px rgba(46, 125, 50, 0.4);
|
||||
border: 1px solid rgba(46, 125, 50, 0.3);
|
||||
}
|
||||
|
||||
.stats-content h2 {
|
||||
@@ -289,16 +284,18 @@ body {
|
||||
}
|
||||
|
||||
.stat-item {
|
||||
background: rgba(255,255,255,0.1);
|
||||
background: linear-gradient(135deg, #2e7d32 0%, #388e3c 100%);
|
||||
color: white;
|
||||
padding: 15px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid rgba(255,255,255,0.2);
|
||||
border: 1px solid rgba(46, 125, 50, 0.3);
|
||||
box-shadow: 0 4px 8px rgba(46, 125, 50, 0.2);
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
display: block;
|
||||
font-size: 0.9rem;
|
||||
opacity: 0.8;
|
||||
opacity: 0.9;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
@@ -309,7 +306,8 @@ body {
|
||||
}
|
||||
|
||||
.achievement {
|
||||
background: linear-gradient(45deg, #f093fb, #f5576c);
|
||||
background: linear-gradient(45deg, #81c784, #66bb6a);
|
||||
color: white;
|
||||
padding: 15px;
|
||||
border-radius: 10px;
|
||||
margin-bottom: 25px;
|
||||
@@ -318,6 +316,7 @@ body {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 4px 8px rgba(46, 125, 50, 0.3);
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@@ -359,11 +358,7 @@ body {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.next-piece,
|
||||
.controls-info {
|
||||
flex: 1;
|
||||
max-width: 200px;
|
||||
}
|
||||
|
||||
|
||||
.mobile-controls {
|
||||
display: block;
|
||||
@@ -428,10 +423,7 @@ body {
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.next-piece,
|
||||
.controls-info {
|
||||
max-width: unset;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* 隐藏类 */
|
||||
|
||||
@@ -3,8 +3,6 @@ class TetrisGame {
|
||||
constructor() {
|
||||
this.canvas = document.getElementById('gameCanvas');
|
||||
this.ctx = this.canvas.getContext('2d');
|
||||
this.nextCanvas = document.getElementById('nextCanvas');
|
||||
this.nextCtx = this.nextCanvas.getContext('2d');
|
||||
|
||||
// 游戏配置
|
||||
this.BOARD_WIDTH = 10;
|
||||
@@ -140,7 +138,6 @@ class TetrisGame {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.drawNextPiece();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -348,39 +345,7 @@ class TetrisGame {
|
||||
}
|
||||
}
|
||||
|
||||
drawNextPiece() {
|
||||
this.nextCtx.clearRect(0, 0, this.nextCanvas.width, this.nextCanvas.height);
|
||||
|
||||
if (this.nextPiece) {
|
||||
const size = 20;
|
||||
const matrix = this.nextPiece.matrix;
|
||||
const offsetX = (this.nextCanvas.width - matrix[0].length * size) / 2;
|
||||
const offsetY = (this.nextCanvas.height - matrix.length * size) / 2;
|
||||
|
||||
this.nextCtx.fillStyle = this.nextPiece.color;
|
||||
|
||||
for (let row = 0; row < matrix.length; row++) {
|
||||
for (let col = 0; col < matrix[row].length; col++) {
|
||||
if (matrix[row][col] !== 0) {
|
||||
this.nextCtx.fillRect(
|
||||
offsetX + col * size,
|
||||
offsetY + row * size,
|
||||
size,
|
||||
size
|
||||
);
|
||||
this.nextCtx.strokeStyle = '#333';
|
||||
this.nextCtx.lineWidth = 1;
|
||||
this.nextCtx.strokeRect(
|
||||
offsetX + col * size,
|
||||
offsetY + row * size,
|
||||
size,
|
||||
size
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
updateDisplay() {
|
||||
document.getElementById('score').textContent = this.score;
|
||||
|
||||
20
InfoGenie-frontend/public/smallgame/别踩白方块/gamedata.js
Normal file
20
InfoGenie-frontend/public/smallgame/别踩白方块/gamedata.js
Normal file
@@ -0,0 +1,20 @@
|
||||
const playerdata = [
|
||||
{
|
||||
"名称":"树萌芽",
|
||||
"账号":"3205788256@qq.com",
|
||||
"分数":1232,
|
||||
"时间":"2025-09-08"
|
||||
},
|
||||
{
|
||||
"名称":"柚大青",
|
||||
"账号":"2143323382@qq.com",
|
||||
"分数":132,
|
||||
"时间":"2025-09-21"
|
||||
},
|
||||
{
|
||||
"名称":"牛马",
|
||||
"账号":"2973419538@qq.com",
|
||||
"分数":876,
|
||||
"时间":"2025-09-25"
|
||||
}
|
||||
]
|
||||
@@ -11,7 +11,7 @@
|
||||
}
|
||||
|
||||
body {
|
||||
background: #f5f5f5;
|
||||
background: linear-gradient(135deg, #a8e6cf 0%, #dcedc8 50%, #f1f8e9 100%);
|
||||
font-family: 'Arial', 'Microsoft YaHei', sans-serif;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
@@ -25,41 +25,45 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
background: white;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
|
||||
background: linear-gradient(135deg, #e8f5e8 0%, #f1f8e9 100%);
|
||||
border-radius: 15px;
|
||||
box-shadow: 0 10px 30px rgba(46,125,50,0.3);
|
||||
padding: 20px;
|
||||
position: relative;
|
||||
border: 1px solid rgba(129,199,132,0.2);
|
||||
}
|
||||
|
||||
.game-title {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
color: #1b5e20;
|
||||
margin-bottom: 10px;
|
||||
text-align: center;
|
||||
text-shadow: 1px 1px 2px rgba(255,255,255,0.5);
|
||||
}
|
||||
|
||||
.score-display {
|
||||
position: relative;
|
||||
width: 300px;
|
||||
height: 60px;
|
||||
background: #333;
|
||||
background: linear-gradient(135deg, #2e7d32 0%, #388e3c 100%);
|
||||
border-radius: 8px 8px 0 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 2px 8px rgba(46,125,50,0.3);
|
||||
}
|
||||
|
||||
.game-container {
|
||||
position: relative;
|
||||
width: 300px;
|
||||
height: 600px;
|
||||
border: 3px solid #333;
|
||||
border: 3px solid #2e7d32;
|
||||
border-top: none;
|
||||
border-radius: 0 0 8px 8px;
|
||||
overflow: hidden;
|
||||
background: white;
|
||||
box-shadow: 0 4px 12px rgba(46,125,50,0.2);
|
||||
}
|
||||
|
||||
.control-panel {
|
||||
@@ -82,28 +86,32 @@
|
||||
}
|
||||
|
||||
.start-btn {
|
||||
background: #4CAF50;
|
||||
background: linear-gradient(45deg, #66bb6a, #4caf50);
|
||||
color: white;
|
||||
box-shadow: 0 4px 12px rgba(76,175,80,0.3);
|
||||
}
|
||||
|
||||
.start-btn:hover {
|
||||
background: #45a049;
|
||||
background: linear-gradient(45deg, #4caf50, #388e3c);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 16px rgba(76,175,80,0.4);
|
||||
}
|
||||
|
||||
.pause-btn {
|
||||
background: #ff9800;
|
||||
background: linear-gradient(45deg, #81c784, #66bb6a);
|
||||
color: white;
|
||||
box-shadow: 0 4px 12px rgba(129,199,132,0.3);
|
||||
}
|
||||
|
||||
.pause-btn:hover {
|
||||
background: #e68900;
|
||||
background: linear-gradient(45deg, #66bb6a, #4caf50);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 16px rgba(129,199,132,0.4);
|
||||
}
|
||||
|
||||
.instructions {
|
||||
text-align: center;
|
||||
color: #666;
|
||||
color: #2e7d32;
|
||||
font-size: 14px;
|
||||
margin-top: 10px;
|
||||
line-height: 1.4;
|
||||
@@ -124,30 +132,32 @@
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background: white;
|
||||
background: linear-gradient(135deg, #e8f5e8 0%, #f1f8e9 100%);
|
||||
padding: 30px;
|
||||
border-radius: 15px;
|
||||
text-align: center;
|
||||
box-shadow: 0 20px 40px rgba(0,0,0,0.3);
|
||||
box-shadow: 0 20px 40px rgba(46,125,50,0.3);
|
||||
max-width: 300px;
|
||||
width: 90%;
|
||||
border: 1px solid rgba(129,199,132,0.3);
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
color: #e74c3c;
|
||||
color: #c62828;
|
||||
margin-bottom: 15px;
|
||||
text-shadow: 1px 1px 2px rgba(255,255,255,0.5);
|
||||
}
|
||||
|
||||
.final-score, .final-speed {
|
||||
font-size: 18px;
|
||||
margin: 15px 0;
|
||||
color: #333;
|
||||
color: #1b5e20;
|
||||
}
|
||||
|
||||
.final-speed {
|
||||
color: #666;
|
||||
color: #2e7d32;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
@@ -163,12 +173,14 @@
|
||||
}
|
||||
|
||||
.restart-btn {
|
||||
background: #4CAF50;
|
||||
background: linear-gradient(45deg, #66bb6a, #4caf50);
|
||||
color: white;
|
||||
box-shadow: 0 4px 12px rgba(76,175,80,0.3);
|
||||
}
|
||||
|
||||
.restart-btn:hover {
|
||||
background: #45a049;
|
||||
background: linear-gradient(45deg, #4caf50, #388e3c);
|
||||
box-shadow: 0 6px 16px rgba(76,175,80,0.4);
|
||||
}
|
||||
|
||||
/* 移动端适配 */
|
||||
|
||||
@@ -1,62 +1,62 @@
|
||||
/* 经典扫雷 - 手机竖屏优先 + 电脑端适配 */
|
||||
:root{
|
||||
--bg:#0f172a;
|
||||
--panel:#111827;
|
||||
--accent:#22d3ee;
|
||||
--accent-2:#60a5fa;
|
||||
--text:#e5e7eb;
|
||||
--muted:#94a3b8;
|
||||
--danger:#ef4444;
|
||||
--bg:#e8f5e8;
|
||||
--panel:#c8e6c9;
|
||||
--accent:#2e7d32;
|
||||
--accent-2:#388e3c;
|
||||
--text:#1b5e20;
|
||||
--muted:#4caf50;
|
||||
--danger:#d32f2f;
|
||||
--success:#22c55e;
|
||||
--warn:#f59e0b;
|
||||
--cell:#1f2937;
|
||||
--cell-hover:#273244;
|
||||
--flag:#fb7185;
|
||||
--warn:#f57c00;
|
||||
--cell:#f1f8e9;
|
||||
--cell-hover:#dcedc8;
|
||||
--flag:#4caf50;
|
||||
}
|
||||
*{box-sizing:border-box}
|
||||
html,body{height:100%;}
|
||||
body{margin:0;background:linear-gradient(180deg,#0b1220,#0f172a);color:var(--text);font-family:system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial,"PingFang SC","Microsoft Yahei",sans-serif;-webkit-tap-highlight-color:transparent}
|
||||
body{margin:0;background:linear-gradient(135deg, #a8e6cf 0%, #dcedc8 50%, #f1f8e9 100%);color:var(--text);font-family:system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial,"PingFang SC","Microsoft Yahei",sans-serif;-webkit-tap-highlight-color:transparent}
|
||||
|
||||
.app{min-height:100dvh;display:flex;flex-direction:column;gap:12px;padding:12px;}
|
||||
.header{display:flex;flex-direction:column;gap:10px;background:rgba(255,255,255,0.02);border:1px solid rgba(255,255,255,0.06);border-radius:14px;padding:12px 12px 10px;backdrop-filter:blur(6px)}
|
||||
.title{margin:0;font-size:20px;letter-spacing:1px}
|
||||
.header{display:flex;flex-direction:column;gap:10px;background:linear-gradient(135deg, #c8e6c9 0%, #e8f5e8 100%);border:1px solid rgba(46, 125, 50, 0.2);border-radius:14px;padding:12px 12px 10px;backdrop-filter:blur(6px);box-shadow:0 4px 8px rgba(46, 125, 50, 0.1)}
|
||||
.title{margin:0;font-size:20px;letter-spacing:1px;color:#1b5e20;text-shadow:1px 1px 2px rgba(255,255,255,0.5)}
|
||||
.hud{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px;align-items:center}
|
||||
.hud-item{display:flex;flex-direction:column;align-items:center;justify-content:center;background:var(--panel);border:1px solid rgba(255,255,255,0.06);border-radius:10px;padding:8px 6px}
|
||||
.hud-item .label{font-size:12px;color:var(--muted)}
|
||||
.hud-item .value{font-size:18px;font-weight:700;color:#fff}
|
||||
.btn{appearance:none;border:none;background:#1e293b;color:#fff;padding:10px 12px;border-radius:10px;cursor:pointer;outline:none;transition:.15s transform,.15s background;display:inline-flex;align-items:center;justify-content:center}
|
||||
.hud-item{display:flex;flex-direction:column;align-items:center;justify-content:center;background:linear-gradient(135deg, #a5d6a7 0%, #c8e6c9 100%);border:1px solid rgba(46, 125, 50, 0.2);border-radius:10px;padding:8px 6px;box-shadow:0 2px 4px rgba(46, 125, 50, 0.1)}
|
||||
.hud-item .label{font-size:12px;color:#2e7d32}
|
||||
.hud-item .value{font-size:18px;font-weight:700;color:#1b5e20}
|
||||
.btn{appearance:none;border:none;background:linear-gradient(135deg, #81c784 0%, #a5d6a7 100%);color:#fff;padding:10px 12px;border-radius:10px;cursor:pointer;outline:none;transition:.15s transform,.15s background;display:inline-flex;align-items:center;justify-content:center;box-shadow:0 2px 4px rgba(46, 125, 50, 0.2)}
|
||||
.btn:active{transform:scale(.98)}
|
||||
.btn.primary{background:linear-gradient(90deg,var(--accent),var(--accent-2))}
|
||||
.btn.primary{background:linear-gradient(135deg,var(--accent),var(--accent-2));color:#fff}
|
||||
.btn.primary:active{filter:brightness(.95)}
|
||||
|
||||
.main{display:flex;flex-direction:column;gap:12px}
|
||||
.board-wrapper{display:flex;justify-content:center;align-items:center}
|
||||
.board{display:grid;gap:4px;touch-action:manipulation;user-select:none;background:rgba(255,255,255,0.03);border:1px solid rgba(255,255,255,0.06);border-radius:12px;padding:6px;width:100%;max-width:92vw}
|
||||
.cell{display:grid;place-items:center;background:var(--cell);border-radius:8px;border:1px solid rgba(255,255,255,0.06);font-weight:700;color:#9ca3af;box-shadow:inset 0 -1px 0 rgba(255,255,255,0.04);aspect-ratio:1/1;font-size:clamp(12px, 2.2vw, 18px)}
|
||||
.cell.revealed{background:#0b1220;color:#e5e7eb}
|
||||
.board{display:grid;gap:4px;touch-action:manipulation;user-select:none;background:linear-gradient(135deg, #c8e6c9 0%, #e8f5e8 100%);border:1px solid rgba(46, 125, 50, 0.2);border-radius:12px;padding:6px;width:100%;max-width:92vw;box-shadow:0 4px 8px rgba(46, 125, 50, 0.1)}
|
||||
.cell{display:grid;place-items:center;background:var(--cell);border-radius:8px;border:1px solid rgba(46, 125, 50, 0.15);font-weight:700;color:#4caf50;box-shadow:inset 0 -1px 0 rgba(255,255,255,0.3);aspect-ratio:1/1;font-size:clamp(12px, 2.2vw, 18px)}
|
||||
.cell.revealed{background:#e8f5e8;color:#2e7d32}
|
||||
.cell:hover{background:var(--cell-hover)}
|
||||
.cell.flag::after{content:"🚩"}
|
||||
.cell.mine.revealed{background:#3b0d0d;color:#fff}
|
||||
.cell.mine.revealed{background:#ffcdd2;color:#d32f2f}
|
||||
.cell.mine.revealed::after{content:"💣"}
|
||||
.cell[data-n="1"].revealed{color:#60a5fa}
|
||||
.cell[data-n="2"].revealed{color:#34d399}
|
||||
.cell[data-n="3"].revealed{color:#f87171}
|
||||
.cell[data-n="4"].revealed{color:#a78bfa}
|
||||
.cell[data-n="5"].revealed{color:#fbbf24}
|
||||
.cell[data-n="6"].revealed{color:#22d3ee}
|
||||
.cell[data-n="7"].revealed{color:#e879f9}
|
||||
.cell[data-n="8"].revealed{color:#cbd5e1}
|
||||
.cell[data-n="1"].revealed{color:#1976d2}
|
||||
.cell[data-n="2"].revealed{color:#388e3c}
|
||||
.cell[data-n="3"].revealed{color:#d32f2f}
|
||||
.cell[data-n="4"].revealed{color:#7b1fa2}
|
||||
.cell[data-n="5"].revealed{color:#f57c00}
|
||||
.cell[data-n="6"].revealed{color:#00796b}
|
||||
.cell[data-n="7"].revealed{color:#c2185b}
|
||||
.cell[data-n="8"].revealed{color:#455a64}
|
||||
|
||||
.tips{font-size:12px;color:var(--muted);text-align:center}
|
||||
.toast{position:fixed;left:50%;bottom:18px;transform:translateX(-50%);background:rgba(17,24,39,.95);border:1px solid rgba(255,255,255,.08);padding:10px 14px;border-radius:10px}
|
||||
.toast{position:fixed;left:50%;bottom:18px;transform:translateX(-50%);background:linear-gradient(135deg, #c8e6c9 0%, #e8f5e8 100%);border:1px solid rgba(46, 125, 50, 0.2);padding:10px 14px;border-radius:10px;color:#1b5e20;box-shadow:0 4px 8px rgba(46, 125, 50, 0.2)}
|
||||
|
||||
.modal-overlay{position:fixed;inset:0;background:rgba(0,0,0,.45);display:grid;place-items:center;padding:14px}
|
||||
.modal{width:min(520px,92vw);background:linear-gradient(180deg,#0f172a,#0b1320);border:1px solid rgba(255,255,255,0.08);border-radius:14px;padding:16px 14px}
|
||||
.modal h2{margin:4px 0 8px;font-size:20px}
|
||||
.modal-overlay{position:fixed;inset:0;background:rgba(46, 125, 50, 0.3);display:grid;place-items:center;padding:14px}
|
||||
.modal{width:min(520px,92vw);background:linear-gradient(135deg, #e8f5e8 0%, #f1f8e9 100%);border:1px solid rgba(46, 125, 50, 0.2);border-radius:14px;padding:16px 14px;box-shadow:0 8px 16px rgba(46, 125, 50, 0.2)}
|
||||
.modal h2{margin:4px 0 8px;font-size:20px;color:#1b5e20}
|
||||
.stats{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;margin:8px 0 14px}
|
||||
.stats .card{background:var(--panel);border:1px solid rgba(255,255,255,0.06);border-radius:10px;padding:10px}
|
||||
.stats .card .k{font-size:12px;color:var(--muted)}
|
||||
.stats .card .v{font-size:18px;font-weight:700}
|
||||
.stats .card{background:linear-gradient(135deg, #c8e6c9 0%, #e8f5e8 100%);border:1px solid rgba(46, 125, 50, 0.2);border-radius:10px;padding:10px;box-shadow:0 2px 4px rgba(46, 125, 50, 0.1)}
|
||||
.stats .card .k{font-size:12px;color:#2e7d32}
|
||||
.stats .card .v{font-size:18px;font-weight:700;color:#1b5e20}
|
||||
.modal-actions{display:flex;gap:10px;justify-content:flex-end}
|
||||
|
||||
/* 响应式:手机竖屏优先 */
|
||||
|
||||
20
InfoGenie-frontend/public/smallgame/扫雷/gamedata.js
Normal file
20
InfoGenie-frontend/public/smallgame/扫雷/gamedata.js
Normal file
@@ -0,0 +1,20 @@
|
||||
const playerdata = [
|
||||
{
|
||||
"名称":"树萌芽",
|
||||
"账号":"3205788256@qq.com",
|
||||
"分数":1232,
|
||||
"时间":"2025-09-08"
|
||||
},
|
||||
{
|
||||
"名称":"柚大青",
|
||||
"账号":"2143323382@qq.com",
|
||||
"分数":132,
|
||||
"时间":"2025-09-21"
|
||||
},
|
||||
{
|
||||
"名称":"牛马",
|
||||
"账号":"2973419538@qq.com",
|
||||
"分数":876,
|
||||
"时间":"2025-09-25"
|
||||
}
|
||||
]
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
62
InfoGenie-frontend/public/smallgame/贪吃蛇/gamedata.js
Normal file
62
InfoGenie-frontend/public/smallgame/贪吃蛇/gamedata.js
Normal 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"
|
||||
}
|
||||
]
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
/* 动画效果已删除 */
|
||||
Reference in New Issue
Block a user