- 8个Boss全部重做:主攻击模式+1~2种随机小攻击+二/三阶段变形动画 - 新增5个雷霆战机参考Boss:太空原种/暗黑突击/激光钢琴/夺权者X/暗黑魔碟 - 多管血条(蓝/红/橙)+锁血转场+入场不掉血(b.y<b.ty-1免疫) - 签名技能:花弹成长/高机动瞄准弹/21键4模式激光/银钉无人机+巨宽激光压制/锥形弹环+眼激光 - 所有激光发射点跟随Boss移动(bossBeam src机制) - Boss挑战模式:随机装备3主武Lv3+3副武Lv3+2僚机Lv2,可选老虎机抽奖动画 - rush模式Boss血量x10,击破计时存档 - 武器修正:黎明重炮近炸引信26px/死光伤害x2/椭圆判定bossHit等
72 lines
4.2 KiB
JavaScript
72 lines
4.2 KiB
JavaScript
"use strict";
|
|
/* ---------------- 音频:程序化合成 ---------------- */
|
|
const AU={ctx:null,master:null,mgain:null,
|
|
init(){ if(this.ctx) return;
|
|
try{ this.ctx=new (window.AudioContext||window.webkitAudioContext)();
|
|
this.master=this.ctx.createGain(); this.master.gain.value=0.5; this.master.connect(this.ctx.destination);
|
|
this.mgain=this.ctx.createGain(); this.mgain.gain.value=SAVE.music?0.16:0; this.mgain.connect(this.master);
|
|
}catch(e){}
|
|
},
|
|
now(){return this.ctx?this.ctx.currentTime:0;},
|
|
env(g,t,a,d,v){g.gain.setValueAtTime(0,t);g.gain.linearRampToValueAtTime(v,t+a);g.gain.exponentialRampToValueAtTime(0.001,t+a+d);},
|
|
tone(f,type,dur,vol=0.2,slide=0){ if(!this.ctx||SAVE.mute)return;
|
|
const t=this.now(),o=this.ctx.createOscillator(),g=this.ctx.createGain();
|
|
o.type=type;o.frequency.setValueAtTime(f,t);
|
|
if(slide) o.frequency.exponentialRampToValueAtTime(Math.max(20,f+slide),t+dur);
|
|
this.env(g,t,0.005,dur,vol); o.connect(g);g.connect(this.master); o.start(t);o.stop(t+dur+0.05); },
|
|
noise(dur,vol=0.25,hp=400){ if(!this.ctx||SAVE.mute)return;
|
|
const t=this.now(),len=Math.floor(this.ctx.sampleRate*dur),buf=this.ctx.createBuffer(1,len,this.ctx.sampleRate),d=buf.getChannelData(0);
|
|
for(let i=0;i<len;i++)d[i]=(Math.random()*2-1)*(1-i/len);
|
|
const s=this.ctx.createBufferSource();s.buffer=buf;
|
|
const f=this.ctx.createBiquadFilter();f.type="highpass";f.frequency.value=hp;
|
|
const g=this.ctx.createGain();this.env(g,t,0.003,dur,vol);
|
|
s.connect(f);f.connect(g);g.connect(this.master);s.start(t); }
|
|
};
|
|
let _shootT=0,_eshootT=0;
|
|
const SFX={
|
|
shoot(){const n=performance.now(); if(n-_shootT<45)return; _shootT=n; AU.tone(880,"square",0.05,0.05,-300);},
|
|
eshoot(){const n=performance.now();if(n-_eshootT<90)return;_eshootT=n;AU.tone(220,"square",0.06,0.03,-80);},
|
|
hit(){AU.noise(0.05,0.12,1200);},
|
|
boom(big){AU.noise(big?0.5:0.25,big?0.4:0.22,big?80:200); AU.tone(big?90:140,"sawtooth",big?0.4:0.2,0.18,-60);},
|
|
pick(){AU.tone(660,"sine",0.08,0.12,300);},
|
|
coin(){AU.tone(990,"square",0.05,0.08);AU.tone(1320,"square",0.08,0.08);},
|
|
level(){[523,659,784,1046].forEach((f,i)=>setTimeout(()=>AU.tone(f,"square",0.1,0.12),i*70));},
|
|
hurt(){AU.tone(160,"sawtooth",0.3,0.3,-100);AU.noise(0.3,0.3,150);},
|
|
bomb(){AU.noise(0.8,0.5,60);AU.tone(70,"sawtooth",0.7,0.3,-40);},
|
|
od(){[440,660,880,1320].forEach((f,i)=>setTimeout(()=>AU.tone(f,"sawtooth",0.09,0.1),i*50));},
|
|
graze(){AU.tone(1800,"sine",0.03,0.04);},
|
|
warn(){for(let i=0;i<4;i++)setTimeout(()=>{AU.tone(440,"square",0.15,0.15);setTimeout(()=>AU.tone(349,"square",0.15,0.15),180);},i*400);},
|
|
};
|
|
/* 简易芯片音序器 */
|
|
const MUS={step:0,next:0,bpm:138,playing:false,boss:false,
|
|
bass:[45,45,48,45,52,45,48,43], lead:[69,72,76,72,74,72,69,64],
|
|
tick(){ if(!AU.ctx||!this.playing||!SAVE.music)return;
|
|
const spb=60/(this.bpm*2);
|
|
while(this.next<AU.now()+0.12){
|
|
const s=this.step%8, t=this.next;
|
|
// 贝斯
|
|
this.mt(this.N(this.bass[s]+(this.boss?2:0)),"triangle",t,spb*0.9,0.5);
|
|
// 琶音
|
|
if(s%2===0||this.boss) this.mt(this.N(this.lead[s]+12),"square",t,spb*0.4,0.12);
|
|
// 鼓点
|
|
if(s%4===0) this.kick(t); this.hat(t+spb/2);
|
|
this.next+=spb; this.step++;
|
|
}
|
|
},
|
|
N(n){return 440*Math.pow(2,(n-69)/12);},
|
|
mt(f,type,t,d,v){const o=AU.ctx.createOscillator(),g=AU.ctx.createGain();
|
|
o.type=type;o.frequency.value=f;g.gain.setValueAtTime(v,t);g.gain.exponentialRampToValueAtTime(0.001,t+d);
|
|
o.connect(g);g.connect(AU.mgain);o.start(t);o.stop(t+d+0.02);},
|
|
kick(t){const o=AU.ctx.createOscillator(),g=AU.ctx.createGain();
|
|
o.frequency.setValueAtTime(150,t);o.frequency.exponentialRampToValueAtTime(40,t+0.1);
|
|
g.gain.setValueAtTime(0.6,t);g.gain.exponentialRampToValueAtTime(0.001,t+0.12);
|
|
o.connect(g);g.connect(AU.mgain);o.start(t);o.stop(t+0.14);},
|
|
hat(t){const len=Math.floor(AU.ctx.sampleRate*0.03),b=AU.ctx.createBuffer(1,len,AU.ctx.sampleRate),d=b.getChannelData(0);
|
|
for(let i=0;i<len;i++)d[i]=(Math.random()*2-1)*(1-i/len);
|
|
const s=AU.ctx.createBufferSource();s.buffer=b;const g=AU.ctx.createGain();
|
|
g.gain.setValueAtTime(0.07,t);g.gain.exponentialRampToValueAtTime(0.001,t+0.03);
|
|
s.connect(g);g.connect(AU.mgain);s.start(t);},
|
|
start(boss){this.playing=true;this.boss=!!boss;this.bpm=boss?152:138;if(AU.ctx)this.next=AU.now()+0.1;},
|
|
stop(){this.playing=false;}
|
|
};
|