Files
kidgo/mapview.html
T
2026-10-21 13:54:25 +08:00

109 lines
4.7 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<title>关卡地图预览 · IWBT C 同人</title>
<style>
:root { --bg:#0e1018; --panel:#171b26; --line:#2a3040; --fg:#dfe3ee; --dim:#8b93a7; }
* { box-sizing: border-box; }
body { margin:0; background:var(--bg); color:var(--fg); font:14px/1.6 ui-sans-serif,system-ui,"PingFang SC","Microsoft YaHei",sans-serif; }
header { padding:14px 18px; border-bottom:1px solid var(--line); display:flex; gap:14px; align-items:center; flex-wrap:wrap; }
h1 { font-size:15px; font-weight:500; margin:0 14px 0 0; }
select, button { background:var(--panel); color:var(--fg); border:1px solid var(--line); border-radius:6px; padding:5px 10px; font:inherit; }
.stat { color:var(--dim); font-size:13px; }
.stat b { color:var(--fg); font-weight:500; }
main { padding:14px 18px 30px; overflow:auto; }
canvas { display:block; background:var(--panel); border:1px solid var(--line); border-radius:6px; image-rendering:pixelated; }
.legend { margin-top:12px; display:flex; gap:18px; flex-wrap:wrap; color:var(--dim); font-size:13px; }
.legend i { display:inline-block; width:12px; height:12px; border-radius:2px; vertical-align:-2px; margin-right:5px; }
</style>
</head>
<body>
<header>
<h1>关卡地图预览</h1>
<select id="sel"></select>
<span class="stat" id="stat"></span>
</header>
<main><canvas id="cv"></canvas></main>
<div class="legend">
<span><i style="background:#3a4056"></i>实心块</span>
<span><i style="background:#5b7fa6"></i>冰面</span>
<span><i style="background:#6b5b8a"></i>单向台</span>
<span><i style="background:#2d5a7a"></i>水</span>
<span><i style="background:#e04b6a"></i>四向刺</span>
<span><i style="background:#8b3ad0"></i>即死块</span>
<span><i style="background:#3ad07a"></i>出生点</span>
<span><i style="background:#4bc8ff"></i>存档点</span>
<span><i style="background:#ffd24b"></i>终点 / 苹果</span>
<span><i style="background:#c48bff"></i>手枪·跳台·炮台·BOSS·掉落刺</span>
</div>
<script type="module">
import { LEVELS } from './js/levels/index.js';
const COLORS = {
'#': '#3a4056', '@': '#3a4056', '=': '#3a4056', 'M': '#4a4f63',
'%': '#5b7fa6', '-': '#6b5b8a', '~': '#2d5a7a', '*': '#8b3ad0', 'V': '#4a4f63',
'^': '#e04b6a', 'v': '#e04b6a', '<': '#e04b6a', '>': '#e04b6a',
S: '#3ad07a', G: '#4bc8ff', X: '#ffd24b', F: '#ffd24b',
P: '#c48bff', J: '#c48bff', O: '#c48bff', B: '#c48bff', D: '#c48bff',
W: '#c48bff', T: '#8b93a7', C: '#8b93a7', '!': '#8b93a7',
};
const sel = document.getElementById('sel');
const stat = document.getElementById('stat');
const cv = document.getElementById('cv');
const ctx = cv.getContext('2d');
LEVELS.forEach((l, i) => {
const o = document.createElement('option');
o.value = i;
o.textContent = `${l.id} ${l.name} ${l.cn || ''}`;
sel.appendChild(o);
});
function draw(d) {
const rows = d.grid, h = rows.length, w = d.width;
const s = Math.max(4, Math.min(16, Math.floor(Math.min(1500 / w, 820 / h))));
cv.width = w * s; cv.height = h * s;
cv.style.width = cv.width + 'px';
cv.style.height = cv.height + 'px';
ctx.clearRect(0, 0, cv.width, cv.height);
let spike = 0;
for (let y = 0; y < h; y++) {
const line = rows[y] || '';
for (let x = 0; x < w; x++) {
const ch = line[x] || '.';
if (ch === '.') continue;
if ('^v<>'.includes(ch)) spike++;
const c = COLORS[ch];
if (!c) continue;
ctx.fillStyle = c;
if ('^v<>'.includes(ch)) { // 刺画成三角形,方向和判定一致
ctx.beginPath();
const px = x * s, py = y * s;
if (ch === '^') { ctx.moveTo(px + s / 2, py + 2); ctx.lineTo(px + s - 2, py + s - 1); ctx.lineTo(px + 2, py + s - 1); }
if (ch === 'v') { ctx.moveTo(px + 2, py + 1); ctx.lineTo(px + s - 2, py + 1); ctx.lineTo(px + s / 2, py + s - 2); }
if (ch === '<') { ctx.moveTo(px + 1, py + s / 2); ctx.lineTo(px + s - 1, py + 2); ctx.lineTo(px + s - 1, py + s - 2); }
if (ch === '>') { ctx.moveTo(px + 1, py + 2); ctx.lineTo(px + s - 1, py + 1); ctx.lineTo(px + 1, py + s - 2); }
ctx.closePath(); ctx.fill();
} else if ('SGXFPJODBW'.includes(ch)) {
ctx.beginPath();
ctx.arc(x * s + s / 2, y * s + s / 2, s * 0.3, 0, 7);
ctx.fill();
} else {
ctx.fillRect(x * s, y * s, s, s);
}
}
}
const total = w * h;
const saves = rows.join('').split('').filter(c => c === 'G').length;
stat.innerHTML = `<b>${d.name}</b> ${d.cn || ''} · ${w}×${h} 格 · 类型 ${d.type} · 难度 ${d.diff} · 刺 ${spike} 格(${(spike / total * 100).toFixed(1)}%)· 存档点 ${saves}`;
}
sel.addEventListener('change', () => draw(LEVELS[+sel.value]));
draw(LEVELS[0]);
</script>
</body>
</html>