同一个指令,GPT 5.5 和 Claude Opus 4.7 的代码差距居然这么大?发表时间:2026-05-09 18:00 两周前 Open AI 正式上线 GPT 5.5。 Claude Opus 4.7 还没坐稳宝座,就被 GPT 5.5 赶下去。4.7好不好用呢?我们可以看看以往的文章。 目前 Nebula Lab 已上线 GPT 5.5,欢迎大家前来测试使用。 ![]() 那么 GPT 5.5 的效果如何呢?官方说: A new class of intelligence for real work and powering agents, built to understand complex goals, use tools, check its work, and carry more tasks through to completion. It marks a new way of getting computer work done. 即,一款面向真实工作、赋能智能代理的全新智能模型,专为理解复杂目标、调用工具、自主核验工作成果而设计,可将更多任务全程执行直至完成。 它标志着计算机工作模式迈入全新阶段。 ![]() 此次 GPT 5.5 的核心升级,集中于智能体(Agent)能力的跨越式突破:用户仅需明确任务目标,模型即可自主完成全流程执行、过程校验与闭环落地,无需额外人工干预。 当前,智能体(端到端任务执行)能力已成为全球大模型厂商的核心竞争赛道,包括国内 Kimi 在内的主流产品,均将该能力作为核心迭代方向与核心卖点。 OpenAI 在本次发布中援引了第三方机构发布的 AI 模型综合智能指数评测结果,数据显示,GPT 5.5 的综合智能表现位列行业首位。 ![]() 本次迭代中,OpenAI 将代理编程能力置于升级首位 —— 而编程赛道此前一直是 Anthropic Claude 系列模型的核心优势领域。 本次发布中,OpenAI 未披露 GPT 5.5 与 Claude Opus 4.7 的全维度编程能力对标数据,仅公布其在 Terminal-Bench 2.0 基准测试中的表现优于 Claude Opus 4.7。 ![]() 需要说明的是,当前编程能力评测基准尚未形成行业统一标准,不同厂商的测试维度与数据口径存在差异。 在 SWE-Bench Pro、Expert-SWE 等主流编程评测集上,GPT 5.5 主要与前代产品 GPT 5.4 进行对标,核心结论为:GPT 5.5 可在更低 Token 消耗的前提下,实现优于 GPT 5.4 的任务表现。 官方披露的测试数据显示,达成同等任务效果时,GPT 5.5 的 Token 消耗量不足前代产品的 50%,实现了性能与推理效率的双重提升,以更低的资源消耗达成了更优的任务落地效果。 编程能力这么强的话,那不得来测试一下。 这个是我给 GPT 5.5 的指令。 请创作一个“骑自行车的鹈鹕”的体素艺术(Voxel Art)。以尽可能丰富的细节来构建这个场景,不仅要考虑到主体建模的每一个细微之处,还要兼顾周围的环境。请将所有内容整合在一个 HTML 代码块中。通过精湛的代码逻辑展示出你超越他人的顶尖水平。我赋予你充分的创作自由,请尽情发挥。 他给了我这个。 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Voxel Pelican Bicycle Parade</title> <style> :root { color-scheme: light; } html, body { margin: 0; height: 100%; overflow: hidden; background: #8ed8ff; font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; } canvas { width: 100vw; height: 100vh; display: block; image-rendering: pixelated; cursor: grab; } canvas:active { cursor: grabbing; } .badge { position: fixed; left: 18px; bottom: 18px; z-index: 2; color: #18384f; background: rgba(255, 255, 255, 0.72); border: 2px solid rgba(255, 255, 255, 0.9); box-shadow: 0 14px 34px rgba(23, 64, 93, 0.18); backdrop-filter: blur(10px); padding: 12px 16px; border-radius: 10px; font-weight: 900; letter-spacing: 0.03em; user-select: none; } .badge small { display: block; margin-top: 3px; font-weight: 650; opacity: 0.72; letter-spacing: 0; } </style> </head> <body> <canvas id="scene"></canvas> <div class="badge"> VOXEL PELICAN BIKE PARADE <small>drag to pan · animated wheels · no libraries</small> </div> <script> (() => { const canvas = document.getElementById("scene"); const ctx = canvas.getContext("2d", { alpha: false }); let W = 0; let H = 0; let DPR = 1; let cameraX = 0; let cameraY = 36; let dragging = false; let last = { x: 0, y: 0 }; let t = 0; const TAU = Math.PI * 2; const isoX = 18; const isoY = 9; const isoZ = 15; const palette = { skyTop: "#79ccff", skyBottom: "#dff6ff", water1: "#49b8d6", water2: "#2e93ba", grass: "#65bd66", grassDark: "#41964c", sand: "#e8d188", board: "#b98555", boardDark: "#8a5c3c", white: "#fffaf0", whiteShade: "#e6e6dc", cream: "#f7eccb", orange: "#f08324", orangeDark: "#c85f16", pouch: "#f7bf63", pouchDark: "#dc9341", black: "#152331", red: "#e65344", blue: "#3c82e6", teal: "#22a8a7", metal: "#5b6872", metalHi: "#cad6de", tire: "#1d2a31", rubberHi: "#40515b", yellow: "#ffd04a" }; function resize() { DPR = Math.min(2, window.devicePixelRatio || 1); W = Math.floor(innerWidth * DPR); H = Math.floor(innerHeight * DPR); canvas.width = W; canvas.height = H; ctx.setTransform(DPR, 0, 0, DPR, 0, 0); W = innerWidth; H = innerHeight; } addEventListener("resize", resize); resize(); canvas.addEventListener("pointerdown", e => { dragging = true; last.x = e.clientX; last.y = e.clientY; canvas.setPointerCapture(e.pointerId); }); canvas.addEventListener("pointermove", e => { if (!dragging) return; cameraX += e.clientX - last.x; cameraY += e.clientY - last.y; last.x = e.clientX; last.y = e.clientY; }); canvas.addEventListener("pointerup", () => dragging = false); canvas.addEventListener("pointercancel", () => dragging = false); function shade(hex, amt) { const n = parseInt(hex.slice(1), 16); let r = (n >> 16) + amt; let g = ((n >> 8) & 255) + amt; let b = (n & 255) + amt; r = Math.max(0, Math.min(255, r)); g = Math.max(0, Math.min(255, g)); b = Math.max(0, Math.min(255, b)); return "#" + (b | (g << 8) | (r << 16)).toString(16).padStart(6, "0"); } function iso(x, y, z) { return { x: W * 0.5 + cameraX + (x - y) * isoX, y: H * 0.58 + cameraY + (x + y) * isoY - z * isoZ }; } function poly(points, fill, stroke = "rgba(30,45,55,0.22)", width = 1) { ctx.beginPath(); ctx.moveTo(points[0].x, points[0].y); for (let i = 1; i < points.length; i++) ctx.lineTo(points[i].x, points[i].y); ctx.closePath(); ctx.fillStyle = fill; ctx.fill(); if (stroke) { ctx.lineWidth = width; ctx.strokeStyle = stroke; ctx.stroke(); } } function cube(x, y, z, w, d, h, color, stroke) { const A = iso(x, y, z + h); const B = iso(x + w, y, z + h); const C = iso(x + w, y + d, z + h); const D = iso(x, y + d, z + h); const E = iso(x, y, z); const F = iso(x + w, y, z); const G = iso(x + w, y + d, z); const Hh = iso(x, y + d, z); poly([A, B, C, D], shade(color, 18), stroke); poly([B, F, G, C], shade(color, -26), stroke); poly([D, C, G, Hh], shade(color, -42), stroke); } function rect2(cx, cy, w, h, color, rot = 0, stroke = "rgba(0,0,0,0.22)") { ctx.save(); ctx.translate(cx, cy); ctx.rotate(rot); ctx.fillStyle = color; ctx.strokeStyle = stroke; ctx.lineWidth = 2; ctx.fillRect(-w / 2, -h / 2, w, h); ctx.strokeRect(-w / 2, -h / 2, w, h); ctx.restore(); } function line(a, b, color, width = 5) { ctx.beginPath(); ctx.moveTo(a.x, a.y); ctx.lineTo(b.x, b.y); ctx.lineCap = "square"; ctx.lineWidth = width; ctx.strokeStyle = color; ctx.stroke(); } function circleBlock(cx, cy, r, count, size, color, phase = 0) { for (let i = 0; i < count; i++) { const a = i / count * TAU + phase; rect2(cx + Math.cos(a) * r, cy + Math.sin(a) * r, size, size, color, a); } } function background() { const g = ctx.createLinearGradient(0, 0, 0, H); g.addColorStop(0, palette.skyTop); g.addColorStop(0.58, palette.skyBottom); g.addColorStop(1, "#fff4d3"); ctx.fillStyle = g; ctx.fillRect(0, 0, W, H); ctx.fillStyle = "#ffe78b"; ctx.beginPath(); ctx.arc(W - 122, 102, 46, 0, TAU); ctx.fill(); for (let i = 0; i < 7; i++) { const x = (i * 250 + (t * 9) % 250) - 130; const y = 68 + (i % 3) * 38; cloud(x, y, 1 + (i % 2) * 0.24); } ctx.fillStyle = "#b7e8f8"; for (let i = 0; i < 4; i++) { const y = H * 0.42 + i * 22; ctx.fillRect(0, y, W, 2); } } function cloud(x, y, s) { ctx.fillStyle = "rgba(255,255,255,0.82)"; const blocks = [ [0, 12, 58, 22], [34, 0, 72, 34], [90, 13, 62, 24], [25, 28, 110, 18], [118, 28, 34, 18] ]; for (const b of blocks) ctx.fillRect(x + b[0] * s, y + b[1] * s, b[2] * s, b[3] * s); } function waterAndLand() { const waterY = H * 0.48 + cameraY * 0.08; ctx.fillStyle = palette.water1; ctx.fillRect(0, waterY, W, H - waterY); for (let i = 0; i < 26; i++) { const y = waterY + 18 + i * 18; ctx.fillStyle = i % 2 ? "rgba(255,255,255,0.15)" : "rgba(35,105,140,0.16)"; const shift = (Math.sin(t * 1.2 + i) * 18); for (let x = -80; x < W + 80; x += 115) { ctx.fillRect(x + shift, y, 54, 4); } } for (let x = -12; x < 36; x += 4) { for (let y = -18; y < 22; y += 4) cube(x, y, -1, 4, 4, 1, palette.sand, null); } for (let x = -14; x < 38; x += 4) { cube(x, -22, 0, 4, 5, 2, palette.grass, null); if (x % 8 === 0) cube(x + 1, -24, 2, 1, 1, 4, palette.grassDark, null); } for (let x = -16; x < 40; x += 4) { cube(x, 21, 0, 4, 4, 2, palette.grass, null); if (x % 12 === 0) cube(x + 2, 24, 2, 1, 1, 5, "#5aa24c", null); } for (let x = -18; x < 42; x += 5) { cube(x, -3, 0, 5, 26, 1.2, palette.board, "rgba(79,54,37,0.28)"); cube(x, -3.2, 1.2, 0.3, 26.4, 0.35, palette.boardDark, null); } for (let y = -1; y < 22; y += 7) { cube(-19, y, 0, 62, 1.2, 1.5, palette.boardDark, null); } for (let x = -18; x < 44; x += 12) { cube(x, -5, 0, 1.4, 1.4, 7, "#7a4b2e", null); cube(x, 23, 0, 1.4, 1.4, 7, "#7a4b2e", null); cube(x - 0.4, -5.4, 7, 2.2, 2.2, 0.8, "#d3a16a", null); cube(x - 0.4, 22.6, 7, 2.2, 2.2, 0.8, "#d3a16a", null); } for (let x = -17; x < 40; x += 3) cube(x, -5, 6.5, 2, 1, 1, "#e5c399", null); for (let x = -17; x < 40; x += 3) cube(x, 23, 6.5, 2, 1, 1, "#e5c399", null); } function lighthouseAndShops() { cube(27, -19, 0, 4, 4, 15, "#f5f0dd", null); cube(27, -19, 15, 4, 4, 3, palette.red, null); cube(26.5, -19.5, 18, 5, 5, 1.2, palette.black, null); cube(28, -20, 19, 2, 6, 2, "#ffd759", null); cube(26.4, -20.2, 21, 5.2, 5.2, 1.2, palette.red, null); cube(-19, -20, 0, 8, 6, 5, "#ffdf9b", null); cube(-20, -21, 5, 10, 8, 2, "#de5144", null); cube(-17, -19, 1, 2, 1, 2, "#4fa8d9", null); cube(-13.8, -19, 0, 2, 1, 3, "#825a3e", null); cube(-7, -21, 0, 7, 7, 5, "#c7e7c4", null); cube(-8, -22, 5, 9, 9, 2, "#348f7c", null); cube(-5.5, -20, 1, 2, 1, 2, "#f7f7ff", null); cube(-2, -20, 1, 1.8, 1, 2, "#f7f7ff", null); for (let i = 0; i < 7; i++) { const x = -16 + i * 5; cube(x, -9, 0, 1, 1, 4 + (i % 2), "#2e9c57", null); cube(x - 0.8, -9.8, 4 + (i % 2), 2.6, 2.6, 1.6, i % 2 ? "#fb6f92" : "#ffd166", null); } } function drawBike() { const bounce = Math.sin(t * 4) * 2; const base = iso(9, 8, 6); const bx = base.x; const by = base.y + bounce; const rot = -t * 3.6; const rear = { x: bx - 126, y: by + 74 }; const front = { x: bx + 118, y: by + 74 }; const crank = { x: bx - 10, y: by + 52 }; const seat = { x: bx - 52, y: by - 14 }; const handle = { x: bx + 88, y: by - 24 }; const forkTop = { x: bx + 70, y: by + 10 }; ctx.lineCap = "square"; circleBlock(rear.x, rear.y, 45, 46, 8, palette.tire, rot); circleBlock(front.x, front.y, 45, 46, 8, palette.tire, rot); circleBlock(rear.x, rear.y, 32, 24, 4, palette.rubberHi, -rot * 1.4); circleBlock(front.x, front.y, 32, 24, 4, palette.rubberHi, -rot * 1.4); for (let i = 0; i < 12; i++) { const a = i / 12 * TAU + rot; line(rear, { x: rear.x + Math.cos(a) * 39, y: rear.y + Math.sin(a) * 39 }, palette.metalHi, 2); line(front, { x: front.x + Math.cos(a) * 39, y: front.y + Math.sin(a) * 39 }, palette.metalHi, 2); } rect2(rear.x, rear.y, 15, 15, palette.metal); rect2(front.x, front.y, 15, 15, palette.metal); line(rear, crank, palette.teal, 8); line(crank, front, palette.teal, 8); line(rear, seat, palette.teal, 8); line(seat, handle, palette.teal, 8); line(crank, seat, palette.teal, 8); line(front, forkTop, palette.teal, 8); line(forkTop, handle, palette.teal, 8); line({ x: bx - 82, y: by + 30 }, { x: bx - 118, y: by + 22 }, "#263843", 4); line({ x: bx + 92, y: by - 24 }, { x: bx + 130, y: by - 34 }, "#263843", 4); rect2(bx - 52, by - 23, 54, 12, "#422f29", -0.04); rect2(bx + 130, by - 36, 34, 8, "#263843", -0.05); circleBlock(crank.x, crank.y, 16, 14, 5, palette.yellow, rot * 1.7); rect2(crank.x + Math.cos(rot * 1.7) * 26, crank.y + Math.sin(rot * 1.7) * 26, 34, 7, palette.orange, rot * 1.7); rect2(crank.x + Math.cos(rot * 1.7 + Math.PI) * 26, crank.y + Math.sin(rot * 1.7 + Math.PI) * 26, 34, 7, palette.orange, rot * 1.7 + Math.PI); const basket = { x: bx + 138, y: by - 3 }; rect2(basket.x, basket.y, 52, 36, "#b77a44", 0.05); for (let i = -2; i <= 2; i++) rect2(basket.x + i * 10, basket.y, 2, 36, "#815231", 0.05); for (let i = -1; i <= 1; i++) rect2(basket.x, basket.y + i * 10, 52, 2, "#815231", 0.05); rect2(basket.x - 12, basket.y - 27, 12, 20, "#ff5f7d", -0.4); rect2(basket.x + 8, basket.y - 28, 13, 19, "#ffd166", 0.35); rect2(basket.x + 24, basket.y - 21, 10, 16, "#6ed06e", 0.1); } function drawPelican() { const bob = Math.sin(t * 4) * 2; const base = iso(8, 8, 12); const x = base.x - 7; const y = base.y - 88 + bob; const block = (dx, dy, w, h, color, rot = 0) => rect2(x + dx, y + dy, w, h, color, rot); block(-68, 38, 116, 72, palette.white); block(-56, 25, 86, 34, palette.whiteShade); block(-86, 46, 38, 56, palette.whiteShade, -0.18); block(-101, 58, 22, 48, "#d9ded7", -0.28); block(4, 72, 43, 23, "#d8d8cf", 0.12); block(7, -4, 62, 57, palette.white); block(30, -39, 68, 55, palette.white); block(66, -49, 32, 29, palette.whiteShade); block(79, -31, 106, 23, palette.orange, 0.02); block(83, -7, 86, 36, palette.pouch, 0.04); block(154, -32, 44, 20, palette.orangeDark, 0.02); block(164, -5, 24, 18, palette.pouchDark, 0.05); block(58, -22, 8, 8, palette.black); block(61, -24, 3, 3, "#ffffff"); block(23, -60, 16, 22, palette.whiteShade, -0.16); block(38, -67, 14, 20, palette.white, 0.1); block(51, -63, 12, 18, palette.whiteShade, 0.25); block(-35, -4, 40, 34, "#f3f0e3", -0.2); block(-48, 4, 18, 18, "#d1d5ce", -0.2); block(-52, 73, 16, 64, palette.orangeDark, 0.25); block(14, 79, 16, 60, palette.orangeDark, -0.22); const pedalA = t * 6; block(-58 + Math.cos(pedalA) * 14, 126 + Math.sin(pedalA) * 14, 34, 11, palette.orange, pedalA * 0.3); block(10 + Math.cos(pedalA + Math.PI) * 14, 126 + Math.sin(pedalA + Math.PI) * 14, 34, 11, palette.orange, -pedalA * 0.3); block(-15, -19, 22, 13, "#4ec5da", 0.08); block(7, -20, 19, 13, "#ffcf57", 0.08); block(29, -19, 22, 13, "#ff6b60", 0.08); block(-20, -24, 58, 4, "#263843", 0.08); for (let i = 0; i < 9; i++) { block(-74 + i * 14, 31 + Math.sin(i + t * 2) * 2, 8, 7, "#f5f4e7"); } for (let i = 0; i < 5; i++) { block(100 + i * 13, -16 + (i % 2) * 4, 7, 5, "#ffd99b"); } } function details() { for (let i = 0; i < 18; i++) { const x = -17 + (i * 3.2); const y = i % 2 ? 20 : -2; cube(x, y, 1.4, 0.8, 0.8, 1.2, i % 3 ? "#f4eee0" : "#d1ebef", null); } for (let i = 0; i < 16; i++) { const x = -14 + i * 3.5; const h = 2 + (i % 4); cube(x, 26 + (i % 3), 0, 0.7, 0.7, h, "#3f8f52", null); cube(x - 0.4, 26.4 + (i % 3), h, 1.5, 0.7, 0.7, i % 2 ? "#ffe66d" : "#ff7a7a", null); } for (let i = 0; i < 8; i++) { const p = iso(-14 + i * 7, 31, 1); const swim = Math.sin(t * 2 + i) * 4; ctx.fillStyle = i % 2 ? "#f6b645" : "#66d0d3"; ctx.fillRect(p.x - 8, p.y + swim, 20, 7); ctx.fillRect(p.x + 10, p.y + swim + 2, 6, 3); } const bannerA = iso(-12, -7, 9); const bannerB = iso(34, -7, 9); line(bannerA, bannerB, "#f8f4d2", 3); for (let i = 0; i < 12; i++) { const u = i / 11; const x = bannerA.x * (1 - u) + bannerB.x * u; const y = bannerA.y * (1 - u) + bannerB.y * u + Math.sin(t * 3 + i) * 2; rect2(x, y + 9, 11, 15, ["#f94144", "#f9c74f", "#43aa8b", "#577590"][i % 4], 0.03); } } function drawShadow() { const p = iso(8, 8, 1.4); ctx.fillStyle = "rgba(33, 52, 47, 0.18)"; ctx.beginPath(); ctx.ellipse(p.x, p.y + 73, 188, 42, -0.01, 0, TAU); ctx.fill(); } function drawScene() { background(); waterAndLand(); lighthouseAndShops(); details(); drawShadow(); drawBike(); drawPelican(); ctx.fillStyle = "rgba(255,255,255,0.18)"; for (let i = 0; i < 80; i++) { const x = (i * 97 + t * 14) % (W + 160) - 80; const y = H * 0.52 + ((i * 53) % Math.max(1, H * 0.42)); const w = 12 + (i % 4) * 8; ctx.fillRect(x, y, w, 2); } } function animate(now) { t = now / 1000; drawScene(); requestAnimationFrame(animate); } requestAnimationFrame(animate); })(); </script> </body> </html> 我们运行一下,可以运行。 ![]() 然后我以同样的问题,又去问了 Claude Opus 4.7,得到这个代码。 <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <title>骑自行车的鹈鹕 · Voxel Art</title> <style> *{margin:0;padding:0;box-sizing:border-box} body{background:#1a1a2e;display:flex;align-items:center;justify-content:center;min-height:100vh;overflow:hidden} canvas{display:block;image-rendering:pixelated;image-rendering:crisp-edges} #info{position:fixed;bottom:16px;left:16px;color:#fff;font:700 13px/1.6 system-ui; background:rgba(0,0,0,.45);padding:10px 14px;border-radius:12px;backdrop-filter:blur(6px);pointer-events:none} </style> </head> <body> <canvas id="c"></canvas> <div id="info"> 骑自行车的鹈鹕 · Voxel Art<br><small>纯 Canvas · 无依赖 · 实时动画</small></div> <script> (function(){ "use strict"; /* ─────────────── 画布初始化 ─────────────── */ const canvas = document.getElementById("c"); const ctx = canvas.getContext("2d"); const W = 900, H = 620; canvas.width = W; canvas.height = H; canvas.style.width = W + "px"; canvas.style.height = H + "px"; /* ─────────────── 体素绘制核心 ─────────────── */ const ISO_X = 0.70; // isometric tilt const ISO_Y = 0.35; /* 将体素坐标 (gx,gy,gz) 转成屏幕 2D */ function toScreen(gx, gy, gz){ return { x: W/2 + (gx - gy) * ISO_X * gz * 0 + (gx - gy) * 14, y: H/2 - gz * 14 + (gx + gy) * 7 }; } /* 画一个单体素(面向正面朝左的等轴视角) */ function vox(gx, gy, gz, col){ const S = 14; // voxel base size px const ox = 14 * ISO_X; // offset x for depth const oy = 14 * ISO_Y; // offset y for depth const px = W/2 + (gx - gy) * S; const py = H/2 - gz * S + (gx + gy) * (S * 0.5); // top face ctx.fillStyle = lighten(col, 40); ctx.beginPath(); ctx.moveTo(px, py); ctx.lineTo(px + S, py); ctx.lineTo(px + S + ox, py - oy); ctx.lineTo(px + ox, py - oy); ctx.closePath(); ctx.fill(); // right face ctx.fillStyle = darken(col, 30); ctx.beginPath(); ctx.moveTo(px + S, py); ctx.lineTo(px + S, py + S); ctx.lineTo(px + S + ox, py + S - oy); ctx.lineTo(px + S + ox, py - oy); ctx.closePath(); ctx.fill(); // front face ctx.fillStyle = col; ctx.beginPath(); ctx.moveTo(px, py); ctx.lineTo(px, py + S); ctx.lineTo(px + S, py + S); ctx.lineTo(px + S, py); ctx.closePath(); ctx.fill(); // outline ctx.strokeStyle = "rgba(0,0,0,0.18)"; ctx.lineWidth = 0.5; ctx.strokeRect(px, py, S, S); } /* 颜色工具 */ function lighten(hex, n){ return shiftColor(hex, n); } function darken(hex, n){ return shiftColor(hex, -n); } function shiftColor(hex, n){ let r = parseInt(hex.slice(1,3),16); let g = parseInt(hex.slice(3,5),16); let b = parseInt(hex.slice(5,7),16); r = Math.max(0,Math.min(255,r+n)); g = Math.max(0,Math.min(255,g+n)); b = Math.max(0,Math.min(255,b+n)); return `rgb(${r},${g},${b})`; } /* ─────────────── 批量绘制工具 ─────────────── */ /* 用 ASCII 图定义层,逐层堆叠 */ function drawLayer(map, z, palette, ox=0, oy=0){ for(let r=0;r<map.length;r++){ for(let c=0;c<map[r].length;c++){ const ch = map[r][c]; if(ch !== "." && palette[ch]){ vox(ox+c, oy+r, z, palette[ch]); } } } } /* ─────────────── 场景物件 ─────────────── */ /* 天空背景 */ function drawSky(){ const g = ctx.createLinearGradient(0,0,0,H); g.addColorStop(0,"#1a1a6e"); g.addColorStop(0.35,"#2255bb"); g.addColorStop(0.72,"#59b8e8"); g.addColorStop(1,"#a8e8ff"); ctx.fillStyle = g; ctx.fillRect(0,0,W,H); } /* 太阳 */ function drawSun(){ const sx = W*0.82, sy = H*0.14; const g = ctx.createRadialGradient(sx,sy,4,sx,sy,52); g.addColorStop(0,"#fff7a0"); g.addColorStop(0.45,"#ffd84d"); g.addColorStop(1,"rgba(255,200,50,0)"); ctx.fillStyle = g; ctx.beginPath(); ctx.arc(sx,sy,52,0,Math.PI*2); ctx.fill(); // pixel sun core for(let r=-2;r<=2;r++) for(let c=-2;c<=2;c++) if(r*r+c*c<6) ctx.fillStyle="#fffcd0", ctx.fillRect(sx+c*8-4,sy+r*8-4,8,8); } /* 云朵(像素块) */ function drawCloud(sx,sy,scale){ const s = scale*7; const m = [ "..WW....", ".WWWW...", "WWWWWWW.", ".WWWWWW.", "..WWWW.." ]; for(let r=0;r<m.length;r++) for(let c=0;c<m[r].length;c++) if(m[r][c]==="W"){ ctx.fillStyle = r<2 ? "#ffffff" : "#e8f4ff"; ctx.fillRect(sx+c*s, sy+r*s, s-1, s-1); } } /* 地面(绿地+道路+海边) */ function drawGround(){ // 草地 const g = ctx.createLinearGradient(0,H*0.62,0,H); g.addColorStop(0,"#4caf6a"); g.addColorStop(1,"#2e7d46"); ctx.fillStyle = g; ctx.fillRect(0, H*0.62, W, H); // 路面 ctx.fillStyle = "#6e7080"; ctx.fillRect(0, H*0.62, W, H*0.18); // 路线 ctx.fillStyle = "#ffffff"; for(let x=0;x<W;x+=90){ ctx.fillRect(x, H*0.70, 55, 5); } // 路边石 ctx.fillStyle = "#bcbcbc"; ctx.fillRect(0,H*0.615,W,6); ctx.fillRect(0,H*0.795,W,6); // 海 (远景) const sea = ctx.createLinearGradient(0,H*0.50,0,H*0.62); sea.addColorStop(0,"#1a7bbf"); sea.addColorStop(1,"#1e96d8"); ctx.fillStyle = sea; ctx.fillRect(0,H*0.50,W,H*0.12); // 海浪像素 ctx.fillStyle = "rgba(255,255,255,0.25)"; for(let i=0;i<12;i++){ ctx.fillRect(i*80, H*0.54, 40, 3); ctx.fillRect(i*80+30, H*0.58, 30, 2); } } /* 树(体素) */ function drawTree(gx,gy){ const trunk = "#7a4520"; const leafA = "#2d9e52"; const leafB = "#3dbb66"; const leafC = "#23813e"; // 树干 for(let z=0;z<5;z++) vox(gx,gy,z,trunk); // 树冠层1 const c1=[ "..LLL..", ".LLLLL.", "LLLLLLL", ".LLLLL.", "..LLL.." ]; drawLayer(c1,5,{L:leafA},gx-3,gy-2); drawLayer(c1,6,{L:leafB},gx-2,gy-2); drawLayer(c1,7,{L:leafC},gx-2,gy-2); // 顶部 const c2=[ ".LL.", "LLLL", ".LL." ]; drawLayer(c2,8,{L:leafA},gx-1,gy-1); drawLayer(c2,9,{L:leafB},gx-1,gy-1); } /* 路灯(体素) */ function drawLamp(gx,gy){ for(let z=0;z<9;z++) vox(gx,gy,z,"#888899"); vox(gx,gy,9,"#aaaacc"); vox(gx+1,gy,9,"#aaaacc"); vox(gx+1,gy,8,"#888899"); vox(gx,gy,10,"#ffee88"); vox(gx+1,gy,10,"#ffe066"); } /* 自行车 */ function drawBicycle(bx, by, wheelRot){ const METAL = "#c0c8d8"; const DARK = "#3a3f55"; const RED = "#e84040"; const CHROME = "#e8eef8"; // 后轮 drawWheel(bx-4, by, 3, wheelRot, DARK, CHROME, "#ffaa22"); // 前轮 drawWheel(bx+5, by, 3, wheelRot, DARK, CHROME, "#ffaa22"); // 车架(简化为体素杆) // 座管(竖直) for(let z=0;z<=4;z++) vox(bx-2,by,z+3,METAL); // 上管(横) for(let i=0;i<=6;i++) vox(bx-2+i,by,7,RED); // 下管(斜) vox(bx-2,by,7,METAL); vox(bx-1,by,5,METAL); vox(bx,by,4,METAL); vox(bx+1,by,4,METAL); vox(bx+2,by,4,METAL); vox(bx+3,by,3,METAL); // 立管(前) for(let z=3;z<=7;z++) vox(bx+4,by,z,METAL); // 后叉 vox(bx-3,by,3,METAL); vox(bx-4,by,3,METAL); // 前叉 vox(bx+5,by,3,METAL); vox(bx+5,by,4,METAL); // 车把 vox(bx+4,by,8,CHROME); vox(bx+5,by,8,CHROME); vox(bx+4,by-1,8,CHROME); vox(bx+4,by+1,8,CHROME); // 车座 for(let i=-1;i<=1;i++) vox(bx-2+i,by,8,"#2a2a3a"); vox(bx-3,by,8,"#2a2a3a"); // 踏板(动画) const pr = 1.6; const pax = bx + Math.round(Math.cos(wheelRot)*pr); const paz = 5 + Math.round(Math.sin(wheelRot)*pr); const pbx = bx + Math.round(Math.cos(wheelRot+Math.PI)*pr); const pbz = 5 + Math.round(Math.sin(wheelRot+Math.PI)*pr); vox(pax,by,paz,"#ffcc44"); vox(pbx,by,pbz,"#ffcc44"); // 链条(简单装饰) for(let i=0;i<=3;i++) vox(bx-2+i,by,3,"#888888"); // 车铃 vox(bx+4,by,9,"#ffd700"); // 车篮(前) for(let z=7;z<=9;z++){ vox(bx+5,by-1,z,"#c8a060"); vox(bx+5,by+1,z,"#c8a060"); } vox(bx+5,by-1,9,"#c8a060"); vox(bx+5,by,9,"#c8a060"); vox(bx+5,by+1,9,"#c8a060"); vox(bx+6,by-1,8,"#c8a060"); vox(bx+6,by+1,8,"#c8a060"); vox(bx+6,by-1,9,"#e8c080"); vox(bx+6,by,9,"#e8c080"); vox(bx+6,by+1,9,"#e8c080"); // 车篮里的鱼 vox(bx+6,by,10,"#ff8844"); vox(bx+5,by,10,"#ffaa66"); } /* 车轮(体素圆环) */ function drawWheel(wx, wy, r, rot, tireCol, rimCol, hubCol){ const pts = 20; for(let i=0;i<pts;i++){ const a = i*Math.PI*2/pts; const gx = wx + Math.round(Math.cos(a)*r); const gz = wy + Math.round(Math.sin(a)*r); vox(gx, 0, gz, tireCol); } // 轮辐 for(let i=0;i<6;i++){ const a = rot + i*Math.PI/3; for(let d=0;d<r;d++){ const t = d/r; const gx = wx + Math.round(Math.cos(a)*d); const gz = wy + Math.round(Math.sin(a)*d); vox(gx, 0, gz, t<0.3?hubCol:rimCol); } } // 轮毂 vox(wx,0,wy,hubCol); vox(wx,0,wy+1,hubCol); } /* ─────────────── 鹈鹕 ─────────────── */ function drawPelican(px, py, t){ /* 颜色 */ const W_COL = "#f5f5f5"; // 白色羽毛 const GRAY = "#c8d0dc"; // 翅膀深色 const ORANGE = "#ff8822"; // 喙 const PINK = "#ffaaaa"; // 喉囊 const EYE = "#1a1a2e"; const PUPIL = "#ffffff"; const LEG = "#e8a040"; const FOOT = "#d08030"; const BEAK_D = "#cc6611"; const BELLY = "#fffaf0"; const WING_A = "#e8ecf0"; const WING_B = "#b0bac8"; const bz = py; // base Z /* 身体(蛋形,多层) */ // 层0 腹部底 const body0=[ "..BBB..", ".BBBBB.", ".BBBBB.", "..BBB.." ]; drawLayer(body0,bz+4,{B:BELLY},px-1,0-1); // 层1-4 身体主体 const body1=[ "..WWW..", ".WWWWW.", "WWWWWWW", ".WWWWW.", "..WWW.." ]; for(let z=bz+5;z<=bz+8;z++) drawLayer(body1,z,{W:W_COL},px-3,0-2); // 层5-6 身体上部(收窄) const body2=[ ".WWWW.", "WWWWWW", ".WWWW." ]; drawLayer(body2,bz+9, {W:W_COL},px-2,0-1); drawLayer(body2,bz+10,{W:W_COL},px-2,0-1); /* 翅膀(左=前,右=后,带扑翼动画) */ const wFlap = Math.sin(t*0.04)*2; const wOff = Math.round(wFlap); // 左翅 const wingL=[ "...AAAA", "..AAAAA", ".AAAAAA", "..BBBB.", "...BB.." ]; for(let z=bz+6;z<=bz+9;z++) drawLayer(wingL,z+wOff,{A:WING_A,B:WING_B},px-7,0-2); // 右翅 const wingR=[ "AAAA...", "AAAAA..", "AAAAAA.", ".BBBB..", "..BB..." ]; for(let z=bz+6;z<=bz+9;z++) drawLayer(wingR,z-wOff,{A:WING_A,B:WING_B},px+2,0-2); /* 颈部 */ const neck=[ ".NN.", "NNNN", ".NN." ]; drawLayer(neck,bz+11,{N:W_COL},px-1,0-1); drawLayer(neck,bz+12,{N:W_COL},px-1,0-1); drawLayer(neck,bz+13,{N:W_COL},px ,0-1); /* 头部 */ const head=[ ".HHH.", "HHHHH", "HHHHH", ".HHH." ]; drawLayer(head,bz+14,{H:W_COL},px-1,0-1); drawLayer(head,bz+15,{H:W_COL},px-1,0-1); drawLayer(head,bz+16,{H:W_COL},px-1,0-1); // 头顶羽冠 vox(px,0,bz+17,W_COL); vox(px+1,0,bz+17,W_COL); vox(px+1,0,bz+18,"#ffe0a0"); /* 眼睛 */ vox(px+2,0,bz+16,EYE); // 眼白外圈 vox(px+2,0,bz+15,EYE); vox(px+3,0,bz+16,PUPIL); // 高光 // 眼圈(橙色) vox(px+2,0,bz+17,ORANGE); vox(px+3,0,bz+17,"#cc6611"); /* 喙(上) */ const beakU=[ "OOOOO", "OOOOO", ".OOO." ]; drawLayer(beakU,bz+15,{O:ORANGE},px+2,0); drawLayer(beakU,bz+14,{O:BEAK_D},px+2,0); // 喙尖 vox(px+7,0,bz+14,BEAK_D); vox(px+7,0,bz+15,ORANGE); /* 喉囊(下颌袋,大特征!) */ const pouch=[ ".PPP.", "PPPPP", "PPPPP", "PPPPP", ".PPP.", "..P.." ]; drawLayer(pouch,bz+8, {P:PINK},px+2,0-1); drawLayer(pouch,bz+9, {P:"#ff9999"},px+2,0-1); drawLayer(pouch,bz+10,{P:"#ffbbbb"},px+2,0-1); drawLayer(pouch,bz+11,{P:"#ffcccc"},px+2,0-1); // 喉囊纹理 vox(px+3,0,bz+10,"#ffaaaa"); vox(px+4,0,bz+9, "#ff8888"); /* 腿和脚 */ // 左腿 for(let z=bz+1;z<=bz+4;z++) vox(px-1,0,z,LEG); // 右腿 for(let z=bz+1;z<=bz+4;z++) vox(px+1,0,z,LEG); // 左脚(3趾) vox(px-1,0,bz+1,FOOT);vox(px-2,0,bz+1,FOOT);vox(px,0,bz+1,FOOT); // 右脚(3趾) vox(px+1,0,bz+1,FOOT);vox(px+2,0,bz+1,FOOT);vox(px+3,0,bz+1,FOOT); /* 尾部 */ const tail=[ ".TT.", "TTTT", ".TT.", "..T." ]; drawLayer(tail,bz+5,{T:GRAY},px-5,0-1); drawLayer(tail,bz+6,{T:"#a8b4c0"},px-5,0-1); /* 肩章(橙色斑块) */ vox(px-2,0,bz+9,"#ffcc44"); vox(px+2,0,bz+9,"#ffcc44"); vox(px-2,0,bz+10,"#ffd866"); vox(px+2,0,bz+10,"#ffd866"); /* 安全帽(小细节) */ const helmet=[ ".HHH.", "HHHHH", "HHHHH", ".HHH." ]; drawLayer(helmet,bz+17,{H:"#ff3333"},px-1,0-1); drawLayer(helmet,bz+18,{H:"#ff4444"},px-1,0-1); // 帽檐 vox(px-2,0,bz+17,"#cc2222"); vox(px+2,0,bz+17,"#cc2222"); // 帽扣(黄色条纹) vox(px,0,bz+17,"#ffee44"); vox(px+1,0,bz+17,"#ffee44"); /* 太阳镜 */ vox(px+3,0,bz+15,"#224488"); vox(px+4,0,bz+15,"#224488"); vox(px+2,0,bz+15,"#335599"); // 镜框 vox(px+2,0,bz+16,"#111122"); vox(px+5,0,bz+15,"#112233"); } /* ─────────────── 环境物件 ─────────────── */ /* 指示牌 */ function drawSign(gx,gy){ for(let z=0;z<6;z++) vox(gx,gy,z,"#9a7050"); for(let r=0;r<3;r++) for(let c=0;c<6;c++) vox(gx-3+c,gy,6+r,c===0||c===5||r===0||r===2?"#cc4444":"#ffffdd"); } /* 邮筒 */ function drawMailbox(gx,gy){ for(let z=0;z<3;z++) vox(gx,gy,z,"#777788"); for(let z=3;z<=6;z++) vox(gx,gy,z,"#dd2222"); vox(gx,gy,7,"#cc2222"); vox(gx-1,gy,5,"#dd2222"); vox(gx+1,gy,5,"#dd2222"); vox(gx,gy,5,"#eeeeee"); // 投信口 } /* 长椅 */ function drawBench(gx,gy){ // 腿 vox(gx,gy,0,"#8b6340"); vox(gx,gy,1,"#8b6340"); vox(gx+3,gy,0,"#8b6340"); vox(gx+3,gy,1,"#8b6340"); // 座板 for(let c=0;c<=3;c++) vox(gx+c,gy,2,"#a0784a"); // 靠背 for(let c=0;c<=3;c++) vox(gx+c,gy,3,"#a0784a"); for(let c=0;c<=3;c++) vox(gx+c,gy,4,"#a0784a"); } /* 花朵 */ function drawFlower(gx,gy,col){ vox(gx,gy,0,"#2e8b44"); // 茎 vox(gx,gy,1,"#2e8b44"); vox(gx,gy,2,col); // 花 vox(gx-1,gy,2,col); vox(gx+1,gy,2,col); vox(gx,gy-1,2,col); vox(gx,gy+1,2,col); vox(gx,gy,3,"#ffee44"); // 花心 } /* 蝴蝶 */ function drawButterfly(gx,gy,gz,t){ const flapW = Math.round(Math.sin(t*0.08)*1.5); vox(gx,gy,gz,"#ff6622"); vox(gx-1+flapW,gy,gz,"#ff8833"); vox(gx+1-flapW,gy,gz,"#ff8833"); vox(gx,gy,gz+1,"#111111"); } /* 海鸥 */ function drawSeagull(gx,gy,gz,t){ const flap = Math.round(Math.sin(t*0.06+gx)*1); vox(gx,gy,gz,"#f5f5f5"); vox(gx-2,gy,gz-flap,"#e0e0e0"); vox(gx-1,gy,gz-flap,"#eeeeee"); vox(gx+1,gy,gz-flap,"#eeeeee"); vox(gx+2,gy,gz-flap,"#e0e0e0"); vox(gx,gy,gz,"#ffcc88"); // 嘴 } /* ─────────────── 主渲染循环 ─────────────── */ let t = 0; function render(){ t++; /* 1. 天空 */ drawSky(); drawSun(); /* 2. 云 */ drawCloud(60+Math.sin(t*0.002)*15, 40, 1.4); drawCloud(280+Math.sin(t*0.0015)*20, 20, 1.1); drawCloud(530+Math.sin(t*0.0018)*12, 55, 1.6); drawCloud(740+Math.sin(t*0.0012)*18, 30, 1.0); /* 3. 地面 */ drawGround(); /* 4. 体素层:坐标系原点投射到道路中央 */ // 远处树 drawTree(-18, 5); drawTree(-12, 7); drawTree(12, 6); drawTree(18, 8); drawTree(20, 4); drawTree(-20, 3); // 路灯 drawLamp(-10, 3); drawLamp( 10, 3); // 长椅(路边) drawBench(-7, 5); drawBench( 8, 5); // 邮筒 drawMailbox(-14, 4); // 指示牌 drawSign(13, 4); // 路边花朵 const flowerCols=["#ff4466","#ff8833","#ffee22","#aa44ff","#22ccff"]; for(let i=-8;i<=8;i++){ drawFlower(i*2.5|0, 5, flowerCols[((i+8)%5)]); drawFlower(i*2.5|0, -6, flowerCols[((i+5)%5)]); } // 蝴蝶(2只) drawButterfly(-3, 4, 4, t); drawButterfly( 5, 5, 6, t+30); // 海鸥(远处) drawSeagull(-15,-8,14,t); drawSeagull( 10,-9,12,t); drawSeagull( 2,-11,16,t); /* 5. 自行车(动画) */ const wheelRot = t * 0.05; drawBicycle(-2, 3, wheelRot); /* 6. 鹈鹕(骑在车上) */ drawPelican(-2, 8, t); requestAnimationFrame(render); } requestAnimationFrame(render); })(); </script> </body> </html> 运行起来,是一张图片,无法动起来。 ![]() 那这两个代码有什么区别呢,我看不懂,所以我去问了 DeepSeek V4。 我的问题是:请问这两篇代码有什么不一样,区别在哪?为什么一个能运行动态效果,一个不可以,两个都是用同一个指令生成出来的代码。 DeepSeek V4给我回答了不同之处。 比如渲染方式上,一个是 2D Canvas + 多边形模拟体素(等距投影,手动计算每个面的颜色和阴影);一个是逐个绘制立方体(每个体素画三个面),用类似体素构建的简单块状风格。 绘制顺序上,一个是手工排序:背景 → 地面 → 建筑 → 阴影 → 自行车 → 鹈鹉 → 前景特效,遮挡正确;另一个则无排序,后绘制的体素直接覆盖先绘制的,导致视觉混乱。 关于为什么 Claude opus 4.7 的代码块不能动,有以下几个原因。 1、车轮动画失效 // 第二个代码中的 drawWheel 片段 function drawWheel(wx, wy, r, rot, tireCol, rimCol, hubCol){ for(let i=0;i<pts;i++){ const a = i*Math.PI*2/pts; const gx = wx + Math.round(Math.cos(a)*r); const gz = wy + Math.round(Math.sin(a)*r); vox(gx, 0, gz, tireCol); // ❌ 第二个参数 0 表示 gy 坐标,但这里本应是车轮的高度 } // 辐条同理…… } 问题:vox(gx, 0, gz) 中 gy=0 固定,gz 被当作深度(实际应为高度)。 后果:车轮的每个“块”都绘制在地面高度 gy=0 的同一个水平面上,形成一个平躺的圆环,而不是竖直的轮子。 旋转效果:rot 参数虽然随时间变化,但它只影响辐条位置,而辐条同样使用错误的坐标系,最终画面看不到正常的车轮转动。 2、翅膀动画偏移可能导致不可见 问题:扑翼应该改变翅膀的横向或纵向位置,但这里修改了 z(高度),相当于翅膀上下移动,且 drawLayer 内部调用 vox 时 z 作为高度参数,会导致翅膀整体升高或降低,脱离身体。 后果:看起来像翅膀“瞬移”而非扇动,且可能超出画布或与其他体素重叠混乱。 3、缺乏深度排序 第二个代码中,自行车、鹈鹕、树木、建筑等没有按“远→近”顺序绘制。后绘制的物体会完全覆盖先绘制的,即使它在逻辑上应该被遮挡。 例如:鹈鹕的后半身体可能被前轮遮挡,或者车把被鹈鹕的肚子覆盖,视觉上非常杂乱,动态效果难以辨认。 4.、潜在的错误与性能问题 drawPelican 中多处使用 0-1 这样的表达式作为偏移量(如 px-3,0-2),虽然 JavaScript 会计算为 -2,但容易误导阅读。 drawLayer 内部没有边界检查,负坐标的体素会被绘制到画布外,浪费性能。 大量密集的 vox 调用(每个体素绘制多个路径和填充)导致每帧操作过多,若同时存在动画计算,可能造成卡顿或掉帧,使得动态变化更不明显。 那为什么第一个代码能完美运行呢?他有: 正确的等距投影:iso(x,y,z) 统一转换,所有物体都基于同一个世界坐标系。 严格的绘制顺序:背景 → 地面 → 建筑 → 阴影 → 自行车 → 鹈鹕 → 粒子效果,前后遮挡正确。 清晰的动画变量:t 随时间线性增长,车轮旋转用 rot = -t * 3.6,鹈鹕弹跳用 bounce = Math.sin(t*4)*2,云移动用 (t * 9) % 250,简单可靠。 高效渲染:只绘制可见的多边形面,没有逐个体素绘制,复杂度低,动画流畅。 细节丰富且可交互:鼠标拖拽平移视角,动态海浪、旗帜飘动、车篮里的鱼跳动等,所有效果都肉眼可见。 写到这里,其实可以明显的看出,相同的指令交给不同的 AI 模型,实现质量差异巨大。 第二个代码虽然结构完整,但坐标系设计失误和绘制顺序缺失导致动态效果完全失效。 第一个代码则正确运用了等距投影、深度排序和基于时间的动画,因此能够呈现出预期的“鹈鹕骑自行车”的生动体素艺术场景。 当然我这个只是一个个例,不能就此说明,GPT 5.5 比 Claude Opus 4.7 强。大模型一直在进步中,人也是。 期待所有大模型百花齐放。 Nebula Data 星雲數據,总部位于新加坡,在雅加达、广州、上海、香港设有分支机构。公司自主研发 Nebula Lab 一站式 AI 内容生成与模型聚合平台,搭载企业级 AI Agent,聚合全球通用大模型与行业垂直模型;同步推出 Nebula AIoT 硬件生态体系(含智能交互终端、物联网网关等产品),形成 “云 - 边 - 端” 全链路智能解决方案,为电商、制造、零售等多领域客户提供从云端算力支撑、AI 智能决策到终端场景落地的一体化服务;同时提供全球 AIDC(AI 智算中心)+ 低延迟网络服务,以技术底座赋能企业拥抱 AI、链接物理世界,拓展全球业务。 声明:此篇为星雲數據(香港)有限公司原创文章,转载请标明出处链接:https://www.nebula-data.com/sys-nd/295.html
|