🎮ArcadeLab

蓝白能量飞碟漫游

by WildWave23
224 lines5.7 KB
▶ Play
<!DOCTYPE html>
 <html lang="zh-CN">
 <head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
 <title>蓝白能量飞碟漫游</title>
 <style>
 *{margin:0;padding:0;box-sizing:border-box}
 body{overflow:hidden;background:#000;touch-action:none}
 canvas{display:block;width:100vw;height:100vh}
 </style>
 </head>
 <body>
 <canvas id="gameCanvas"></canvas>
 <script>
 const canvas = document.getElementById('gameCanvas');
 const ctx = canvas.getContext('2d');
 function resize(){
   canvas.width = window.innerWidth;
   canvas.height = window.innerHeight;
 }
 resize();
 window.addEventListener('resize',resize);
 let ship = {x:canvas.width/2,y:canvas.height/2,vx:0,vy:0,r:28};
 let targetX = ship.x, targetY = ship.y;
 let sceneId = 0;
 // 三个完全区分开的场景
 const sceneList = [
   {
     name:"浩瀚宇宙星空",
     bg1:"#030513",
     bg2:"#091035",
     hasNebula:true,
     hasIce:false
   },
   {
     name:"飞碟能量夹层",
     bg1:"#070b20",
     bg2:"#131e46",
     hasNebula:false,
     hasEnergyFog:true,
     hasIce:false
   },
   {
     name:"南极冰墙溶洞",
     bg1:"#040f17",
     bg2:"#0b2436",
     hasNebula:false,
     hasIce:true
   }
 ];
 let portal = {x:0,y:0,r:90,pulse:0};
 let stars = [];
 let fogParticles = [];
 let transition = 0;
 // 生成星空粒子
 function buildStars(){
   stars = [];
   for(let i=0;i<400;i++){
     stars.push({
       x:Math.random()*canvas.width,
       y:Math.random()*canvas.height,
       size:Math.random()*1.6+0.2,
       twinkle:Math.random()*Math.PI*2
     })
   }
 }
 // 生成能量雾粒子(夹层场景用)
 function buildFog(){
   fogParticles = [];
   for(let i=0;i<120;i++){
     fogParticles.push({
       x:Math.random()*canvas.width,
       y:Math.random()*canvas.height,
       size:Math.random()*20+5,
       speedX:(Math.random()-0.5)*0.3,
       speedY:(Math.random()-0.5)*0.3,
       alpha:Math.random()*0.25
     })
   }
 }
 buildStars();
 buildFog();
 canvas.addEventListener('touchmove',e=>{
   e.preventDefault();
   const t = e.touches[0];
   targetX = t.clientX;
   targetY = t.clientY;
 })
 canvas.addEventListener('touchstart',e=>{
   const t = e.touches[0];
   targetX = t.clientX;
   targetY = t.clientY;
 })
 function changeScene(){
   sceneId = (sceneId+1) % sceneList.length;
   transition = 1;
   buildStars();
   buildFog();
   resetPortal();
 }
 function resetPortal(){
   portal.x = Math.random()*(canvas.width*0.5)+canvas.width*0.25;
   portal.y = Math.random()*(canvas.height*0.5)+canvas.height*0.25;
 }
 resetPortal();
 //葫芦飞碟绘制
 function drawShip(){
   ctx.save();
   ctx.translate(ship.x,ship.y);
   const gradOuter = ctx.createRadialGradient(0,0,10,0,0,45);
   gradOuter.addColorStop(0,"rgba(180,220,255,0.7)");
   gradOuter.addColorStop(1,"rgba(80,150,255,0)");
   ctx.fillStyle = gradOuter;
   ctx.beginPath();
   ctx.arc(0,0,45,0,Math.PI*2);
   ctx.fill();
   ctx.fillStyle="#e8f4ff";
   ctx.beginPath();
   ctx.ellipse(0,-14,14,16,0,0,Math.PI*2);
   ctx.fill();
   ctx.beginPath();
   ctx.ellipse(0,12,22,18,0,0,Math.PI*2);
   ctx.fill();
   ctx.fillStyle="#081022";
   const holeR = 4;
   for(let i=0;i<6;i++){
     const ang = Math.PI*2/6*i;
     let hx = Math.cos(ang)*16;
     let hy = Math.sin(ang)*12+12;
     ctx.beginPath();
     ctx.arc(hx,hy,holeR,0,Math.PI*2);
     ctx.fill();
   }
   ctx.restore();
 }
 //传送光圈
 function drawPortal(){
   portal.pulse +=0.035;
   const pulseR = portal.r + Math.sin(portal.pulse)*14;
   ctx.save();
   ctx.translate(portal.x,portal.y);
   for(let l=3;l>0;l--){
     ctx.strokeStyle=`rgba(140,200,255,${0.25*l})`;
     ctx.lineWidth=3+l;
     ctx.beginPath();
     ctx.arc(0,0,pulseR - l*12,0,Math.PI*2);
     ctx.stroke();
   }
   ctx.restore();
 }
 //绘制背景和场景独有元素
 function drawBackground(){
   const sc = sceneList[sceneId];
   const grad = ctx.createLinearGradient(0,0,0,canvas.height);
   grad.addColorStop(0,sc.bg1);
   grad.addColorStop(1,sc.bg2);
   ctx.fillStyle = grad;
   ctx.fillRect(0,0,canvas.width,canvas.height);
   // 绘制星星
   stars.forEach(s=>{
     s.twinkle +=0.02;
     const alpha = 0.35 + Math.sin(s.twinkle)*0.45;
     ctx.fillStyle=`rgba(240,245,255,${alpha})`;
     ctx.beginPath();
     ctx.arc(s.x,s.y,s.size,0,Math.PI*2);
     ctx.fill();
   })
   //能量夹层:流动薄雾
   if(sc.hasEnergyFog){
     fogParticles.forEach(p=>{
       p.x += p.speedX;
       p.y += p.speedY;
       if(p.x<0)p.x=canvas.width;
       if(p.x>canvas.width)p.x=0;
       if(p.y<0)p.y=canvas.height;
       if(p.y>canvas.height)p.y=0;
       ctx.fillStyle=`rgba(160,200,255,${p.alpha})`;
       ctx.beginPath();
       ctx.arc(p.x,p.y,p.size,0,Math.PI*2);
       ctx.fill();
     })
   }
   //溶洞场景:冰纹光点
   if(sc.hasIce){
     fogParticles.forEach(p=>{
       p.x += p.speedX*0.15;
       p.y += p.speedY*0.15;
       if(p.x<0)p.x=canvas.width;
       if(p.x>canvas.width)p.x=0;
       if(p.y<0)p.y=canvas.height;
       if(p.y>canvas.height)p.y=0;
       ctx.fillStyle=`rgba(180,230,255,${p.alpha*0.7})`;
       ctx.beginPath();
       ctx.arc(p.x,p.y,p.size*0.5,0,Math.PI*2);
       ctx.fill();
     })
   }
 }
 function drawTransition(){
   if(transition <=0) return;
   ctx.fillStyle=`rgba(220,240,255,${transition*0.85})`;
   ctx.fillRect(0,0,canvas.width,canvas.height);
   transition -=0.022;
 }
 function loop(){
   requestAnimationFrame(loop);
   ship.vx = (targetX - ship.x)*0.06;
   ship.vy = (targetY - ship.y)*0.06;
   ship.x += ship.vx;
   ship.y += ship.vy;
   const dist = Math.hypot(ship.x-portal.x, ship.y-portal.y);
   if(dist < portal.r && transition <=0){
     changeScene();
   }
   drawBackground();
   drawPortal();
   drawShip();
   drawTransition();
 }
 loop();
 </script>
 </body>
 </html>

Game Source: 蓝白能量飞碟漫游

Creator: WildWave23

Libraries: none

Complexity: complex (224 lines, 5.7 KB)

The full source code is displayed above on this page.

Remix Instructions

To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: game-wildwave23-mv52u7yg" to link back to the original. Then publish at arcadelab.ai/publish.