用一句完整提示词,直接做出一个“球球大作战”级小游戏

游戏简单演示

视频演示

游戏介绍

一款单机 2D 吃球生存小游戏,玩法类似《球球大作战 / Agar.io》。你操控球体在巨型地图中吞噬食物和更小的敌人,不断变大冲击排行榜。W 分裂冲刺追杀/逃命,S 主动合并收回分身;E/右键发射粘液弹减速命中目标;小心病毒刺球会让大球爆裂。地图随机刷新多种道具(加速、护盾、磁铁、冲刺、双倍、减速光环等),配合操作打出节奏,目标只有一个:活下去,变成最大的那颗球。

这个小游戏是怎么生成出来的?

需要先说明一句:这个完整可玩的 2D 吃球小游戏,并不是手写代码完成的。

我只是通过在线生成环境,用自然语言把玩法和规则一步步描述清楚,包括移动手感、AI 行为、病毒机制、分裂与合并、粘液喷射等细节,再通过多轮生成不断调整,最终直接得到了一个能在浏览器运行的完整 index.html 游戏文件。

我用的生成环境就是下面这套,几个入口本质是同一套服务,只是线路不同,哪个快用哪个即可:

整个过程中不需要本地环境、不需要任何依赖,也不用拆分文件结构,对这种偏玩法、偏展示的项目来说非常省事。更重要的是,它并不是一次性生成,而是可以在原代码基础上持续往上加规则、加机制,把一个想法慢慢"逼"成现在这个完成度。

参考提示词

请用原生 HTML5 + CSS + JavaScript 实现一个类似《球球大作战 / Agar.io》的 2D 单机吃球小游戏,不依赖任何第三方库或打包工具,只输出一个可直接在浏览器打开的 index.html。

硬性功能要求:

  1. 使用 <canvas> 全屏渲染地图,世界为大平面;摄像机跟随玩家(以玩家整体中心为镜头中心)。

  2. 玩家球由鼠标控制移动:具备加速度、最大速度限制与平滑插值;体积越大最大速度越低;加入粘性阻尼(viscous damping)。

  3. 地图初始化大量食物小圆点;被吃后玩家/AI 增加质量(面积模型 πr²);只对已被吃掉的食物复活,60 秒后在随机位置复活,不额外无限补球。

  4. 生成若干 Bot AI 球:自动寻找附近食物发育;追击更小目标;遇到更大玩家/敌人会逃离;会规避病毒;AI 也有名字和分数。

  5. 实现圆形碰撞检测与吞噬:当小球被大球几乎完全覆盖(d + r_small <= r_big*0.98)且体积差超过阈值时判定被吃,质量转移。

  6. W 分身:玩家按 W 分裂(每颗质量减半),新分身朝鼠标方向高速冲刺并有更精确的速度衰减曲线;分裂数量上限与冷却。

  7. S 主动合并:玩家按 S 清除合并冷却并触发"慢慢加速靠拢合并"机制(分身向中心被拉回并重叠后合并)。

  8. 喷射玩法:E 或右键喷射"粘液弹 Slime Shot",消耗少量质量:

    • 粘液弹可被更大球吃掉;
    • 命中球体会施加明显减速/粘性阻尼持续约 2.5 秒;
    • 可用于追杀/逃命/控 AI;
    • 粘液弹也能喂病毒。
  9. 病毒/刺球系统:

    • 大球撞上病毒会爆裂为多分身;
    • 病毒可被粘液弹喂食,喂到阈值会分裂出新病毒并朝最后喂食方向喷射;喷射速度有平滑衰减曲线。
  10. 视野随体积变化:玩家总质量越大,镜头缩放越小(看得更远)。

  11. 边界软限制/回弹:世界有硬边界,靠近边缘会被柔性推回并带轻微回弹,不能穿出地图。

  12. 道具系统(随机刷新、道具更大、带名称显示 + 拾取 Toast + Buff 列表显示余时):至少实现 8 种有意义道具:

  • ⚡加速(8s 提升最大速度)
  • 🛡护盾(抵挡一次被吃)
  • 🧲磁铁(10s 吸附近食物)
  • 💨冲刺(瞬发向鼠标方向强冲)
  • ✨双倍吞噬(12s 吃到的质量×2)
  • ❄减速光环(10s 附近 AI 减速)
  • 🌀分裂充能(清 W 冷却 + 清合并冷却)
  • 🧪粘液强化(10s 粘液弹更大更远更久减速)
  1. UI:显示当前质量/得分、分身数、AI/病毒/食物/道具数量;排行榜 Top5(含 AI 名字与分数);开始/重新开始按钮;小地图 minimap。

代码与结构要求:

  • 面向对象/模块化风格:如 Game、PlayerCell、Bot、Food、SlimeBall、Virus、PowerUp 等类。
  • 对核心算法/关键函数添加简要注释。
  • 输出必须是完整单文件 index.html,复制后浏览器即可运行。

**注意:**不要使用第三方库、不要拆分文件、不要使用构建工具。

最终完整代码

复制代码
<!doctype html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width,initial-scale=1" />
  <title>吃球小游戏</title>
  <style>
    html, body { margin: 0; padding: 0; width: 100%; height: 100%; overflow: hidden; background: #0b0f14; }
    canvas { display: block; width: 100vw; height: 100vh; }

    #ui {
      position: fixed; left: 12px; top: 12px; z-index: 10; color: #e6edf3;
      font-family: system-ui, -apple-system, "Segoe UI", Roboto, "PingFang SC", "Microsoft Yahei", sans-serif;
      user-select: none; pointer-events: none; text-shadow: 0 2px 8px rgba(0,0,0,.6);
    }
    #stats, #leaderboard {
      background: rgba(0,0,0,.35); padding: 8px 10px; border-radius: 10px; font-size: 14px;
      border: 1px solid rgba(255,255,255,.06); backdrop-filter: blur(4px);
      display: block; pointer-events: none;
      margin-bottom: 8px;
      min-width: 280px;
    }
    #leaderboard h4{ margin:0 0 6px 0; font-size:13px; opacity:.9; font-weight:600; }
    #leaderboard ol{ margin:0; padding-left:18px; line-height:1.55; }
    #leaderboard li{ white-space:nowrap; }
    #leaderboard .me{ color:#7dd3fc; font-weight:700; }

    #controls { position: fixed; right: 12px; top: 12px; z-index: 10; display: flex; gap: 8px; pointer-events: auto; }
    button {
      background: rgba(255,255,255,.08); color: #e6edf3; border: 1px solid rgba(255,255,255,.12);
      padding: 8px 12px; border-radius: 10px; cursor: pointer; font-size: 14px;
      transition: .15s ease; backdrop-filter: blur(4px);
    }
    button:hover { transform: translateY(-1px); background: rgba(255,255,255,.12); }

    #hint {
      position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%);
      z-index: 10; color: #e6edf3; text-align: center; font-size: 18px;
      background: rgba(0,0,0,.55); padding: 16px 18px; border-radius: 14px;
      border: 1px solid rgba(255,255,255,.08);
    }
    #hint small { display: block; opacity: .8; margin-top: 6px; font-size: 13px; }
    #hint.hidden { display: none; }

    #minimap {
      position: fixed; right: 12px; bottom: 12px; z-index: 10;
      width: 160px; height: 160px; background: rgba(0,0,0,.35);
      border: 1px solid rgba(255,255,255,.08); border-radius: 12px;
      pointer-events: none;
    }

    #toast {
      position: fixed; left: 50%; top: 14%;
      transform: translateX(-50%);
      z-index: 20; color: #e6edf3; font-size: 18px; font-weight: 700;
      background: rgba(0,0,0,.6); padding: 10px 14px; border-radius: 12px;
      border: 1px solid rgba(255,255,255,.12);
      opacity: 0; transition: .2s ease; pointer-events: none; white-space: nowrap;
    }
    #toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
  </style>
