Files
tankwar_proj/js/scenes/RankingScene.js
T
2026-04-10 22:59:39 +08:00

147 lines
3.6 KiB
JavaScript

/**
* RankingScene.js
* Ranking/leaderboard scene.
* In production, this would use WeChat Open Data Domain (SharedCanvas).
* For now, displays local high scores with a placeholder for friend rankings.
*/
const {
SCREEN_WIDTH,
SCREEN_HEIGHT,
COLORS,
SCENE,
GAME_MODE,
} = require('../base/GameGlobal');
const { t } = require('../i18n/I18n');
const StorageManager = require('../managers/StorageManager');
const RankingScene = {
_storage: null,
_scores: [],
_buttons: {},
enter() {
this._storage = new StorageManager();
this._buttons = {};
// Load local scores
this._scores = [
{
label: t('ranking.classicHigh'),
score: this._storage.getHighScore(GAME_MODE.CLASSIC),
},
{
label: t('ranking.endlessHigh'),
score: this._storage.getHighScore(GAME_MODE.ENDLESS),
},
{
label: t('ranking.highestLevel'),
score: this._storage.getHighestLevel(),
suffix: t('ranking.levelSuffix'),
},
];
},
exit() {},
update(dt) {},
render(ctx) {
// Background
ctx.fillStyle = COLORS.MENU_BG;
ctx.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
const cx = SCREEN_WIDTH / 2;
let y = 60;
// Title
ctx.fillStyle = COLORS.MENU_TITLE;
ctx.font = 'bold 28px Arial';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(t('ranking.title'), cx, y);
y += 60;
// Local scores section
ctx.fillStyle = '#AAAAAA';
ctx.font = '14px Arial';
ctx.fillText(t('ranking.personalRecord'), cx, y);
y += 40;
for (const item of this._scores) {
// Card background
const cardW = SCREEN_WIDTH * 0.75;
const cardH = 55;
const cardX = cx - cardW / 2;
ctx.fillStyle = '#1e1e3a';
ctx.fillRect(cardX, y - cardH / 2, cardW, cardH);
ctx.strokeStyle = '#333366';
ctx.lineWidth = 1;
ctx.strokeRect(cardX, y - cardH / 2, cardW, cardH);
// Label
ctx.fillStyle = COLORS.HUD_TEXT;
ctx.font = '14px Arial';
ctx.textAlign = 'left';
ctx.fillText(item.label, cardX + 15, y - 5);
// Score
ctx.fillStyle = '#FFD700';
ctx.font = 'bold 18px Arial';
ctx.textAlign = 'right';
const suffix = item.suffix || t('ranking.scoreSuffix');
ctx.fillText(`${item.score} ${suffix}`, cardX + cardW - 15, y + 2);
y += 70;
}
y += 20;
// Friend ranking placeholder
ctx.fillStyle = '#666666';
ctx.font = '13px Arial';
ctx.textAlign = 'center';
ctx.fillText(t('ranking.friendHint'), cx, y);
ctx.fillText('(SharedCanvas)', cx, y + 20);
// Back button
y = SCREEN_HEIGHT - 80;
const btnW = SCREEN_WIDTH * 0.4;
const btnH = 42;
const btnX = cx - btnW / 2;
this._buttons['back'] = { x: btnX, y: y - btnH / 2, w: btnW, h: btnH };
ctx.fillStyle = COLORS.MENU_BTN;
ctx.strokeStyle = COLORS.MENU_BTN_BORDER;
ctx.lineWidth = 2;
ctx.fillRect(btnX, y - btnH / 2, btnW, btnH);
ctx.strokeRect(btnX, y - btnH / 2, btnW, btnH);
ctx.fillStyle = COLORS.MENU_BTN_TEXT;
ctx.font = 'bold 16px Arial';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(t('common.back'), cx, y);
},
handleTouch(eventType, e) {
if (eventType !== 'touchstart') return;
const touch = e.touches[0];
const tx = touch.clientX;
const ty = touch.clientY;
const back = this._buttons['back'];
if (back && tx >= back.x && tx <= back.x + back.w && ty >= back.y && ty <= back.y + back.h) {
GameGlobal.sceneManager.switchTo(SCENE.MENU);
}
},
};
module.exports = RankingScene;