update: 2026-03-28 20:59
This commit is contained in:
@@ -1,96 +0,0 @@
|
||||
// 游戏结束排行榜展示
|
||||
const gameStats = {
|
||||
showStats({ score, playTime }) {
|
||||
// 将毫秒转为 mm:ss
|
||||
const formatDuration = (ms) => {
|
||||
const totalSec = Math.max(0, Math.floor(ms / 1000));
|
||||
const m = String(Math.floor(totalSec / 60)).padStart(2, '0');
|
||||
const s = String(totalSec % 60).padStart(2, '0');
|
||||
return `${m}:${s}`;
|
||||
};
|
||||
|
||||
// 构造排行榜数据(模拟),将当前成绩与 gamedata.js 合并
|
||||
const todayStr = (() => {
|
||||
const d = new Date();
|
||||
const y = d.getFullYear();
|
||||
const m = String(d.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(d.getDate()).padStart(2, '0');
|
||||
return `${y}-${m}-${day}`;
|
||||
})();
|
||||
|
||||
// 当前玩家信息(可根据实际项目替换为真实用户)
|
||||
const currentEntry = {
|
||||
名称: localStorage.getItem('tetris_player_name') || '我',
|
||||
账号: localStorage.getItem('tetris_player_account') || 'guest@local',
|
||||
分数: score,
|
||||
时间: formatDuration(playTime), // 排行榜展示“游戏时长”
|
||||
isCurrent: true,
|
||||
};
|
||||
|
||||
// 注意:在浏览器中,使用 const 声明的全局变量不会挂载到 window 上
|
||||
// 因此这里直接使用 playerdata,而不是 window.playerdata
|
||||
const baseData = (typeof playerdata !== 'undefined' && Array.isArray(playerdata)) ? playerdata : [];
|
||||
|
||||
// 为基础数据模拟“游戏时长”(mm:ss),以满足展示需求
|
||||
const simulateDuration = (scoreVal) => {
|
||||
const sec = Math.max(30, Math.min(30 * 60, Math.round((Number(scoreVal) || 0) * 1.2)));
|
||||
return formatDuration(sec * 1000);
|
||||
};
|
||||
|
||||
const merged = [...baseData.map((d) => ({
|
||||
...d,
|
||||
// 使用已有分数推导一个模拟时长
|
||||
时间: simulateDuration(d.分数),
|
||||
isCurrent: false,
|
||||
})), currentEntry]
|
||||
.sort((a, b) => (b.分数 || 0) - (a.分数 || 0));
|
||||
|
||||
// 3) 渲染排行榜(取前10)
|
||||
const tbody = document.getElementById('leaderboardBody');
|
||||
tbody.innerHTML = '';
|
||||
const topN = merged.slice(0, 10);
|
||||
topN.forEach((item, idx) => {
|
||||
const tr = document.createElement('tr');
|
||||
if (item.isCurrent) {
|
||||
tr.classList.add('current-row');
|
||||
}
|
||||
const rankCell = document.createElement('td');
|
||||
const nameCell = document.createElement('td');
|
||||
const scoreCell = document.createElement('td');
|
||||
const timeCell = document.createElement('td');
|
||||
|
||||
const rankBadge = document.createElement('span');
|
||||
rankBadge.className = 'rank-badge';
|
||||
rankBadge.textContent = String(idx + 1);
|
||||
rankCell.appendChild(rankBadge);
|
||||
|
||||
nameCell.textContent = item.名称 || '未知';
|
||||
scoreCell.textContent = item.分数 || 0;
|
||||
timeCell.textContent = item.时间 || formatDuration(playTime);
|
||||
|
||||
tr.appendChild(rankCell);
|
||||
tr.appendChild(nameCell);
|
||||
tr.appendChild(scoreCell);
|
||||
tr.appendChild(timeCell);
|
||||
tbody.appendChild(tr);
|
||||
});
|
||||
|
||||
// 4) 展示排行榜界面
|
||||
const statsEl = document.getElementById('gameStats');
|
||||
statsEl.style.display = 'flex';
|
||||
|
||||
// 5) 再玩一次按钮
|
||||
const playAgainBtn = document.getElementById('playAgainBtn');
|
||||
if (playAgainBtn) {
|
||||
playAgainBtn.onclick = () => {
|
||||
statsEl.style.display = 'none';
|
||||
if (window.game && typeof window.game.restart === 'function') {
|
||||
window.game.restart();
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// 暴露到全局
|
||||
window.gameStats = gameStats;
|
||||
@@ -1,20 +0,0 @@
|
||||
const playerdata = [
|
||||
{
|
||||
"名称":"树萌芽",
|
||||
"账号":"3205788256@qq.com",
|
||||
"分数":1232,
|
||||
"时间":"2025-09-08"
|
||||
},
|
||||
{
|
||||
"名称":"柚大青",
|
||||
"账号":"2143323382@qq.com",
|
||||
"分数":132,
|
||||
"时间":"2025-09-21"
|
||||
},
|
||||
{
|
||||
"名称":"牛马",
|
||||
"账号":"2973419538@qq.com",
|
||||
"分数":876,
|
||||
"时间":"2025-09-25"
|
||||
}
|
||||
]
|
||||
@@ -43,7 +43,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 手机端触摸控制 -->
|
||||
<div class="mobile-controls">
|
||||
<div class="mobile-controls-left">
|
||||
<button class="control-btn" id="rotateBtn">↻</button>
|
||||
@@ -58,35 +57,15 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 游戏结束统计界面 -->
|
||||
<div class="game-stats" id="gameStats">
|
||||
<div class="stats-content">
|
||||
<h2>游戏结束排行榜</h2>
|
||||
<!-- 排行榜 -->
|
||||
<div class="leaderboard" id="leaderboard">
|
||||
<div class="leaderboard-title">本局排行榜</div>
|
||||
<div class="leaderboard-wrap">
|
||||
<table class="leaderboard-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>排名</th>
|
||||
<th>名称</th>
|
||||
<th>分数</th>
|
||||
<th>游戏时长</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="leaderboardBody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="leaderboard-tip">仅显示前10名;“游戏时长”为模拟数据,已与您的成绩合并</div>
|
||||
</div>
|
||||
<h2>游戏结束</h2>
|
||||
<div class="end-summary" id="endSummary"></div>
|
||||
<button class="game-btn" id="playAgainBtn">再玩一次</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="tetris.js"></script>
|
||||
<script src="game-controls.js"></script>
|
||||
<script src="gamedata.js"></script>
|
||||
<script src="game-stats.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -319,82 +319,13 @@ body {
|
||||
box-shadow: 0 4px 8px rgba(46, 125, 50, 0.3);
|
||||
}
|
||||
|
||||
/* 排行榜样式 */
|
||||
.leaderboard {
|
||||
background: linear-gradient(135deg, #e8f5e8 0%, #f1f8e9 100%);
|
||||
.end-summary {
|
||||
margin: 16px 0 24px;
|
||||
font-size: 1.05rem;
|
||||
line-height: 1.8;
|
||||
}
|
||||
.end-summary strong {
|
||||
color: #2e7d32;
|
||||
border: 1px solid rgba(46, 125, 50, 0.3);
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 6px 18px rgba(46, 125, 50, 0.25);
|
||||
padding: 16px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.leaderboard-title {
|
||||
font-weight: 700;
|
||||
font-size: 1.2rem;
|
||||
margin-bottom: 12px;
|
||||
background: linear-gradient(135deg, #4caf50 0%, #8bc34a 50%, #cddc39 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
.leaderboard-wrap {
|
||||
max-height: 260px;
|
||||
overflow: auto;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.leaderboard-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.leaderboard-table thead tr {
|
||||
background: linear-gradient(135deg, #66bb6a 0%, #8bc34a 100%);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.leaderboard-table th,
|
||||
.leaderboard-table td {
|
||||
text-align: left;
|
||||
padding: 10px 12px;
|
||||
border-bottom: 1px solid rgba(46, 125, 50, 0.15);
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.leaderboard-table tbody tr {
|
||||
background: linear-gradient(135deg, rgba(46,125,50,0.08) 0%, rgba(46,125,50,0.03) 100%);
|
||||
transition: background 0.2s ease, transform 0.2s ease;
|
||||
}
|
||||
|
||||
.leaderboard-table tbody tr:hover {
|
||||
background: linear-gradient(135deg, rgba(46,125,50,0.12) 0%, rgba(46,125,50,0.06) 100%);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.rank-badge {
|
||||
display: inline-block;
|
||||
min-width: 32px;
|
||||
text-align: center;
|
||||
padding: 4px 8px;
|
||||
border-radius: 12px;
|
||||
background: linear-gradient(45deg, #66bb6a, #8bc34a);
|
||||
color: #fff;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.current-row {
|
||||
outline: 2px solid rgba(76, 175, 80, 0.7);
|
||||
box-shadow: 0 0 0 4px rgba(76, 175, 80, 0.15) inset;
|
||||
}
|
||||
|
||||
.leaderboard-tip {
|
||||
margin-top: 10px;
|
||||
font-size: 0.85rem;
|
||||
color: #388e3c;
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@@ -457,14 +388,6 @@ body {
|
||||
width: 95%;
|
||||
}
|
||||
|
||||
.leaderboard-wrap {
|
||||
max-height: 200px;
|
||||
}
|
||||
.leaderboard-table th,
|
||||
.leaderboard-table td {
|
||||
padding: 8px 10px;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
@@ -536,39 +459,3 @@ body {
|
||||
.pulse {
|
||||
animation: pulse 2s infinite;
|
||||
}
|
||||
/* 摘要卡片 */
|
||||
.leaderboard-summary {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 12px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.summary-item {
|
||||
background: linear-gradient(135deg, #2e7d32 0%, #388e3c 100%);
|
||||
color: #fff;
|
||||
padding: 12px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid rgba(46, 125, 50, 0.3);
|
||||
box-shadow: 0 4px 8px rgba(46, 125, 50, 0.2);
|
||||
}
|
||||
|
||||
.summary-label {
|
||||
display: block;
|
||||
font-size: 0.9rem;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.summary-value {
|
||||
display: block;
|
||||
font-size: 1.3rem;
|
||||
font-weight: 700;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.leaderboard-summary {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,15 +402,28 @@ class TetrisGame {
|
||||
gameOver() {
|
||||
this.gameRunning = false;
|
||||
this.gamePaused = false;
|
||||
|
||||
// 显示游戏统计
|
||||
gameStats.showStats({
|
||||
score: this.score,
|
||||
level: this.level,
|
||||
lines: this.lines,
|
||||
playTime: Date.now() - this.gameStartTime,
|
||||
maxCombo: this.maxCombo
|
||||
});
|
||||
|
||||
const playMs = Date.now() - this.gameStartTime;
|
||||
const sec = Math.floor(playMs / 1000);
|
||||
const m = String(Math.floor(sec / 60)).padStart(2, '0');
|
||||
const s = String(sec % 60).padStart(2, '0');
|
||||
|
||||
const summary = document.getElementById('endSummary');
|
||||
if (summary) {
|
||||
summary.innerHTML =
|
||||
`<p>得分 <strong>${this.score}</strong> · 等级 <strong>${this.level}</strong></p>` +
|
||||
`<p>消除 <strong>${this.lines}</strong> 行 · 用时 <strong>${m}:${s}</strong></p>`;
|
||||
}
|
||||
const statsEl = document.getElementById('gameStats');
|
||||
if (statsEl) statsEl.style.display = 'flex';
|
||||
|
||||
const btn = document.getElementById('playAgainBtn');
|
||||
if (btn) {
|
||||
btn.onclick = () => {
|
||||
statsEl.style.display = 'none';
|
||||
if (window.game && typeof window.game.restart === 'function') window.game.restart();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
gameLoop(currentTime = 0) {
|
||||
|
||||
Reference in New Issue
Block a user