</head>
<body>
  <canvas id="c"></canvas>

  <div id="ui">
    <div id="stats">
      质量:<span id="mass">0</span> 
      分身数:<span id="cells">1</span> 
      得分:<span id="score">0</span> 
      AI:<span id="bots">0</span> 
      病毒:<span id="viruses">0</span> 
      食物:<span id="foods">0</span> 
      道具:<span id="items">0</span>
      <div style="opacity:.8;margin-top:4px;font-size:12px">
        W 分身 / S 合并 / E或右键 粘液喷射(减速命中目标) / 食物60s复活
      </div>
      <div id="buffs" style="opacity:.95;margin-top:4px;font-size:12px"></div>
    </div>

    <div id="leaderboard">
      <h4>排行榜 Top5</h4>
      <ol id="lbList"></ol>
    </div>
  </div>

  <div id="controls">
    <button id="startBtn">开始</button>
    <button id="restartBtn">重新开始</button>
  </div>

  <div id="hint">
    点击"开始"进入游戏<br/>
    <small>鼠标控制方向;W 分身;S 合并;E/右键粘液喷射</small>
  </div>

  <div id="toast"></div>
  <canvas id="minimap"></canvas>

<script>
(() => {
  // ===== utils =====
  const rand = (a, b) => a + Math.random() * (b - a);
  const clamp = (v, a, b) => Math.max(a, Math.min(b, v));
  const dist2 = (ax, ay, bx, by) => { const dx=ax-bx, dy=ay-by; return dx*dx+dy*dy; };
  const dist = (ax, ay, bx, by) => Math.hypot(ax-bx, ay-by);
  const lerp=(a,b,t)=>a+(b-a)*t;
  const hsl=(h,s,l)=>`hsl(${h},${s}%,${l}%)`;

  const BOT_NAMES = [
    "Aqua","Blaze","Coco","Duke","Echo","Frost","Gizmo","Hana","Iris","Jade",
    "Kite","Luna","Mango","Nova","Odin","Pico","Quinn","Rex","Sora","Tango",
    "Uma","Vivi","Wisp","Xeno","Yuki","Zane","Kitty","Bobo","Mimi","Toto"
  ];

  // ===== Entities =====
  class Entity {
    constructor(x,y,r,color){
      this.x=x; this.y=y; this.vx=0; this.vy=0;
      this.mass=Math.PI*r*r; this.r=r; this.color=color;
      this.alive=true; this.name=""; this.mergeCooldown=0;
      this.boostAge=0; this.boostDuration=0;
      this.slowTimer=0; // 被粘液减速的剩余时间
    }
    setMass(m){ this.mass=Math.max(1,m); this.r=Math.sqrt(this.mass/Math.PI); }
    addMass(dm){ this.setMass(this.mass+dm); }

    getMaxSpeed(game){
      const base=300;
      let spd=base/Math.sqrt(this.r/16);

      if(this.isPlayer && game.speedBoostTimer>0) spd*=game.speedBoostMul;
      if(this.slowTimer>0) spd*=game.slowMul;

      if(this.isBot && game.freezeTimer>0){
        const pc=game.playerCenter();
        if(dist(pc.x,pc.y,this.x,this.y)<game.freezeRadius) spd*=game.freezeMul;
      }
      return spd;
    }

    applyViscousDamping(dt){
      const k=0.0009*(this.r/20);
      const factor=Math.exp(-k*dt*60);
      this.vx*=factor; this.vy*=factor;
    }
    applyBoost(vx,vy,duration=0.9){
      this.vx=vx; this.vy=vy; this.boostDuration=duration; this.boostAge=0;
    }
    applyBoostDecay(dt){
      if(this.boostDuration<=0) return;
      this.boostAge+=dt;
      const t=clamp(this.boostAge/this.boostDuration,0,1);
      const drag=lerp(0.015,0.30,t*t);
      const factor=Math.exp(-drag*dt*60);
      this.vx*=factor; this.vy*=factor;
      if(t>=1) this.boostDuration=0;
    }
    moveToward(dx,dy,dt,game){
      const len=Math.hypot(dx,dy)||1;
      const ux=dx/len, uy=dy/len;
      const maxSpd=this.getMaxSpeed(game);
      const desiredVx=ux*maxSpd, desiredVy=uy*maxSpd;
      const smooth=1-Math.pow(0.001,dt);
      this.vx=lerp(this.vx,desiredVx,smooth);
      this.vy=lerp(this.vy,desiredVy,smooth);
      const spd=Math.hypot(this.vx,this.vy);
      if(spd>maxSpd){ this.vx=this.vx/spd*maxSpd; this.vy=this.vy/spd*maxSpd; }
    }
    updateBase(dt,game){
      this.applyBoostDecay(dt);
      this.applyViscousDamping(dt);
      if(this.slowTimer>0) this.slowTimer-=dt;

      this.x+=this.vx*dt; this.y+=this.vy*dt;
      game.applySoftBounds(this,dt);
      if(this.mergeCooldown>0) this.mergeCooldown-=dt;
    }
    draw(ctx){
      ctx.beginPath();
      ctx.fillStyle=this.color;
      ctx.arc(this.x,this.y,this.r,0,Math.PI*2);
      ctx.fill();
      ctx.lineWidth=Math.max(1.2,this.r*0.06);
      ctx.strokeStyle="rgba(0,0,0,0.35)";
      ctx.stroke();

      if(this.name){
        ctx.fillStyle="rgba(255,255,255,0.9)";
        ctx.font=`${Math.max(12,this.r*0.6)}px sans-serif`;
        ctx.textAlign="center"; ctx.textBaseline="middle";
        ctx.fillText(this.name,this.x,this.y);
      }
      // 减速圈提示
      if(this.slowTimer>0){
        ctx.beginPath();
        ctx.strokeStyle="rgba(140,200,255,0.35)";
        ctx.lineWidth=3;
        ctx.arc(this.x,this.y,this.r*1.12,0,Math.PI*2);
        ctx.stroke();
      }
    }
  }

  class PlayerCell extends Entity{
    constructor(x,y,r,color){ super(x,y,r,color); this.isPlayer=true; }
    update(dt,game){
      const dx=game.inputX-game.w/2, dy=game.inputY-game.h/2;
      if(Math.hypot(dx,dy)>5) this.moveToward(dx,dy,dt,game);
      this.updateBase(dt,game);
    }
  }

  class Bot extends Entity{
    constructor(x,y,r,color,name){
      super(x,y,r,color); this.isBot=true; this.name=name;
      this.wanderAngle=rand(0,Math.PI*2); this.thinkTimer=0; this.goal=null;
    }
    update(dt,game){
      this.thinkTimer-=dt;
      if(this.thinkTimer<=0){ this.thinkTimer=rand(0.15,0.35); this.pickGoal(game); }
      if(this.goal) this.moveToward(this.goal.x-this.x,this.goal.y-this.y,dt,game);
      else{
        this.wanderAngle+=rand(-1,1)*dt;
        this.moveToward(Math.cos(this.wanderAngle),Math.sin(this.wanderAngle),dt,game);
      }
      this.updateBase(dt,game);
    }
    pickGoal(game){
      const sense=1200, sense2=sense*sense;
      let bestScore=-Infinity, best=null;

      for(const v of game.viruses){
        const d2=dist2(this.x,this.y,v.x,v.y);
        if(d2>sense2) continue;
        if(this.r>game.config.virusExplodeRadius*0.9){
          const d=Math.sqrt(d2);
          const score=2500/(d+40);
          if(score>bestScore){ bestScore=score; best={x:this.x-(v.x-this.x),y:this.y-(v.y-this.y)}; }
        }
      }

      for(const cell of game.allCells()){
        if(cell===this||!cell.alive) continue;
        const d2=dist2(this.x,this.y,cell.x,cell.y);
        if(d2>sense2) continue;
        const d=Math.sqrt(d2);

        if(cell.r<this.r*0.85){
          const score=4200/(d+80)+cell.mass*0.02;
          if(score>bestScore){ bestScore=score; best=cell; }
        }else if(cell.r>this.r*1.08){
          const score=3000/(d+50);
          if(score>bestScore){ bestScore=score; best={x:this.x-(cell.x-this.x),y:this.y-(cell.y-this.y)}; }
        }
      }

      for(const f of game.foods){
        if(!f.alive) continue;
        const d2=dist2(this.x,this.y,f.x,f.y);
        if(d2>sense2) continue;
        const d=Math.sqrt(d2);
        const score=1200/(d+30)+f.mass*0.5;
        if(score>bestScore){ bestScore=score; best=f; }
      }
      this.goal=best;
    }
  }

  class Food{
    constructor(x,y,r,color){
      this.x=x; this.y=y; this.r=r;
      this.mass=Math.PI*r*r; this.color=color; this.alive=true; this.isFood=true;
    }
    draw(ctx){
      ctx.beginPath();
      ctx.fillStyle=this.color;
      ctx.arc(this.x,this.y,this.r,0,Math.PI*2);
      ctx.fill();
    }
  }

  // 粘液弹:命中减速
  class SlimeBall extends Food{
    constructor(x,y,r,color,vx,vy,slowDuration){
      super(x,y,r,color);
      this.vx=vx; this.vy=vy;
      this.isEjecta=true;
      this.age=0; this.decayDuration=1.0;
      this.slowDuration=slowDuration;
      this.isSlime=true;
    }
    update(dt,game){
      this.age+=dt;
      const t=clamp(this.age/this.decayDuration,0,1);
      const drag=lerp(0.06,0.42,t*t);
      const factor=Math.exp(-drag*dt*60);
      this.vx*=factor; this.vy*=factor;
      this.x+=this.vx*dt; this.y+=this.vy*dt;
      game.applySoftBounds(this,dt,true);
    }
    draw(ctx){
      ctx.beginPath();
      ctx.fillStyle=this.color;
      ctx.arc(this.x,this.y,this.r,0,Math.PI*2);
      ctx.fill();
      ctx.strokeStyle="rgba(255,255,255,0.35)";
      ctx.lineWidth=2;
      ctx.stroke();
    }
  }

  class Virus{
    constructor(x,y,r=38){
      this.x=x; this.y=y; this.r=r; this.mass=Math.PI*r*r;
      this.alive=true; this.isVirus=true; this.color="hsl(115,75%,45%)";
      this.spikeCount=18; this.feedMass=0; this.lastFeedDir={x:1,y:0};
    }
    addMass(dm){ this.mass=Math.max(1,this.mass+dm); this.r=Math.sqrt(this.mass/Math.PI); }
    draw(ctx){
      ctx.save(); ctx.translate(this.x,this.y); ctx.fillStyle=this.color; ctx.beginPath();
      for(let i=0;i<this.spikeCount*2;i++){
        const ang=i*Math.PI/this.spikeCount;
        const rr=(i%2===0)?this.r*1.15:this.r*0.85;
        ctx.lineTo(Math.cos(ang)*rr,Math.sin(ang)*rr);
      }
      ctx.closePath(); ctx.fill();
      ctx.lineWidth=3; ctx.strokeStyle="rgba(0,0,0,0.35)"; ctx.stroke(); ctx.restore();
    }
  }

  // ===== PowerUps =====
  const ITEM_DEFS = {
    speed:  { name:"⚡加速",  color:"hsl(45, 95%, 60%)" , short:"SPD"},
    shield: { name:"🛡护盾",  color:"hsl(210, 90%, 65%)", short:"SHD"},
    magnet: { name:"🧲磁铁",  color:"hsl(300, 85%, 70%)", short:"MAG"},
    dash:   { name:"💨冲刺",  color:"hsl(160, 85%, 55%)", short:"DSH"},
    double: { name:"✨双倍",  color:"hsl(280, 90%, 70%)", short:"DBL"},
    freeze: { name:"❄减速光环", color:"hsl(200, 85%, 75%)", short:"FRZ"},
    splitReset:{ name:"🌀分裂充能", color:"hsl(30, 90%, 65%)", short:"RST"},
    slimePlus:{ name:"🧪粘液强化", color:"hsl(110, 80%, 55%)", short:"SLM"},
  };
  const ITEM_TYPES = Object.keys(ITEM_DEFS);

  class PowerUp{
    constructor(x,y,type){
      this.x=x; this.y=y; this.type=type;
      this.r=22; this.alive=true; this.mass=0; this.isPowerUp=true;
      this.color=ITEM_DEFS[type].color; this.name=ITEM_DEFS[type].name; this.short=ITEM_DEFS[type].short;
    }
    draw(ctx){
      ctx.save(); ctx.translate(this.x,this.y);
      ctx.fillStyle=this.color; ctx.beginPath(); ctx.arc(0,0,this.r,0,Math.PI*2); ctx.fill();
      ctx.fillStyle="rgba(255,255,255,0.9)";
      ctx.beginPath(); for(let i=0;i<6;i++){
        const a=i*Math.PI/3; const rr=(i%2===0)?this.r*0.55:this.r*0.25;
        ctx.lineTo(Math.cos(a)*rr,Math.sin(a)*rr);
      } ctx.closePath(); ctx.fill();
      ctx.fillStyle="rgba(0,0,0,0.8)";
      ctx.font="10px sans-serif"; ctx.textAlign="center"; ctx.textBaseline="middle";
      ctx.fillText(this.short,0,1);

      ctx.fillStyle="rgba(255,255,255,0.95)";
      ctx.font="12px sans-serif"; ctx.textAlign="center"; ctx.textBaseline="top";
      ctx.fillText(this.name,0,this.r+4);
      ctx.restore();
    }
  }

  // ===== Game =====
  class Game{
    constructor(canvas,minimap){
      this.canvas=canvas; this.ctx=canvas.getContext("2d");
      this.minimap=minimap; this.mctx=minimap.getContext("2d");
      this.w=canvas.width=innerWidth; this.h=canvas.height=innerHeight;
      this.worldSize=5600;
      this.playerCells=[]; this.bots=[]; this.foods=[]; this.viruses=[]; this.items=[];
      this.running=false; this.gameOver=false; this.lastTime=performance.now();
      this.inputX=this.w/2; this.inputY=this.h/2;
      this.splitCooldown=0; this.ejectCooldown=0;
      this.foodRespawnTimers=[];

      // buffs
      this.speedBoostTimer=0; this.speedBoostMul=1.6;
      this.magnetTimer=0;
      this.doubleTimer=0;
      this.freezeTimer=0; this.freezeMul=0.6; this.freezeRadius=700;
      this.playerShield=0;
      this.forceMergeTimer=0;
      this.slimePlusTimer=0;  // 粘液强化
      this.slowMul=0.55;      // 被粘液减速倍率

      this.itemSpawnTimer=0;

      this.config={
        foodInitial:2200, foodRespawnDelay:60, foodRadiusRange:[3.2,7.2],
        botTarget:32, botSpawnPerSec:2, maxPlayerCells:8,
        virusCount:12, virusRadius:38, virusExplodeRadius:55,
        virusFeedGain:18, virusSplitThreshold:220, virusShootSpeed:760,
        itemMax:7, itemSpawnEvery:12,
      };

      addEventListener("resize",()=>this.resize());
      this.bindInput(); this.resize();
    }

    bindInput(){
      const setTarget=(x,y)=>{this.inputX=x; this.inputY=y;};
      this.canvas.addEventListener("mousemove",e=>setTarget(e.clientX,e.clientY));
      this.canvas.addEventListener("mousedown",e=>setTarget(e.clientX,e.clientY));
      this.canvas.addEventListener("contextmenu",e=>e.preventDefault());
      this.canvas.addEventListener("mouseup",e=>{ if(e.button===2) this.eject(); });

      addEventListener("keydown",(e)=>{
        if(!this.running) return;
        const k=e.key.toLowerCase();
        if(k==="w"){ e.preventDefault(); this.split(); }
        if(k==="s"){ e.preventDefault(); this.forceMerge(); }
        if(k==="e"){ e.preventDefault(); this.eject(); }
      });
    }

    resize(){ this.w=this.canvas.width=innerWidth; this.h=this.canvas.height=innerHeight; this.minimap.width=this.minimap.height=160; }

    start(){ this.reset(); this.running=true; this.gameOver=false; }

    reset(){
      this.playerCells=[new PlayerCell(this.worldSize/2,this.worldSize/2,24,hsl(195,85,55))];
      this.playerCells[0].name="YOU";
      this.bots=[]; for(let i=0;i<this.config.botTarget;i++) this.spawnBot();
      this.foods=[]; for(let i=0;i<this.config.foodInitial;i++) this.foods.push(this.spawnFood());
      this.viruses=[]; for(let i=0;i<this.config.virusCount;i++) this.viruses.push(this.spawnVirus());
      this.items=[]; this.foodRespawnTimers=[];
      this.splitCooldown=this.ejectCooldown=0;
      this.speedBoostTimer=this.magnetTimer=this.doubleTimer=this.freezeTimer=0;
      this.playerShield=0; this.forceMergeTimer=0; this.slimePlusTimer=0;
      this.itemSpawnTimer=this.config.itemSpawnEvery;
    }

    spawnBot(){
      const r=rand(12,28);
      const name=BOT_NAMES[Math.floor(rand(0,BOT_NAMES.length))];
      this.bots.push(new Bot(rand(100,this.worldSize-100),rand(100,this.worldSize-100),r,hsl(Math.floor(rand(0,360)),75,60),name));
    }
    spawnFood(){
      const r=rand(...this.config.foodRadiusRange);
      return new Food(rand(0,this.worldSize),rand(0,this.worldSize),r,hsl(Math.floor(rand(0,360)),90,65));
    }
    spawnVirus(){
      return new Virus(rand(200,this.worldSize-200),rand(200,this.worldSize-200),this.config.virusRadius);
    }
    spawnItem(){
      const t=ITEM_TYPES[Math.floor(rand(0,ITEM_TYPES.length))];
      return new PowerUp(rand(150,this.worldSize-150),rand(150,this.worldSize-150),t);
    }

    allCells(){ return [...this.playerCells,...this.bots]; }
    playerMass(){ return this.playerCells.reduce((s,c)=>s+c.mass,0); }
    playerScore(){ return Math.round(this.playerMass()); }
    playerCenter(){
      const n=this.playerCells.length; let x=0,y=0;
      for(const c of this.playerCells){ x+=c.x; y+=c.y; }
      return {x:x/n,y:y/n};
    }

    applySoftBounds(obj,dt,isFood=false){
      const margin=120, k=isFood?0.5:1.1, restit=isFood?0.25:0.5;
      if(obj.x<obj.r+margin){ const pen=(obj.r+margin)-obj.x; obj.vx+=pen*k*dt; if(obj.x<obj.r){ obj.x=obj.r; obj.vx=Math.abs(obj.vx)*restit; } }
      if(obj.x>this.worldSize-obj.r-margin){ const pen=obj.x-(this.worldSize-obj.r-margin); obj.vx-=pen*k*dt; if(obj.x>this.worldSize-obj.r){ obj.x=this.worldSize-obj.r; obj.vx=-Math.abs(obj.vx)*restit; } }
      if(obj.y<obj.r+margin){ const pen=(obj.r+margin)-obj.y; obj.vy+=pen*k*dt; if(obj.y<obj.r){ obj.y=obj.r; obj.vy=Math.abs(obj.vy)*restit; } }
      if(obj.y>this.worldSize-obj.r-margin){ const pen=obj.y-(this.worldSize-obj.r-margin); obj.vy-=pen*k*dt; if(obj.y>this.worldSize-obj.r){ obj.y=this.worldSize-obj.r; obj.vy=-Math.abs(obj.vy)*restit; } }
      obj.x=clamp(obj.x,obj.r,this.worldSize-obj.r);
      obj.y=clamp(obj.y,obj.r,this.worldSize-obj.r);
    }

    split(){
      if(this.splitCooldown>0||this.playerCells.length>=this.config.maxPlayerCells) return;
      const dx=this.inputX-this.w/2, dy=this.inputY-this.h/2;
      const len=Math.hypot(dx,dy)||1, ux=dx/len, uy=dy/len;

      this.playerCells.sort((a,b)=>b.mass-a.mass);
      const newCells=[];
      for(const c of this.playerCells){
        if(this.playerCells.length+newCells.length>=this.config.maxPlayerCells) break;
        if(c.mass<120) continue;
        const half=c.mass*0.5; c.setMass(half);
        const nc=new PlayerCell(c.x+ux*(c.r+8),c.y+uy*(c.r+8),c.r,c.color);
        nc.setMass(half); nc.mergeCooldown=7; c.mergeCooldown=7;
        const boost=620/Math.sqrt(nc.r/16);
        nc.applyBoost(ux*boost,uy*boost,0.95);
        newCells.push(nc);
      }
      this.playerCells.push(...newCells);
      this.splitCooldown=0.7;
    }

    // 粘液喷射
    eject(){
      if(this.ejectCooldown>0) return;
      const c=this.playerCells.reduce((a,b)=>a.mass>b.mass?a:b);
      if(!c||c.mass<90) return;

      const dx=this.inputX-this.w/2, dy=this.inputY-this.h/2;
      const len=Math.hypot(dx,dy)||1, ux=dx/len, uy=dy/len;

      const plus = this.slimePlusTimer>0;
      const ejectMass = plus ? 28 : 22;
      c.addMass(-ejectMass);

      const r=Math.sqrt(ejectMass/Math.PI) * (plus ? 1.25 : 1.0);
      const speed= plus ? 820 : 700;
      const slowDuration = plus ? 4.0 : 2.5;

      const s=new SlimeBall(
        c.x+ux*(c.r+r+2), c.y+uy*(c.r+r+2),
        r, plus ? "hsl(110,80%,55%)" : "hsl(200,75%,60%)",
        ux*speed, uy*speed, slowDuration
      );
      this.foods.push(s);
      this.ejectCooldown=0.12;
    }

    forceMerge(){
      if(this.playerCells.length<=1) return;
      for(const c of this.playerCells) c.mergeCooldown=0;
      this.forceMergeTimer=2.2;
    }

    explodeCell(cell,towardMouse=false){
      const isPlayer=cell.isPlayer, totalMass=cell.mass;
      const maxPieces=isPlayer?this.config.maxPlayerCells:10;
      const pieces=clamp(Math.floor(cell.r/14),4,maxPieces);
      const baseMass=totalMass/pieces;
      const dx=this.inputX-this.w/2, dy=this.inputY-this.h/2;
      const baseAng=Math.atan2(dy,dx);
      cell.alive=false;
      const newOnes=[];
      for(let i=0;i<pieces;i++){
        const ang=towardMouse?baseAng+(i-(pieces-1)/2)*(Math.PI/10):rand(0,Math.PI*2);
        const m=baseMass, r=Math.sqrt(m/Math.PI);
        const nx=cell.x+Math.cos(ang)*(cell.r+r+4);
        const ny=cell.y+Math.sin(ang)*(cell.r+r+4);
        const nc=isPlayer?new PlayerCell(nx,ny,r,cell.color):new Bot(nx,ny,r,cell.color,cell.name);
        nc.setMass(m); nc.mergeCooldown=isPlayer?7:0;
        const boost=820/Math.sqrt(r/16);
        nc.applyBoost(Math.cos(ang)*boost,Math.sin(ang)*boost,1.05);
        newOnes.push(nc);
      }
      if(isPlayer){
        this.playerCells.push(...newOnes);
        if(this.playerCells.length>this.config.maxPlayerCells){
          this.playerCells.sort((a,b)=>b.mass-a.mass);
          this.playerCells.length=this.config.maxPlayerCells;
        }
      }else this.bots.push(...newOnes);
    }

    update(dt){
      if(!this.running||this.gameOver||this.playerCells.length===0) return;
      if(this.splitCooldown>0) this.splitCooldown-=dt;
      if(this.ejectCooldown>0) this.ejectCooldown-=dt;

      // buff timers
      if(this.speedBoostTimer>0) this.speedBoostTimer-=dt;
      if(this.magnetTimer>0) this.magnetTimer-=dt;
      if(this.doubleTimer>0) this.doubleTimer-=dt;
      if(this.freezeTimer>0) this.freezeTimer-=dt;
      if(this.forceMergeTimer>0) this.forceMergeTimer-=dt;
      if(this.slimePlusTimer>0) this.slimePlusTimer-=dt;

      for(const c of this.playerCells) c.update(dt,this);

      // 玩家分身软碰撞
      for(let i=0;i<this.playerCells.length;i++){
        for(let j=i+1;j<this.playerCells.length;j++){
          const a=this.playerCells[i], b=this.playerCells[j];
          const d=dist(a.x,a.y,b.x,b.y), min=a.r+b.r;
          if(d<min&&d>0.0001){
            const push=(min-d)/min*0.6, ux=(a.x-b.x)/d, uy=(a.y-b.y)/d;
            a.x+=ux*push*b.r; a.y+=uy*push*b.r;
            b.x-=ux*push*a.r; b.y-=uy*push*a.r;
          }
        }
      }

      for(const b of this.bots) b.update(dt,this);
      for(const f of this.foods) if(f.isEjecta) f.update(dt,this);

      this.applyMergeAttraction(dt);
      this.applyMagnet(dt);

      for(const c of this.playerCells) this.handleFoodEat(c);
      for(const b of this.bots) this.handleFoodEat(b);

      this.handleSlimeHit(); // 新玩法核心
      this.handleVirusInteractions();
      this.handleBallEat();
      this.handlePlayerMerge();

      this.updateFoodRespawn(dt);
      this.updateItems(dt);

      if(this.bots.length<this.config.botTarget){
        const addBot=Math.floor(this.config.botSpawnPerSec*dt)+1;
        for(let i=0;i<addBot;i++) this.spawnBot();
      }

      this.foods=this.foods.filter(f=>f.alive);
      this.bots=this.bots.filter(b=>b.alive);
      this.playerCells=this.playerCells.filter(c=>c.alive);
      this.viruses=this.viruses.filter(v=>v.alive);
      this.items=this.items.filter(it=>it.alive);
      while(this.viruses.length<this.config.virusCount) this.viruses.push(this.spawnVirus());

      if(this.playerCells.length===0){ this.gameOver=true; this.running=false; }
    }

    applyMergeAttraction(dt){
      if(this.playerCells.length<=1) return;
      const center=this.playerCenter();
      const forceMul=(this.forceMergeTimer>0)?3.2:1.0;
      for(const c of this.playerCells){
        if(c.mergeCooldown>0) continue;
        const dx=center.x-c.x, dy=center.y-c.y;
        const d=Math.hypot(dx,dy); if(d<1) continue;
        const pull=(d*0.8*forceMul)/(c.r+30);
        c.vx+=(dx/d*pull)*dt*60; c.vy+=(dy/d*pull)*dt*60;
        if(d<c.r*1.6){ c.vx*=Math.pow(0.55,dt); c.vy*=Math.pow(0.55,dt); }
      }
    }

    applyMagnet(dt){
      if(this.magnetTimer<=0) return;
      const center=this.playerCenter(), radius=520;
      for(const f of this.foods){
        if(!f.alive||f.isEjecta) continue;
        const d=dist(center.x,center.y,f.x,f.y);
        if(d<radius&&d>1){
          const ux=(center.x-f.x)/d, uy=(center.y-f.y)/d;
          f.x+=ux*dt*140; f.y+=uy*dt*140;
        }
      }
    }

    handleFoodEat(ball){
      for(const f of this.foods){
        if(!f.alive) continue;
        if(dist2(ball.x,ball.y,f.x,f.y)<ball.r*ball.r){
          f.alive=false;
          const gain=(this.doubleTimer>0)?f.mass*2:f.mass;
          ball.addMass(gain);
          if(!f.isEjecta) this.foodRespawnTimers.push(this.config.foodRespawnDelay);
        }
      }
    }

    // 粘液弹命中:减速 + 可被吃
    handleSlimeHit(){
      const cells=this.allCells().filter(c=>c.alive);
      for(const s of this.foods){
        if(!s.alive||!s.isSlime) continue;
        for(const c of cells){
          const d=dist(s.x,s.y,c.x,c.y);
          if(d<s.r+c.r){
            // 大球吃掉粘液弹
            if(c.r>s.r*1.15){
              s.alive=false;
              const gain=(this.doubleTimer>0)?s.mass*2:s.mass;
              c.addMass(gain);
              break;
            }else{
              // 命中减速(叠加取最大)
              c.slowTimer=Math.max(c.slowTimer,s.slowDuration);
              // 轻微冲量让命中有反馈
              const ux=(c.x-s.x)/(d||1), uy=(c.y-s.y)/(d||1);
              c.vx+=ux*40; c.vy+=uy*40;
              s.vx*=-0.35; s.vy*=-0.35;
            }
          }
        }
      }
    }

    handleVirusInteractions(){
      for(const v of this.viruses){
        for(const f of this.foods){
          if(!f.alive||!f.isEjecta) continue;
          const d=dist(v.x,v.y,f.x,f.y);
          if(d<v.r+f.r){
            f.alive=false;
            v.addMass(this.config.virusFeedGain);
            v.feedMass+=this.config.virusFeedGain;
            const sp=Math.hypot(f.vx,f.vy)||1;
            v.lastFeedDir={x:f.vx/sp,y:f.vy/sp};

            if(v.feedMass>=this.config.virusSplitThreshold){
              v.feedMass=0;
              const dir=v.lastFeedDir;
              const nv=new Virus(v.x+dir.x*(v.r*1.6),v.y+dir.y*(v.r*1.6),this.config.virusRadius);
              nv.vx=dir.x*this.config.virusShootSpeed;
              nv.vy=dir.y*this.config.virusShootSpeed;
              nv.age=0;
              v.addMass(-this.config.virusSplitThreshold*0.45);
              this.viruses.push(nv);
            }
          }
        }
      }

      for(const v of this.viruses){
        if(v.vx||v.vy){
          v.age=(v.age||0)+0.016;
          const t=clamp((v.age||0)/1.1,0,1);
          const drag=lerp(0.03,0.25,t*t);
          const factor=Math.exp(-drag*0.016*60);
          v.vx*=factor; v.vy*=factor;
          v.x+=v.vx*0.016; v.y+=v.vy*0.016;
          this.applySoftBounds(v,0.016,true);
          if(Math.hypot(v.vx,v.vy)<8){ v.vx=0; v.vy=0; }
        }
      }

      const all=this.allCells().filter(e=>e.alive);
      for(const v of this.viruses){
        for(const c of all){
          const d=dist(v.x,v.y,c.x,c.y);
          if(d<v.r+c.r*0.9 && c.r>=this.config.virusExplodeRadius){
            this.explodeCell(c,c.isPlayer);
            v.alive=false; break;
          }
        }
      }
    }

    handleBallEat(){
      const all=this.allCells().filter(e=>e.alive);
      for(let i=0;i<all.length;i++){
        const a=all[i];
        for(let j=i+1;j<all.length;j++){
          const b=all[j];
          let big=a, small=b;
          if(b.r>a.r){ big=b; small=a; }
          const d=dist(big.x,big.y,small.x,small.y);
          const normalEat=(d+small.r<=big.r*0.98 && big.r>small.r*1.05);
          const boostEat=(big.boostDuration>0 && big.r>small.r*1.05 && d<big.r);
          if(normalEat||boostEat){
            if(small.isPlayer && this.playerShield>0){
              this.playerShield=0;
              const ux=(small.x-big.x)/(d||1), uy=(small.y-big.y)/(d||1);
              small.applyBoost(ux*420,uy*420,0.6);
              continue;
            }
            small.alive=false; big.addMass(small.mass);
          }
        }
      }
    }

    handlePlayerMerge(){
      for(let i=0;i<this.playerCells.length;i++){
        for(let j=i+1;j<this.playerCells.length;j++){
          const a=this.playerCells[i], b=this.playerCells[j];
          if(a.mergeCooldown>0||b.mergeCooldown>0) continue;
          const d=dist(a.x,a.y,b.x,b.y);
          if(d<Math.max(a.r,b.r)*0.5){
            let big=a, small=b; if(b.r>a.r){ big=b; small=a; }
            small.alive=false; big.addMass(small.mass);
          }
        }
      }
    }

    updateFoodRespawn(dt){
      for(let i=0;i<this.foodRespawnTimers.length;i++) this.foodRespawnTimers[i]-=dt;
      this.foodRespawnTimers=this.foodRespawnTimers.filter(t=>{
        if(t<=0){ this.foods.push(this.spawnFood()); return false; }
        return true;
      });
    }

    updateItems(dt){
      this.itemSpawnTimer-=dt;
      if(this.itemSpawnTimer<=0){
        this.itemSpawnTimer=this.config.itemSpawnEvery*rand(0.7,1.3);
        if(this.items.length<this.config.itemMax) this.items.push(this.spawnItem());
      }
      const center=this.playerCenter();
      const pr=Math.sqrt(this.playerMass()/Math.PI);

      for(const it of this.items){
        if(!it.alive) continue;
        if(dist2(center.x,center.y,it.x,it.y)<(pr+it.r)*(pr+it.r)){
          it.alive=false;
          this.applyItem(it.type);
        }
      }
    }

    applyItem(type){
      const def=ITEM_DEFS[type];
      showToast(`获得道具:${def.name}`);

      if(type==="speed") this.speedBoostTimer=8;
      else if(type==="shield") this.playerShield=1;
      else if(type==="magnet") this.magnetTimer=10;
      else if(type==="double") this.doubleTimer=12;
      else if(type==="freeze") this.freezeTimer=10;
      else if(type==="dash"){
        const c=this.playerCells.reduce((a,b)=>a.mass>b.mass?a:b);
        const dx=this.inputX-this.w/2, dy=this.inputY-this.h/2;
        const len=Math.hypot(dx,dy)||1, ux=dx/len, uy=dy/len;
        const boost=1100/Math.sqrt(c.r/16);
        c.applyBoost(ux*boost,uy*boost,1.0);
      }
      else if(type==="splitReset"){
        this.splitCooldown=0;
        for(const c of this.playerCells) c.mergeCooldown=0;
        this.forceMergeTimer=1.6;
      }
      else if(type==="slimePlus"){
        this.slimePlusTimer=10;
      }
    }

    getCameraScale(){
      const totalR=Math.sqrt(this.playerMass()/Math.PI);
      const s=1/clamp(totalR/60,1,4.2);
      return clamp(s,0.22,1);
    }

    render(){
      const ctx=this.ctx;
      ctx.clearRect(0,0,this.w,this.h);
      if(this.playerCells.length===0){ ctx.fillStyle="#0b0f14"; ctx.fillRect(0,0,this.w,this.h); return; }

      const center=this.playerCenter(), scale=this.getCameraScale();
      ctx.save();
      ctx.translate(this.w/2,this.h/2);
      ctx.scale(scale,scale);
      ctx.translate(-center.x,-center.y);

      const viewLeft=center.x-this.w/(2*scale);
      const viewTop=center.y-this.h/(2*scale);
      const viewRight=viewLeft+this.w/scale;
      const viewBottom=viewTop+this.h/scale;

      this.drawBackground(ctx,viewLeft,viewTop,viewRight,viewBottom);

      for(const v of this.viruses) v.draw(ctx);
      for(const it of this.items) it.draw(ctx);
      for(const f of this.foods) f.draw(ctx);
      for(const b of this.bots) b.draw(ctx);
      for(const c of this.playerCells) c.draw(ctx);

      ctx.restore();
      this.drawMinimap();
    }

    drawBackground(ctx,viewLeft,viewTop,viewRight,viewBottom){
      ctx.fillStyle="#0b0f14"; ctx.fillRect(0,0,this.worldSize,this.worldSize);
      const grid=90;
      ctx.strokeStyle="rgba(255,255,255,0.04)"; ctx.lineWidth=1;
      const startX=Math.floor(viewLeft/grid)*grid;
      const startY=Math.floor(viewTop/grid)*grid;
      ctx.beginPath();
      for(let x=startX;x<=viewRight;x+=grid){ ctx.moveTo(x,viewTop); ctx.lineTo(x,viewBottom); }
      for(let y=startY;y<=viewBottom;y+=grid){ ctx.moveTo(viewLeft,y); ctx.lineTo(viewRight,y); }
      ctx.stroke();
      ctx.strokeStyle="rgba(255,255,255,0.10)"; ctx.lineWidth=6;
      ctx.strokeRect(0,0,this.worldSize,this.worldSize);
    }

    drawMinimap(){
      if(this.playerCells.length===0) return;
      const mctx=this.mctx, size=this.minimap.width;
      mctx.clearRect(0,0,size,size);
      mctx.fillStyle="rgba(0,0,0,0.4)"; mctx.fillRect(0,0,size,size);
      const scale=size/this.worldSize;

      mctx.fillStyle="rgba(255,255,255,0.2)";
      for(let i=0;i<this.foods.length;i+=30){
        const f=this.foods[i];
        mctx.fillRect(f.x*scale,f.y*scale,2,2);
      }
      for(const v of this.viruses){
        mctx.beginPath(); mctx.fillStyle="rgba(120,255,120,0.9)";
        mctx.arc(v.x*scale,v.y*scale,Math.max(2,v.r*scale),0,Math.PI*2); mctx.fill();
      }
      for(const it of this.items){
        mctx.beginPath(); mctx.fillStyle="rgba(255,255,255,0.9)";
        mctx.arc(it.x*scale,it.y*scale,3,0,Math.PI*2); mctx.fill();
      }
      for(const b of this.bots){
        mctx.beginPath(); mctx.fillStyle="rgba(255,80,80,0.9)";
        mctx.arc(b.x*scale,b.y*scale,Math.max(2,b.r*scale),0,Math.PI*2); mctx.fill();
      }
      const center=this.playerCenter();
      const pr=Math.sqrt(this.playerMass()/Math.PI);
      mctx.beginPath(); mctx.fillStyle="rgba(80,200,255,1)";
      mctx.arc(center.x*scale,center.y*scale,Math.max(3,pr*scale),0,Math.PI*2); mctx.fill();
      mctx.strokeStyle="rgba(255,255,255,0.4)"; mctx.lineWidth=2; mctx.strokeRect(0,0,size,size);
    }

    updateLeaderboard(){
      const list=[{name:"YOU",mass:this.playerMass(),isMe:true}];
      for(const b of this.bots) if(b.alive) list.push({name:b.name,mass:b.mass,isMe:false});
      list.sort((a,b)=>b.mass-a.mass);
      const top5=list.slice(0,5);
      const lbEl=document.getElementById("lbList");
      lbEl.innerHTML="";
      top5.forEach((p,idx)=>{
        const li=document.createElement("li"); li.className=p.isMe?"me":"";
        li.textContent=`${idx+1}. ${p.name} (${Math.round(p.mass)})`;
        lbEl.appendChild(li);
      });
    }

    updateUI(){
      document.getElementById("mass").textContent=Math.round(this.playerMass());
      document.getElementById("cells").textContent=this.playerCells.length;
      document.getElementById("score").textContent=this.playerScore();
      document.getElementById("bots").textContent=this.bots.length;
      document.getElementById("viruses").textContent=this.viruses.length;
      document.getElementById("foods").textContent=this.foods.filter(f=>f.alive&&!f.isEjecta).length;
      document.getElementById("items").textContent=this.items.length;

      const buffs=[];
      if(this.speedBoostTimer>0) buffs.push(`${ITEM_DEFS.speed.name} ${this.speedBoostTimer.toFixed(1)}s`);
      if(this.magnetTimer>0) buffs.push(`${ITEM_DEFS.magnet.name} ${this.magnetTimer.toFixed(1)}s`);
      if(this.doubleTimer>0) buffs.push(`${ITEM_DEFS.double.name} ${this.doubleTimer.toFixed(1)}s`);
      if(this.freezeTimer>0) buffs.push(`${ITEM_DEFS.freeze.name} ${this.freezeTimer.toFixed(1)}s`);
      if(this.slimePlusTimer>0) buffs.push(`${ITEM_DEFS.slimePlus.name} ${this.slimePlusTimer.toFixed(1)}s`);
      if(this.playerShield>0) buffs.push(`${ITEM_DEFS.shield.name} x${this.playerShield}`);
      document.getElementById("buffs").textContent=buffs.join("  ");

      this.updateLeaderboard();

      if(this.gameOver){
        hint.classList.remove("hidden");
        hint.innerHTML=`你被吃掉了 😵<br/><small>得分:${this.playerScore()} 点击"重新开始"</small>`;
      }
    }

    loop=(t)=>{
      const dt=Math.min(0.033,(t-this.lastTime)/1000);
      this.lastTime=t;
      this.update(dt);
      this.render();
      this.updateUI();
      requestAnimationFrame(this.loop);
    }
  }

  // ===== Toast =====
  const toastEl=document.getElementById("toast");
  let toastTimer=0;
  function showToast(text){
    toastEl.textContent=text;
    toastEl.classList.add("show");
    toastTimer=1.8;
  }
  function updateToast(dt){
    if(toastTimer>0){
      toastTimer-=dt;
      if(toastTimer<=0) toastEl.classList.remove("show");
    }
  }

  // ===== init =====
  const canvas=document.getElementById("c");
  const minimap=document.getElementById("minimap");
  const game=new Game(canvas,minimap);
  const hint=document.getElementById("hint");

  document.getElementById("startBtn").onclick=()=>{ hint.classList.add("hidden"); game.start(); };
  document.getElementById("restartBtn").onclick=()=>{ hint.classList.add("hidden"); game.start(); };

  let lastT=performance.now();
  function outerLoop(t){
    const dt=Math.min(0.033,(t-lastT)/1000);
    lastT=t;
    updateToast(dt);
    requestAnimationFrame(outerLoop);
  }
  requestAnimationFrame(outerLoop);
  requestAnimationFrame(game.loop);
})();
</script>
</body>
</html>

