fix: 优化跳跃和下落手感

This commit is contained in:
cancerai committed 2026-10-24 01:54:39 +08:00
1 parent ada64fe4be
commit afe2f64b9b
25 files changed
+1197 -188

No files matched your search

+28 -28
View File
@@ -8,7 +8,7 @@ const C = {
metal: '#5a6478', metalDark: '#333a4a',
ice: '#8fd8f0', iceDark: '#4a90b8',
water: '#2a6fd8',
spike: '#c8c8d8', spikeDark: '#5a5a6a',
spike: '#cfdde9', spikeDark: '#a8bccf',
kid: '#d94a55', kidDark: '#8e2530', skin: '#f5cfa8', hair: '#5a3a22', pant: '#2c3a7a',
save: '#b06bff', goal: '#ffc63a', gun: '#b8b8c8', apple: '#e03050',
};
@@ -77,33 +77,34 @@ export function drawOneWay(ctx, x, y) {
for (let i = 0; i < 8; i++) px(ctx, x + i * 4, y + 6, 2, 3, C.metalDark);
}
// 单个三角形刺:尖端指向 dir,底边贴在相反一侧(与 level.js 的 spikeTri 顶点完全一致)。
// 外观对齐经典 I wanna 素材:冰蓝白渐变的干净大三角,占满整格。
export function drawSpike(ctx, x, y, dir, t) {
const s = TILE;
const g = ctx.createLinearGradient(x, y, x, y + s);
// 底座
if (dir === 0) { // 朝上(在地面上)
px(ctx, x + 1, y + s - 7, s - 2, 7, C.spikeDark);
for (let i = 0; i < 3; i++) tri(ctx, x + 3 + i * 9, y + s - 6, x + 7.5 + i * 9, y + 5, x + 12 + i * 9, y + s - 6);
px(ctx, x + 1, y + s - 2, s - 2, 2, '#2a2a34');
} else if (dir === 1) { // 朝下(天花板)
px(ctx, x + 1, y, s - 2, 7, C.spikeDark);
for (let i = 0; i < 3; i++) tri(ctx, x + 3 + i * 9, y + 6, x + 7.5 + i * 9, y + s - 5, x + 12 + i * 9, y + 6);
px(ctx, x + 1, y, s - 2, 2, '#2a2a34');
} else if (dir === 2) { // 朝左(贴右墙)
px(ctx, x + s - 7, y + 1, 7, s - 2, C.spikeDark);
for (let i = 0; i < 3; i++) tri(ctx, x + s - 6, y + 3 + i * 9, x + 5, y + 7.5 + i * 9, x + s - 6, y + 12 + i * 9);
px(ctx, x + s - 2, y + 1, 2, s - 2, '#2a2a34');
} else { // 朝右(贴左墙)
px(ctx, x, y + 1, 7, s - 2, C.spikeDark);
for (let i = 0; i < 3; i++) tri(ctx, x + 6, y + 3 + i * 9, x + s - 5, y + 7.5 + i * 9, x + 6, y + 12 + i * 9);
px(ctx, x, y + 1, 2, s - 2, '#2a2a34');
let ax, ay, bx, by, cx, cy;
if (dir === 0) { // 朝上(地面上)
ax = x + s / 2; ay = y; bx = x; by = y + s; cx = x + s; cy = y + s;
} else if (dir === 1) { // 朝下(天花板)
ax = x + s / 2; ay = y + s; bx = x; by = y; cx = x + s; cy = y;
} else if (dir === 2) { // 朝左(贴右墙)
ax = x; ay = y + s / 2; bx = x + s; by = y; cx = x + s; cy = y + s;
} else { // 朝右(贴左墙)
ax = x + s; ay = y + s / 2; bx = x; by = y; cx = x; cy = y + s;
}
}
function tri(ctx, x1, y1, x2, y2, x3, y3) {
// 冰蓝白渐变:尖端最亮,往底边过渡到淡蓝
let g;
if (dir === 0) { g = ctx.createLinearGradient(x, y, x, y + s); }
else if (dir === 1) { g = ctx.createLinearGradient(x, y + s, x, y); }
else if (dir === 2) { g = ctx.createLinearGradient(x, y, x + s, y); }
else { g = ctx.createLinearGradient(x + s, y, x, y); }
g.addColorStop(0, '#f4f9fd');
g.addColorStop(0.55, '#cfdde9');
g.addColorStop(1, '#a8bccf');
ctx.beginPath();
ctx.moveTo(x1, y1); ctx.lineTo(x2, y2); ctx.lineTo(x3, y3); ctx.closePath();
ctx.fillStyle = C.spike; ctx.fill();
ctx.strokeStyle = '#8d8da0'; ctx.lineWidth = 1; ctx.stroke();
ctx.moveTo(ax, ay); ctx.lineTo(bx, by); ctx.lineTo(cx, cy); ctx.closePath();
ctx.fillStyle = g; ctx.fill();
// 淡蓝描边(参考图的柔和轮廓)
ctx.strokeStyle = 'rgba(150,175,200,.9)'; ctx.lineWidth = 1; ctx.stroke();
}
/** 全致死方块(美味水果外观) */
@@ -152,11 +153,10 @@ export function drawKid(ctx, p, t) {
const x = Math.round(p.x), y = Math.round(p.y);
const w = p.w, h = p.h;
const air = !p.grounded;
const sq = p.squash; // 1 正常
// 不做任何 squash/stretch 形变:起跳与落地都保持原始体型,
// 避免身体忽高忽低被感知为"上下晃动"(2026-10-23 用户两次反馈后彻底移除)
ctx.save();
ctx.translate(x + w / 2, y + h);
ctx.scale(1 / sq, sq);
ctx.translate(-w / 2, -h);
ctx.translate(x, y);
const face = p.facing; // 1 右 -1 左
// 身体(红衣)