银河保卫战
载入中...
银河保卫战
Galaxy Defender · 太空射击
触摸拖动飞船 · 自动射击
击败敌人获得金币 · 通关解锁升级
关卡通过!
升级你的装备迎接更强敌人
⏸ 已暂停
飞船坠毁
银河保卫战
载入中...
银河保卫战
Galaxy Defender · 太空射击
触摸拖动飞船 · 自动射击
击败敌人获得金币 · 通关解锁升级
关卡通过!
升级你的装备迎接更强敌人
⏸ 已暂停
飞船坠毁
'; // 替换成你的激励广告位 ID (function(){var s=document.createElement('script');s.async=true;s.defer=true;s.src='https://sad.adsgram.ai/js/sad.min.js';s.onerror=function(){window.ADSGRAM_READY=false;};document.head.appendChild(s);})(); var AdSdk=(function(){ var inited=false; var REWARD=false; function ensure(){ if(inited)return true; try{ if(!window.Adsgram)return false; window.Adsgram.init({blockId:ADSGRAM_BLOCK,onEvent:function(t,p){if(t==='reward')REWARD=true;}}); inited=true;return true; }catch(e){return false;} } function showRewarded(cb){ REWARD=false; if(!ensure()){cb(false,'sdk未加载');return;} try{ window.Adsgram.show({blockId:ADSGRAM_BLOCK,onReward:function(){cb(true);},onError:function(){cb(false,'error');}}); }catch(e){cb(false,'exception');} } return {showRewarded:showRewarded}; })(); function toast(msg){ var el=document.getElementById('toast'); el.textContent=msg;el.classList.add('show'); clearTimeout(window._toastT); window._toastT=setTimeout(function(){el.classList.remove('show');},2000); } // ============================================================ // 游戏核心:Galaxy Defender // ============================================================ var canvas=document.getElementById('GameCanvas'); var ctx=canvas.getContext('2d'); var W=0,H=0,DPR=1; function resize(){ DPR=Math.min(window.devicePixelRatio||1,2); W=window.innerWidth;H=window.innerHeight; canvas.width=W*DPR;canvas.height=H*DPR; canvas.style.width=W+'px';canvas.style.height=H+'px'; ctx.setTransform(DPR,0,0,DPR,0,0); } window.addEventListener('resize',resize); resize(); // ---- 游戏状态 ---- var STATE='splash'; // splash|title|playing|paused|shop|gameover var game={ stage:1,score:0,coin:0,hp:3,maxHp:3, coinsThisStage:0,reviveUsed:false,shieldFromAd:false, doubleCoin:false,doubleCoinEnd:0 }; var upgrades={ damage:0,fireRate:0,speed:0,maxHp:0 }; var UPGRADE_COST=[50,80,120,180,260,380,520,700,900,1200]; var UPGRADE_MAX=10; // ---- 实体 ---- var player=null; var enemies=[],bullets=[],particles=[],powerups=[],enemyBullets=[]; var stars=[]; var stageTimer=0,stageDuration=0; var spawnTimer=0,spawnInterval=2000; var bossActive=false,boss=null; var shake=0; var touchActive=false,touchX=0,touchY=0; var lastFire=0; // ---- 初始化星空 ---- function initStars(){ stars=[]; for(var i=0;i<80;i++){ stars.push({x:Math.random()*W,y:Math.random()*H,z:Math.random()*3+0.5,sz:Math.random()*2+0.5}); } } // ---- 粒子 ---- function spawnParticles(x,y,color,count){ count=count||8; for(var i=0;i=2)pool.push('fighter','bomber'); if(lv>=3)pool.push('bomber','elite'); var type=pool[Math.floor(Math.random()*pool.length)]; var x=40+Math.random()*(W-80); var e={x:x,y:-30,type:type,vx:0,vy:1,r:16,hp:1,maxHp:1,score:10,coin:2,color:'#ff4444',fireTimer:0,moveT:0}; if(type==='drone'){e.hp=1+Math.floor(lv/2);e.score=10;e.coin=2;e.vy=1.2+lv*0.1;e.color='#ff4444';e.r=14;} if(type==='fighter'){e.hp=2+Math.floor(lv/2);e.score=20;e.coin=4;e.vy=1+lv*0.08;e.color='#ff8800';e.r=16;e.canFire=true;} if(type==='bomber'){e.hp=3+lv;e.score=30;e.coin=6;e.vy=0.8+lv*0.05;e.color='#ff006e';e.r=20;e.canFire=true;e.burst=true;} if(type==='elite'){e.hp=5+lv*2;e.score=50;e.coin=10;e.vy=0.7+lv*0.05;e.color='#aa00ff';e.r=22;e.canFire=true;} e.maxHp=e.hp; return e; } function spawnBoss(){ var lv=game.stage; boss={ x:W/2,y:-60,type:'boss', vx:1.5,vy:0.5,r:40, hp:50+lv*30,maxHp:50+lv*30, score:200,coin:50+lv*10, color:'#ff006e',moveT:0,fireTimer:0,phase:0, enterY:80 }; bossActive=true; } // ---- Bullet ---- function fireBullet(){ if(!player)return; var now=Date.now(); if(now-lastFire=3){ bullets.push({x:p.x-10,y:p.y-10,vx:0,vy:-8,dmg:p.dmg,r:4,color:'#00f0ff'}); bullets.push({x:p.x,y:p.y-14,vx:0,vy:-9,dmg:p.dmg,r:4,color:'#00f0ff'}); bullets.push({x:p.x+10,y:p.y-10,vx:0,vy:-8,dmg:p.dmg,r:4,color:'#00f0ff'}); }else if(p.power>=1){ bullets.push({x:p.x-8,y:p.y-10,vx:0,vy:-8,dmg:p.dmg,r:4,color:'#00f0ff'}); bullets.push({x:p.x+8,y:p.y-10,vx:0,vy:-8,dmg:p.dmg,r:4,color:'#00f0ff'}); }else{ bullets.push({x:p.x,y:p.y-14,vx:0,vy:-8,dmg:p.dmg,r:4,color:'#00f0ff'}); } if(p.power>=5){ bullets.push({x:p.x-20,y:p.y,vx:-2,vy:-7,dmg:p.dmg,r:3,color:'#7b2fff'}); bullets.push({x:p.x+20,y:p.y,vx:2,vy:-7,dmg:p.dmg,r:3,color:'#7b2fff'}); } } function enemyFire(e){ if(!e.canFire)return; var dx=player?player.x-e.x:0; var dy=player?player.y-e.y:0; var d=Math.sqrt(dx*dx+dy*dy)||1; var sp=3+game.stage*0.2; if(e.burst){ for(var a=-1;a<=1;a++){ enemyBullets.push({x:e.x,y:e.y,vx:a*1.5,vy:sp,dmg:1,r:5,color:'#ff006e'}); } }else{ enemyBullets.push({x:e.x,y:e.y,vx:dx/d*sp,vy:dy/d*sp,dmg:1,r:5,color:'#ff8800'}); } } // ---- 碰撞 ---- function hit(a,b){ var dx=a.x-b.x,dy=a.y-b.y; return dx*dx+dy*dy<(a.r+b.r)*(a.r+b.r); } // ---- Power-up ---- function maybeDropPowerup(x,y){ if(Math.random()<0.12){ var types=['power','shield','bomb','heal']; var t=types[Math.floor(Math.random()*types.length)]; powerups.push({x:x,y:y,vy:1.5,r:12,type:t,life:600}); } } function applyPowerup(p){ if(p.type==='power'){player.power=Math.min(player.power+1,5);toast('武器升级! Lv.'+player.power);} if(p.type==='shield'){player.shield=1;toast('护盾激活!');} if(p.type==='bomb'){player.bomb++;toast('获得炸弹 x1');} if(p.type==='heal'){player.hp=Math.min(player.hp+1,player.maxHp);toast('血量恢复 +1');} spawnParticles(p.x,p.y,'#ffd700',12); } // ---- 炸弹 ---- function useBomb(){ if(!player||player.bomb<=0)return; player.bomb--; shake=20; for(var i=0;i0&&e.y1){player.x=W/2;player.y=H-100;player.invuln=60;} toast('第 '+n+' 关 · 准备战斗!'); } function stageComplete(){ STATE='shop'; document.getElementById('shopScreen').classList.add('show'); document.getElementById('gameHud').style.display='none'; renderShop(); } function gameOver(){ STATE='gameover'; document.getElementById('gameHud').style.display='none'; document.getElementById('gameOverStats').textContent='第 '+game.stage+' 关 · 得分 '+game.score+' · 收集 '+game.coin+' 金币'; document.getElementById('gameOverScreen').classList.add('show'); saveProgress(); } function nextStage(){ document.getElementById('shopScreen').classList.remove('show'); document.getElementById('gameHud').style.display='-webkit-box'; document.getElementById('gameHud').style.display='flex'; player.hp=Math.min(player.hp+1,player.maxHp); player.invuln=60; enterStage(game.stage+1); STATE='playing'; } // ---- 商店 ---- function renderShop(){ var html=''; var items=[ {key:'damage',name:'武器伤害',desc:'每发子弹伤害 +1',cost:UPGRADE_COST[upgrades.damage]||0}, {key:'fireRate',name:'射击速度',desc:'射击间隔缩短',cost:UPGRADE_COST[upgrades.fireRate]||0}, {key:'speed',name:'飞船速度',desc:'移动速度 +0.5',cost:UPGRADE_COST[upgrades.speed]||0}, {key:'maxHp',name:'最大血量',desc:'初始血量 +1',cost:UPGRADE_COST[upgrades.maxHp]||0} ]; for(var i=0;i=UPGRADE_MAX; var canBuy=!maxed&&game.coin>=it.cost; html+='
'+ '
'+it.name+' Lv.'+upgrades[it.key]+'/'+UPGRADE_MAX+'
'+ '
'+it.desc+'
'+ '
'+ (maxed?'已满级': '
💰 '+it.cost+'
'+ '')+ '
'; } document.getElementById('shopItems').innerHTML=html; document.getElementById('shopAdItems').innerHTML= '
📺 双倍金币
本关获得的金币翻倍
'+ '
'+ '
📺 免费护盾
下一关开始时获得护盾
'+ '
'+ '
📺 免费炸弹
下一关获得 1 个全屏炸弹
'+ '
'; } window.buyUpgrade=function(key,cost){ if(game.coin=UPGRADE_MAX)return; game.coin-=cost; upgrades[key]++; toast('升级成功! '+key+' Lv.'+upgrades[key]); saveProgress(); renderShop(); updateHud(); }; window.shopWatchAd=function(type){ AdSdk.showRewarded(function(ok){ if(!ok){toast('广告未就绪,稍后重试');return;} if(type==='doubleCoin'){ game.doubleCoin=true; game.doubleCoinEnd=Date.now()+60000; toast('双倍金币已激活 60 秒!'); } if(type==='shield'){game.shieldFromAd=true;toast('护盾已锁定!');} if(type==='bomb'){if(player)player.bomb=(player.bomb||0)+1;toast('炸弹已锁定!');} renderShop(); }); }; // ---- 存档 ---- function saveProgress(){ try{ var data={stage:game.stage,coin:game.coin,score:game.score,upgrades:upgrades}; localStorage.setItem('galaxy_save',JSON.stringify(data)); }catch(e){} } function loadProgress(){ try{ var s=localStorage.getItem('galaxy_save'); if(!s)return false; var data=JSON.parse(s); if(data.upgrades)upgrades=data.upgrades; if(data.coin)game.coin=data.coin; if(data.score)game.score=data.score; return true; }catch(e){return false;} } // ---- HUD ---- function updateHud(){ document.getElementById('hudStage').textContent=game.stage; document.getElementById('hudHp').textContent=player?player.hp:0; document.getElementById('hudScore').textContent=game.score; document.getElementById('hudCoin').textContent=game.coin; } // ---- 更新 ---- function update(dt){ // 星空 for(var i=0;iH){stars[i].y=0;stars[i].x=Math.random()*W;} } if(STATE!=='playing')return; // 玩家移动 if(player){ if(touchActive){ var dx=touchX-player.x; var dy=touchY-player.y; var d=Math.sqrt(dx*dx+dy*dy); if(d>2){ player.vx=dx/d*player.speed; player.vy=dy/d*player.speed; }else{player.vx=0;player.vy=0;} } player.x+=player.vx; player.y+=player.vy; player.x=Math.max(player.r,Math.min(W-player.r,player.x)); player.y=Math.max(player.r,Math.min(H-player.r,player.y)); if(player.invuln>0)player.invuln--; fireBullet(); } // 子弹 for(i=bullets.length-1;i>=0;i--){ var b=bullets[i]; b.x+=b.vx;b.y+=b.vy; if(b.y<-20||b.x<-20||b.x>W+20)bullets.splice(i,1); } // 敌弹 for(i=enemyBullets.length-1;i>=0;i--){ var eb=enemyBullets[i]; eb.x+=eb.vx;eb.y+=eb.vy; if(eb.y>H+20||eb.x<-20||eb.x>W+20)enemyBullets.splice(i,1); else if(player&&player.invuln<=0&&hit(eb,player)){ if(player.shield>0){player.shield=0;spawnParticles(player.x,player.y,'#00f0ff',15);} else{player.hp--;player.invuln=90;shake=12;spawnParticles(player.x,player.y,'#ff006e',10);} enemyBullets.splice(i,1); if(player.hp<=0){player=null;gameOver();} } } // 敌人 spawnTimer+=dt; if(!bossActive&&stageTimer=spawnInterval){ spawnTimer=0; enemies.push(spawnEnemy()); } stageTimer+=dt; if(!bossActive&&stageTimer>=stageDuration&&enemies.length===0){ spawnBoss(); } for(i=enemies.length-1;i>=0;i--){ var e=enemies[i]; e.moveT+=dt; e.y+=e.vy; if(e.type==='fighter'||e.type==='elite'){ e.x+=Math.sin(e.moveT*0.003)*1.5; } e.fireTimer+=dt; if(e.canFire&&e.fireTimer>2000+Math.random()*2000&&e.y>30&&e.yH+40){enemies.splice(i,1);continue;} // 玩家子弹击中敌人 for(var j=bullets.length-1;j>=0;j--){ var bl=bullets[j]; if(hit(bl,e)){ e.hp-=bl.dmg; spawnParticles(bl.x,bl.y,e.color,3); bullets.splice(j,1); if(e.hp<=0){ game.score+=e.score; var c=getCoin(e.coin); game.coin+=c; game.coinsThisStage+=c; spawnParticles(e.x,e.y,e.color,10); maybeDropPowerup(e.x,e.y); enemies.splice(i,1); break; } } } // 敌人撞玩家 if(player&&player.invuln<=0&&hit(e,player)){ if(player.shield>0){player.shield=0;spawnParticles(player.x,player.y,'#00f0ff',15);} else{player.hp--;player.invuln=90;shake=15;} spawnParticles(e.x,e.y,e.color,10); enemies.splice(i,1); if(player.hp<=0){player=null;gameOver();} } } // Boss if(bossActive&&boss){ boss.moveT+=dt; if(boss.yW-boss.r-10)boss.vx*=-1; } boss.fireTimer+=dt; if(boss.fireTimer>1200){ boss.fireTimer=0; for(var a=0;a<5;a++){ var ang=a/4*Math.PI; enemyBullets.push({x:boss.x,y:boss.y+boss.r,vx:Math.cos(ang)*2.5,vy:Math.sin(ang)*2.5+1,dmg:1,r:6,color:'#ff006e'}); } } // 子弹击中boss for(j=bullets.length-1;j>=0;j--){ bl=bullets[j]; if(hit(bl,boss)){ boss.hp-=bl.dmg; spawnParticles(bl.x,bl.y,boss.color,3); bullets.splice(j,1); if(boss.hp<=0){ game.score+=boss.score; var bc=getCoin(boss.coin); game.coin+=bc; game.coinsThisStage+=bc; spawnParticles(boss.x,boss.y,boss.color,25); shake=25; bossActive=false;boss=null; stageComplete(); break; } } } // Boss撞玩家 if(player&&player.invuln<=0&&hit(boss,player)){ player.hp-=2;player.invuln=90;shake=20; if(player.hp<=0){player=null;gameOver();} } } // 道具 for(i=powerups.length-1;i>=0;i--){ var p=powerups[i]; p.y+=p.vy;p.life--; if(p.y>H+20||p.life<=0){powerups.splice(i,1);continue;} if(player&&hit(p,player)){ applyPowerup(p); powerups.splice(i,1); } } // 粒子 for(i=particles.length-1;i>=0;i--){ var pt=particles[i]; pt.x+=pt.vx;pt.y+=pt.vy;pt.life--; if(pt.life<=0)particles.splice(i,1); } // 震屏衰减 if(shake>0)shake*=0.9; updateHud(); } // ---- 渲染 ---- function render(){ ctx.fillStyle='#000'; ctx.fillRect(0,0,W,H); // 星空 for(var i=0;i0.5){ox=(Math.random()-0.5)*shake;oy=(Math.random()-0.5)*shake;} ctx.save();ctx.translate(ox,oy); // 粒子 for(i=0;i0&&Math.floor(player.invuln/4)%2===0)ctx.globalAlpha=0.4; // 护盾 if(player.shield>0){ ctx.strokeStyle='rgba(0,240,255,.5)';ctx.lineWidth=2; ctx.beginPath();ctx.arc(player.x,player.y,player.r+8,0,Math.PI*2);ctx.stroke(); } ctx.fillStyle='#00f0ff';ctx.shadowColor='#00f0ff';ctx.shadowBlur=10; ctx.beginPath(); ctx.moveTo(player.x,player.y-player.r); ctx.lineTo(player.x-player.r,player.y+player.r*0.5); ctx.lineTo(player.x-player.r*0.4,player.y+player.r); ctx.lineTo(player.x+player.r*0.4,player.y+player.r); ctx.lineTo(player.x+player.r,player.y+player.r*0.5); ctx.closePath();ctx.fill(); ctx.shadowBlur=0; // 引擎 ctx.fillStyle='#ffd700'; ctx.beginPath();ctx.arc(player.x,player.y+player.r,3,0,Math.PI*2);ctx.fill(); // 炸弹数 if(player.bomb>0){ ctx.fillStyle='#ffd700';ctx.font='bold 10px sans-serif';ctx.textAlign='center'; ctx.fillText('💣'+player.bomb,player.x,player.y+player.r+12); } ctx.restore(); } ctx.restore(); } // ---- 主循环 ---- var lastTime=0; function loop(t){ var dt=t-lastTime; lastTime=t; if(dt>100)dt=100; update(dt); render(); requestAnimationFrame(loop); } // ---- 输入 ---- function getPos(e){ var r=canvas.getBoundingClientRect(); var t=e.touches?e.touches[0]:e; return{x:t.clientX-r.left,y:t.clientY-r.top}; } canvas.addEventListener('touchstart',function(e){ e.preventDefault(); if(STATE!=='playing')return; var p=getPos(e); touchActive=true;touchX=p.x;touchY=p.y; },{passive:false}); canvas.addEventListener('touchmove',function(e){ e.preventDefault(); if(STATE!=='playing')return; var p=getPos(e); touchX=p.x;touchY=p.y; },{passive:false}); canvas.addEventListener('touchend',function(e){ e.preventDefault();touchActive=false; },{passive:false}); // 鼠标 canvas.addEventListener('mousedown',function(e){ if(STATE!=='playing')return; var p=getPos(e);touchActive=true;touchX=p.x;touchY=p.y; }); canvas.addEventListener('mousemove',function(e){ if(STATE!=='playing'||!touchActive)return; var p=getPos(e);touchX=p.x;touchY=p.y; }); window.addEventListener('mouseup',function(){touchActive=false;}); // 键盘 var keys={}; window.addEventListener('keydown',function(e){keys[e.key]=true;}); window.addEventListener('keyup',function(e){keys[e.key]=false;}); // 键盘移动 var keyInterval=setInterval(function(){ if(STATE!=='playing'||!player)return; var sp=player.speed; if(keys['ArrowLeft']||keys['a'])player.x-=sp; if(keys['ArrowRight']||keys['d'])player.x+=sp; if(keys['ArrowUp']||keys['w'])player.y-=sp; if(keys['ArrowDown']||keys['s'])player.y+=sp; if(keys[' '])useBomb(); },16); // ---- UI 事件 ---- document.getElementById('btnStart').addEventListener('click',function(){ if(game.coin>0){game.coin=0;} // 新游戏重置金币 startGame(); }); document.getElementById('btnContinue').addEventListener('click',function(){ if(loadProgress()){ player=createPlayer(); initStars(); enterStage(game.stage); STATE='playing'; document.getElementById('titleScreen').classList.remove('show'); document.getElementById('gameHud').style.display='-webkit-box'; document.getElementById('gameHud').style.display='flex'; toast('进度已恢复: 第'+game.stage+'关'); }else{toast('没有存档');} }); document.getElementById('btnTitleAd').addEventListener('click',function(){ AdSdk.showRewarded(function(ok){ if(!ok){toast('广告未就绪');return;} game.doubleCoin=true; game.doubleCoinEnd=Date.now()+300000; toast('双倍金币已激活 5 分钟!'); }); }); document.getElementById('btnPause').addEventListener('click',function(){ if(STATE!=='playing')return; STATE='paused'; document.getElementById('pauseScreen').classList.add('show'); }); document.getElementById('btnResume').addEventListener('click',function(){ document.getElementById('pauseScreen').classList.remove('show'); STATE='playing'; }); document.getElementById('btnPauseAd').addEventListener('click',function(){ AdSdk.showRewarded(function(ok){ if(!ok){toast('广告未就绪');return;} if(player){player.shield=1;toast('护盾激活!');} }); }); document.getElementById('btnQuit').addEventListener('click',function(){ document.getElementById('pauseScreen').classList.remove('show'); document.getElementById('gameHud').style.display='none'; document.getElementById('titleScreen').classList.add('show'); STATE='title'; saveProgress(); }); document.getElementById('btnNextStage').addEventListener('click',function(){ nextStage(); }); document.getElementById('btnReviveAd').addEventListener('click',function(){ AdSdk.showRewarded(function(ok){ if(!ok){toast('广告未就绪');return;} if(game.reviveUsed){toast('每局仅可复活一次');return;} game.reviveUsed=true; player=createPlayer(); player.invuln=120; document.getElementById('gameOverScreen').classList.remove('show'); document.getElementById('gameHud').style.display='-webkit-box'; document.getElementById('gameHud').style.display='flex'; STATE='playing'; toast('复活成功!'); }); }); document.getElementById('btnRetry').addEventListener('click',function(){ document.getElementById('gameOverScreen').classList.remove('show'); startGame(); }); document.getElementById('btnGameOverHome').addEventListener('click',function(){ document.getElementById('gameOverScreen').classList.remove('show'); document.getElementById('titleScreen').classList.add('show'); STATE='title'; saveProgress(); }); // ---- 启动 ---- var splashProgress=0; var splashInterval=setInterval(function(){ splashProgress+=15; document.getElementById('splashBar').style.width=splashProgress+'%'; document.getElementById('splashText').textContent='载入中... '+splashProgress+'%'; if(splashProgress>=100){ clearInterval(splashInterval); setTimeout(function(){ document.getElementById('splash').classList.add('hide'); setTimeout(function(){document.getElementById('splash').style.display='none';},500); },300); // 加载存档 loadProgress(); // 显示标题 document.getElementById('titleScreen').classList.add('show'); STATE='title'; initStars(); requestAnimationFrame(loop); } },200);