在线体验

复制代码
https://qiu.zhangsan.shop

GPt5.1/Gemini3pro/Grok4.1/香蕉2模型等,使用网站:

复制代码
https://share.zhangsan.cool
https://share-hk.zhangsan.cool
https://share.searchknowledge.cloud
https://hello.aiforme.cloud

AI群:967915168

相关推荐
nunca_te_rindas13 小时前
Gemini初体验
ai·chatgpt·gemini·deepseek
shandianchengzi14 小时前
【记录】Github|Github账号意外被封以及不需要手机号解封的全过程(被封原因:一台设备上登录过多个账号)
github·gemini
Pocker_Spades_A15 小时前
AiOnly平台大模型API实战:一键调用GPT-5搭建个人专属文本摘要工具
gpt
魁首1 天前
Gemini CLI 深度源码:从零到一理解 AI 命令行代理的设计与实现
ai编程·gemini·mcp
Sherlock Ma1 天前
OpenAI新论文!GPT-5-Thinking新训练方法
人工智能·gpt·深度学习·语言模型·自然语言处理·chatgpt·openai
热爱生活的五柒2 天前
gpt上面的内容复制到word后格式会乱怎么办?
gpt
qq19226382 天前
分布式光伏发电系统并网运行的Matlab仿真研究
gpt
Niuguangshuo2 天前
从 One-Hot 到 GPT:语言模型的演进之路
人工智能·gpt·语言模型
询问QQ:180809512 天前
复现ICRA 2022自动驾驶实时轨迹规划:速度路径解耦方法研究,基于Linux系统ROS的场...
gpt