diff --git a/js/enemies.js b/js/enemies.js index 3652c71..ee79f65 100644 --- a/js/enemies.js +++ b/js/enemies.js @@ -303,24 +303,24 @@ function bossMain(b,def,fm){ const ks=b.keys,n=ks.n; if(ks.hotT>0){ks.hotT--; if(ks.hotT===0){const list=ks.hotList||[ks.hot]; - for(const kh of list){if(kh<0)continue;const kx=-(n-1)*4.75+kh*9.5; + for(const kh of list){if(kh<0)continue;const kx=-(n-1)*5+kh*10; // 与drawPiano键位一致(整数键距10) bossBeam(b.x+kx,b.y+18,b.x+kx,H+8,4,"#43e8ff",7,22,18,{b,ox:kx,oy:18,followX2:true});} ks.hotList=null;ks.hot=-1;SFX.eshoot();}} ks.t--; if(ks.t<=0&&ks.hotT<=0){ if(ks.i>=ks.seq.length){ // 布下一局:轮换模式 ks.mode=(ks.mode+1)%4; - if(ks.mode===0){ks.seq=[];for(let i=0;i=0;i--)ks.seq.push(i);} + if(ks.mode===0){ks.seq=[];for(let i=0;i=3;i--)ks.seq.push(i);} // 反扫止于3号:最左3键永远安全 else if(ks.mode===2){ks.seq=shuffled(n);} else{ks.seq=[];for(let i=0;i<6+ph*2;i++)ks.seq.push(-1);} // -1=齐射标记 - ks.i=0;ks.t=Math.round((ph?8:14)/fm); // 光速进入下一种模式 + ks.i=0;ks.t=Math.round((ph?14:22)/fm); }else{const cur=ks.seq[ks.i++]; - if(cur===-1){const pool=shuffled(n);ks.hotList=pool.slice(0,4+ph*2);ks.hotT=4;ks.t=Math.round((ph?8:12)/fm);} - else{ks.hot=cur;ks.hotT=1;ks.t=Math.round((ph?1:1)/fm);} // 扫射模式:每tick一键(≈5倍速) + if(cur===-1){const pool=shuffled(n);ks.hotList=pool.slice(0,4+ph*2);ks.hotT=6;ks.hotT0=6;ks.t=Math.round((ph?14:20)/fm);} + else{ks.hot=cur;ks.hotT=2;ks.hotT0=2;ks.t=Math.round((ph?2:3)/fm);} // 扫射模式(整体已降速) } } - b.mainT=2;break;} + b.mainT=4;break;} case "hive": // 母巢核心:环弹+孵化 for(let i=0;i<10+ph*4;i++)ebul(b.x,b.y,i/(10+ph*4)*TAU+b.t*0.03,1.6+0.2*ph,"orbO"); if(b.t%240<3)for(let i=0;i<1+ph;i++)spawnEnemy(ph>=2?"kami":"mini",b.x+rnd(-30,30),b.y+8,false); diff --git a/js/render.js b/js/render.js index ec63d0f..f1ec312 100644 --- a/js/render.js +++ b/js/render.js @@ -228,11 +228,19 @@ function drawAssault(t,fl,swp,ph,mp){ // 暗黑突击(swp=翼展角;炮管/ } function drawPiano(b,t,fl,split){ // 激光钢琴(split=裂壳进度0~1) const ks=b.keys,n=ks?ks.n:21; - px(-(n-1)*4.75-5,6,(n-1)*9.5+10,19,"#141821"); // 键槽 - for(let i=0;i=0)); px(kx-4,8,8,14,hot?(t%6<3?"#e8fbff":"#43e8ff"):"#d8e4f0"); px(kx-4,20,8,2,hot?"#43e8ff":"#8a9ab8");} + if(ks&&ks.hotT>0&&ks.hotT0){const pr=1-ks.hotT/ks.hotT0; // 蓄力前摇:即将发射的键下方圆形蓄力 + const list=ks.hotList||(ks.hot>=0?[ks.hot]:[]); + for(const kh of list){const kx=-(n-1)*5+kh*10; + ctx.globalAlpha=0.3+0.55*pr;ctx.strokeStyle="#43e8ff";ctx.lineWidth=1.5; + ctx.beginPath();ctx.arc(kx,28,2+3.5*pr,0,TAU);ctx.stroke(); + ctx.globalAlpha=0.22*pr;ctx.fillStyle="#43e8ff"; + ctx.beginPath();ctx.arc(kx,28,2+3.5*pr,0,TAU);ctx.fill(); + ctx.globalAlpha=1;}} const off=split*30; // 两半穹顶向左右裂开 for(const sd of[-1,1]){ctx.save();ctx.translate(sd*off,0); const q0=sd<0?Math.PI:Math.PI*1.5,q1=sd<0?Math.PI*1.5:Math.PI*2; @@ -247,9 +255,13 @@ function drawPiano(b,t,fl,split){ // 激光钢琴(split=裂壳进度0~1) if(split<1){ctx.globalAlpha=1-split; // 一阶段青色核心窗 px(-7,-14,14,9,fl||"#43e8ff");px(-4,-12,8,5,"#bfefff"); ctx.globalAlpha=1;} - px(-10-off,-32,20,10,"#3a4460");px(-6-off,-37,12,5,"#55648a"); // 舰桥随左半壳 - if(split<0.4)for(let i=0;i<7;i++){const a=Math.PI+(i+0.5)/7*Math.PI; - px(Math.cos(a)*110-1.5,6+Math.sin(a)*30-1.5,3,3,"#9fb4d8");} + for(const sd of[-1,1]){ctx.save();ctx.translate(sd*off,0); // 舰桥从中线剖开,各随各的半壳 + px(sd<0?-10:0,-32,10,10,"#3a4460"); + px(sd<0?-6:0,-37,6,5,"#55648a"); + for(let i=0;i<7;i++){const a=Math.PI+(i+0.5)/7*Math.PI; // 壳沿铆钉也随半壳 + if((sd<0)!==(a