diff --git a/index.html b/index.html
index 92fa9d7..db285a3 100644
--- a/index.html
+++ b/index.html
@@ -7,7 +7,7 @@
兜爸心选 · 孕育陪伴
-
+
diff --git a/js/app.js b/js/app.js
index 2c0c39a..64b0c44 100644
--- a/js/app.js
+++ b/js/app.js
@@ -3,7 +3,7 @@
(function () {
'use strict';
/* 页面版本号(YYMMDD+序号):显示在「关于兜爸心选」页底部;bump 时同步 head 注释与 ?v= */
- var VER = '26100405';
+ var VER = '26100406';
const $ = (s, c) => (c || document).querySelector(s);
const $$ = (s, c) => Array.from((c || document).querySelectorAll(s));
diff --git a/js/bump.js b/js/bump.js
index 7b01f40..9eb953f 100644
--- a/js/bump.js
+++ b/js/bump.js
@@ -26,6 +26,7 @@
· 26~33 周「拳打脚踢」:完整版——小脚丫 / 小拳头 / 膝盖 / 小屁股,最勤(隔 4~8 秒),中途还会再顶一下
· 34 周起「地方小了」:很少猛踢,多是一大片慢慢拱过去(翻身、屁股),节奏放慢(隔 7~12 秒),次数不减
孕周来自 app.js 的 mb-preg 事件(syncPregnancy 跑完后广播)。调试:URL 带 bumpweek=24 可强制按 24 周演示。
+ · 节奏(26 周起):有时原地「哒哒哒」带节奏连踢几拍;有时踢完不歇,旁边紧接着再踢 1~2 下
开关:「我的 → 隐私权限 → 宝宝在肚皮下动」,存 localStorage 'mb_bump'('0' = 关);系统开了「减弱动态效果」也不出来。 */
(function () {
'use strict';
@@ -78,10 +79,13 @@
/* ---------- 孕周 → 阶段 ---------- */
const STAGES = {
- flutter: { order: ['flick', 'flick', 'tap', 'flick'], gap: [10, 18], kick: false, again: 0, double: .45, follow: false },
- active: { order: ORDER, gap: [4, 8], kick: true, again: .34, double: 0, follow: true },
- late: { order: ['roll', 'butt', 'foot', 'roll', 'knee'], gap: [7, 12], kick: false, again: .15, double: 0, follow: true, slow: true }
+ // drum:原地带节奏连踢的概率;chain:踢完不歇、旁边紧接着再踢的概率,最多连 chainMax 下(2026-10-04 用户:「有时会带点节奏、可以连续踢」)
+ flutter: { order: ['flick', 'flick', 'tap', 'flick'], gap: [10, 18], kick: false, again: 0, double: .45, follow: false, drum: 0, chain: 0 },
+ active: { order: ORDER, gap: [4, 8], kick: true, again: .34, double: 0, follow: true, drum: .4, chain: .3, chainMax: 3 },
+ late: { order: ['roll', 'butt', 'foot', 'roll', 'knee'], gap: [7, 12], kick: false, again: .15, double: 0, follow: true, slow: true, drum: .22, chain: .15, chainMax: 2 }
};
+ // 原地连踢的节奏型(每拍间隔,秒):匀速「哒哒哒」、「哒哒—哒」、「哒—哒哒」、两下一组
+ const RHYTHMS = [[.42, .42, .42], [.3, .3, .75, .3], [.6, .28, .28], [.32, .9, .32], [.38, .38, .38, .38]];
const dbgWeek = (location.href.match(/bumpweek=(\d+)/) || [])[1];
let week = dbgWeek ? +dbgWeek : (window.__mbPreg ? window.__mbPreg.week : null);
const stageOf = w => w == null || w < 20 ? null : w < 26 ? STAGES.flutter : w < 34 ? STAGES.active : STAGES.late;
@@ -212,6 +216,20 @@
ft.h.vel += P.roll ? 30 : slow ? 45 : P.soft ? 50 : 120;
ft.life = 0; ft.dur = P.dur[0] + Math.random() * (P.dur[1] - P.dur[0]); ft.kicked = false;
ft.chained = !!ft.chainNext; ft.chainNext = false;
+ ft.chainN = ft.chained ? (ft.chainN || 0) + 1 : 0;
+ // 连续踢:第一下就定好后面还跟几下;连踢的每一下都短促(1 秒出头),不像单独那一下要停好几秒
+ if (ft.chained) ft.chainLeft--;
+ else ft.chainLeft = stage && stage.chain && !P.soft && !P.roll && P !== PARTS.kick && Math.random() < stage.chain
+ ? 1 + (Math.random() * (stage.chainMax - 1) | 0) : 0;
+ const inChain = ft.chained || ft.chainLeft > 0;
+ if (inChain && !P.roll) ft.dur = (1.1 + Math.random() * .6) * (stage && stage.slow ? 1.3 : 1);
+ // 原地连踢:脚丫 / 拳头 / 膝盖才有;晚期节奏放慢 1.4 倍。拍子排在第一下顶起来之后,整段时长跟着拉长
+ ft.beats = null; ft.beat = 0; ft.pop = 0;
+ if (!inChain && stage && stage.drum && !P.roll && !P.soft && P !== PARTS.kick && Math.random() < stage.drum) {
+ const r = RHYTHMS[Math.random() * RHYTHMS.length | 0], m = stage.slow ? 1.4 : 1;
+ let t = .7; ft.beats = r.map(d => (t += d * m));
+ ft.dur = Math.max(ft.dur, t + .9); ft.kicked = true; // 有节奏就不再「中途再顶一下」
+ }
ft.catchable = P !== PARTS.kick;
if (!skin) skin = findSkin(ft.x, ft.y);
gather(ft.x, ft.y, Math.max(P.rx, P.ry) * 1.25 + 20);
@@ -322,11 +340,25 @@
} else {
ft.wob = Math.sin(u * 2.1) * .12;
if (u > ft.dur * .4 && !ft.kicked && P !== PARTS.kick && !P.soft && stage && stage.kick) { ft.kicked = true; ft.h.vel += 70; } // 中途再顶一下
+ // 一拍:先往回缩一下(鼓包塌一点),0.12 秒后再顶上来,位置跟着微微挪(脚尖 / 脚跟轮流使劲)
+ if (ft.beats && ft.beat < ft.beats.length && u >= ft.beats[ft.beat]) {
+ ft.beat++; ft.h.vel -= 85; ft.pop = .12;
+ ft.ox += (Math.random() - .5) * 10; ft.oy += (Math.random() - .5) * 10;
+ }
+ if (ft.pop > 0 && (ft.pop -= dt) <= 0) ft.h.vel += stage && stage.slow ? 95 : 150;
+ }
+ if (u > ft.dur) {
+ // 连续踢:这一下收得快一点,旁边紧接着再来,不等下一个间隔
+ ft.chainNext = ft.chainLeft > 0;
+ if (ft.chainNext) { ft.h.to = 0; ft.h.k = 200; ft.h.c = 24; mode = 'hide'; } else hide(false);
}
- if (u > ft.dur) hide(false);
} else if (mode === 'hide') {
if (ft.h.v < .3) {
mode = 'wait'; wait = gap();
+ if (ft.chainNext) {
+ const a = Math.random() * Math.PI * 2, d = 50 + Math.random() * 40;
+ near = { x: ft.x + ft.ox + Math.cos(a) * d, y: ft.y + ft.oy + Math.sin(a) * d }; wait = .2 + Math.random() * .35;
+ }
// 小鱼吐泡泡常常是连着的:一闪没了,旁边紧跟着又一下
if (stage && stage.double && ft.part.soft && !ft.chained && Math.random() < stage.double) {
const a = Math.random() * Math.PI * 2;