v0.02
This commit is contained in:
1 parent
234e769f4d
commit
e6a0aa94de
10 files changed
+872
-583
No files matched your search
+108
@@ -0,0 +1,108 @@
|
||||
<!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>
|
||||
Reference in new issue
Block a user