improvements Cyst_Kid
This commit is contained in:
@@ -12,9 +12,7 @@ constructor(){
|
||||
this.lv=1;this.lives=3;this.sc=0;this.lsc=0;
|
||||
this.lt=0;this.ld=0;this.tt=0;this.td=0;
|
||||
this.dots=[];this.nDots=0;this.eDots=0;
|
||||
this.pl=null;this.pains=[];this.cysts=[];this.bios=[];
|
||||
this.ateSt=false;this.ateBi=false;this.combD=0;this.combN=1;
|
||||
this.sup=false;this.supT=0;
|
||||
this.pl=null;this.pains=[];
|
||||
this.fx=[];this.fr=0;this.lastT=0;this.acc=0;
|
||||
// Input
|
||||
this.ks={up:false,down:false,left:false,right:false,shift:false};
|
||||
@@ -33,6 +31,7 @@ _rsz(){
|
||||
// ---------- INPUT ----------
|
||||
_inp(){
|
||||
window.addEventListener('keydown',e=>{
|
||||
if(e.target.tagName==='INPUT')return;
|
||||
let h=true;
|
||||
switch(e.code){
|
||||
case'ArrowUp':case'KeyW':this.ks.up=true;break;
|
||||
@@ -143,16 +142,19 @@ _dir(){
|
||||
_ui(){
|
||||
document.getElementById('startBtn').onclick=()=>{this.snd.init();this._start()};
|
||||
document.getElementById('nextLevelBtn').onclick=()=>this._ent();
|
||||
document.getElementById('restartBtn').onclick=()=>{this.sc=0;this._start()};
|
||||
document.getElementById('restartBtn').onclick=()=>{this.sc=0;this._ov('start')};
|
||||
document.getElementById('submitScoreBtn').onclick=()=>this._sub();
|
||||
document.getElementById('playAgainBtn').onclick=()=>this._ov('start');
|
||||
document.getElementById('playAgainBtn').onclick=()=>{this.sc=0;this._ov('start')};
|
||||
document.getElementById('go-submitScoreBtn').onclick=()=>this._subGO();
|
||||
document.getElementById('playerName').addEventListener('keydown',e=>{if(e.key==='Enter'){e.stopPropagation();this._sub()}});
|
||||
document.getElementById('go-playerName').addEventListener('keydown',e=>{if(e.key==='Enter'){e.stopPropagation();this._subGO()}});
|
||||
}
|
||||
|
||||
_esc(){if(this.state==='playing'){this.sc=0;this.lsc=0;this.state='start';this._ov('start')}}
|
||||
|
||||
_ent(){
|
||||
if(this.state==='lvlDone'){this.lv++;this._init();this.state='playing';this._ov(null)}
|
||||
else if(this.state==='over'){this.sc=0;this._start()}
|
||||
else if(this.state==='over'||this.state==='win'){this.sc=0;this._ov('start')}
|
||||
else if(this.state==='start'){this.snd.init();this._start()}
|
||||
}
|
||||
|
||||
@@ -168,10 +170,13 @@ _ov(n){
|
||||
// ---------- LIFECYCLE ----------
|
||||
_init(){
|
||||
this.dots=[];this.nDots=0;this.eDots=0;
|
||||
this.meds=MED_SPAWNS.map(sp=>({r:sp.r,c:sp.c,eaten:true,pulse:0,respT:0}));
|
||||
for(let r=0;r<ROWS;r++)for(let c=0;c<COLS;c++)if(MAP[r][c]===0){this.dots.push({r,c,e:false});this.nDots++}
|
||||
this.lsc=0;this.lt=0;this.ld=0;this.sup=false;this.supT=0;
|
||||
this.ateSt=false;this.ateBi=false;this.combD=0;this.combN=this.lv;
|
||||
this.fx=[];this.lives=3;this.qDir=null;
|
||||
this.lsc=0;this.lt=0;this.ld=0;
|
||||
this.fx=[];this.lives=LIVES;this.qDir=null;
|
||||
this.hasMed=false;this.patient=null;
|
||||
this.challActive=false;this.challTimer=0;this.challGhostIdx=-1;
|
||||
this.nextChallIn=(FPS*(CHALL_FIRST_MIN+Math.random()*(CHALL_FIRST_MAX-CHALL_FIRST_MIN)))|0;
|
||||
|
||||
this.pl={
|
||||
x:PL0.c*TILE, y:PL0.r*TILE+HUD_TOP,
|
||||
@@ -187,23 +192,16 @@ _init(){
|
||||
x:h.c*TILE, y:h.r*TILE+HUD_TOP,
|
||||
gc:h.c, gr:h.r,
|
||||
dir:'up', moving:false,
|
||||
spd:1.2+this.lv*0.2,
|
||||
strat:st[i], scared:false, eaten:false,
|
||||
spd:GHOST_SPD_BASE+this.lv*GHOST_SPD_LEVEL,
|
||||
strat:st[i], scared:false, eaten:i>=2,
|
||||
inHouse:true, leaving:false,
|
||||
relT:i*80+50,
|
||||
relT:i<2?i*GHOST_REL_INTERVAL+GHOST_REL_OFFSET:999999,
|
||||
dormant:i>=2,
|
||||
pulse:Math.random()*6.28
|
||||
}));
|
||||
|
||||
this.cysts=[];
|
||||
this._rp(this.lv,1,8).forEach(p=>this.cysts.push({r:p.r,c:p.c,e:false,v:true}));
|
||||
this.bios=[];
|
||||
}
|
||||
|
||||
_rp(n,mr,xr){
|
||||
const cs=[];for(let r=mr;r<=xr;r++)for(let c=1;c<COLS-1;c++)if(isPath(r,c))cs.push({r,c});
|
||||
for(let i=cs.length-1;i>0;i--){const j=0|Math.random()*(i+1);[cs[i],cs[j]]=[cs[j],cs[i]]}
|
||||
const o=[];for(const p of cs){if(o.length>=n)break;if(o.every(q=>Math.abs(q.r-p.r)+Math.abs(q.c-p.c)>=4))o.push(p)}return o;
|
||||
}
|
||||
|
||||
// -------- MAIN LOOP --------
|
||||
_loop(ts){
|
||||
@@ -219,15 +217,16 @@ _upd(){
|
||||
const liveDir=this._dir();
|
||||
if(liveDir) this.qDir=liveDir;
|
||||
const wantDir=this.qDir;
|
||||
const base=BASE_SPD+(this.lv-1)*0.2;
|
||||
const base=BASE_SPD+(this.lv-1)*GHOST_SPD_LEVEL;
|
||||
const gp=this._gp();
|
||||
const sprint=this.ks.shift||(gp.sprint||false);
|
||||
this.pl.spd=this.sup?base*2:(sprint?base*2:base);
|
||||
this.pl.spd=this.sup?base*SPEED_MULT:(sprint?base*SPEED_MULT:base);
|
||||
|
||||
this._movePl(wantDir);
|
||||
this._movePains();
|
||||
this._coll();
|
||||
if(this.sup){this.supT--;if(this.supT<=0)this._esup()}
|
||||
this._tickMeds();
|
||||
this._tickChall();
|
||||
this.fx=this.fx.filter(f=>{f.t--;return f.t>0});
|
||||
this._chkDone();
|
||||
}
|
||||
@@ -236,9 +235,8 @@ _upd(){
|
||||
_coll(){
|
||||
for(const p of this.pains){
|
||||
if(p.eaten||p.inHouse||p.leaving)continue;
|
||||
if(Math.abs(this.pl.x-p.x)+Math.abs(this.pl.y-p.y)<TILE*.8){
|
||||
if(this.sup&&p.scared){p.eaten=true;this.lsc+=5;this.snd.bite();this.fx.push({x:p.x+TILE/2,y:p.y+TILE/2,co:'#00ff88',t:20,mx:20,tp:'burst'})}
|
||||
else if(!this.sup){this._die();return}
|
||||
if(Math.abs(this.pl.x-p.x)+Math.abs(this.pl.y-p.y)<TILE*COLL_DIST){
|
||||
this._die();return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -246,18 +244,77 @@ _coll(){
|
||||
_die(){
|
||||
this.lives--;this.snd.boom();
|
||||
this.fx.push({x:this.pl.x+TILE/2,y:this.pl.y+TILE/2,co:'#FF4444',t:40,mx:40,tp:'exp'});
|
||||
if(this.lives<=0){this.lsc=0;this.state='over';this.snd.over();setTimeout(()=>this._ov('over'),600)}
|
||||
if(this.lives<=0){this.sc+=this.lsc;this.lsc=0;this.state='over';this.snd.over();setTimeout(()=>this._ov('over'),600)}
|
||||
else{
|
||||
this.pl.x=PL0.c*TILE;this.pl.y=PL0.r*TILE+HUD_TOP;this.pl.gc=PL0.c;this.pl.gr=PL0.r;this.pl.dir='right';this.pl.moving=false;
|
||||
this.qDir=null;this.swD=null;this.ks.up=this.ks.down=this.ks.left=this.ks.right=false;
|
||||
PH.forEach((h,i)=>{const p=this.pains[i];p.x=h.c*TILE;p.y=h.r*TILE+HUD_TOP;p.gc=h.c;p.gr=h.r;p.inHouse=true;p.leaving=false;p.eaten=false;p.relT=i*90+60;p.moving=false});
|
||||
PH.forEach((h,i)=>{const p=this.pains[i];
|
||||
if(p.dormant){p.inHouse=true;p.leaving=false;p.eaten=true;p.relT=999999;p.moving=false;return}
|
||||
p.x=h.c*TILE;p.y=h.r*TILE+HUD_TOP;p.gc=h.c;p.gr=h.r;p.inHouse=true;p.leaving=false;p.eaten=false;p.relT=i*GHOST_REL_INTERVAL+GHOST_REL_OFFSET;p.moving=false});
|
||||
this._endChall();
|
||||
}
|
||||
}
|
||||
|
||||
_tickMeds(){
|
||||
for(const m of this.meds){
|
||||
if(m.eaten){if(m.respT>0&&--m.respT<=0){m.eaten=false;m.pulse=0}}
|
||||
else{m.pulse+=0.08}
|
||||
}
|
||||
}
|
||||
|
||||
_tickChall(){
|
||||
if(!this.challActive){if(--this.nextChallIn<=0)this._startChall()}
|
||||
else{if(--this.challTimer<=0)this._failChall()}
|
||||
}
|
||||
|
||||
_startChall(){
|
||||
if(!MED_SPAWNS||!MED_SPAWNS.length)return;
|
||||
const gi=this.pains.findIndex(p=>p.dormant);
|
||||
if(gi<0)return;
|
||||
// pick patient position, far from player
|
||||
const cells=[];
|
||||
for(let r=1;r<ROWS-1;r++)for(let c=1;c<COLS-1;c++)
|
||||
if(isPath(r,c)&&Math.abs(r-this.pl.gr)+Math.abs(c-this.pl.gc)>5)cells.push({r,c});
|
||||
if(!cells.length)return;
|
||||
const pc=cells[0|Math.random()*cells.length];
|
||||
// activate a random med spawn
|
||||
const avail=this.meds.filter(m=>m.eaten);
|
||||
if(!avail.length)return;
|
||||
const med=avail[0|Math.random()*avail.length];
|
||||
med.eaten=false;med.pulse=0;
|
||||
// activate ghost
|
||||
const g=this.pains[gi];
|
||||
g.dormant=false;g.inHouse=true;g.leaving=false;g.eaten=false;
|
||||
g.relT=FPS*CHALL_DURATION;
|
||||
this.patient={r:pc.r,c:pc.c};
|
||||
this.challActive=true;this.challTimer=FPS*CHALL_DURATION;this.challGhostIdx=gi;
|
||||
}
|
||||
|
||||
_succChall(){
|
||||
const g=this.pains[this.challGhostIdx];
|
||||
this.fx.push({x:g.x+TILE/2,y:g.y+TILE/2,co:'#00ff88',t:40,mx:40,tp:'burst'});
|
||||
g.eaten=true;g.dormant=true;g.inHouse=true;g.leaving=false;g.relT=999999;
|
||||
this.lsc+=SC_CHALL;this.snd.laser();
|
||||
this._endChall();
|
||||
}
|
||||
|
||||
_failChall(){
|
||||
if(this.challGhostIdx>=0)this.pains[this.challGhostIdx].relT=0;
|
||||
this._endChall();
|
||||
}
|
||||
|
||||
_endChall(){
|
||||
this.meds.filter(m=>!m.eaten).forEach(m=>{m.eaten=true;});
|
||||
this.patient=null;
|
||||
this.challActive=false;this.challTimer=0;this.challGhostIdx=-1;
|
||||
this.hasMed=false;
|
||||
this.nextChallIn=(FPS*(CHALL_NEXT_MIN+Math.random()*(CHALL_NEXT_MAX-CHALL_NEXT_MIN)))|0;
|
||||
}
|
||||
|
||||
_chkDone(){
|
||||
if(this.eDots>=this.nDots&&this.cysts.every(c=>c.e)&&this.combD>=this.combN){
|
||||
this.sc+=this.lsc;this.tt+=this.lt;this.td+=this.ld;this.snd.lvlUp();
|
||||
if(this.lv>=3){this.state='win';setTimeout(()=>this._ov('win'),800)}
|
||||
if(this.eDots>=this.nDots){
|
||||
this.sc+=this.lsc;this.lsc=0;this.tt+=this.lt;this.td+=this.ld;this.snd.lvlUp();
|
||||
if(this.lv>=WIN_LEVEL){this.state='win';setTimeout(()=>this._ov('win'),800)}
|
||||
else{this.state='lvlDone';setTimeout(()=>this._ov('lvlDone'),800)}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user