🎮ArcadeLab

汉阳造步枪 - 独立建模测试

by TurboKoala83
273 lines8.1 KB
▶ Play
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>汉阳造步枪 - 独立建模测试</title>
<style>
  body { margin: 0; background: #1a1a2e; display: flex; justify-content: center; align-items: center; height: 100vh; overflow: hidden; font-family: 'Microsoft YaHei', sans-serif; }
  canvas { background: linear-gradient(180deg, #16213e 0%, #0f3460 100%); border-radius: 12px; box-shadow: 0 0 40px rgba(196, 30, 58, 0.3); }
  .info { position: absolute; top: 20px; left: 50%; transform: translateX(-50%); color: #c41e3a; font-size: 14px; letter-spacing: 4px; text-shadow: 0 0 10px rgba(196, 30, 58, 0.8); }
</style>
</head>
<body>
<div class="info">★ 汉阳造步枪 · 独立建模 ★</div>
<canvas id="game" width="700" height="500"></canvas>

<script>
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');

// ========== 枪械配色 ==========
const GUN_COLORS = {
  wood:       '#5A3A1A', // 枪托木质主色
  woodDark:   '#3A2210', // 木质阴影
  woodLite:   '#7A4A2A', // 木质高光
  metal:      '#4A4A4A', // 金属主色(枪管、机匣)
  metalDark:  '#2A2A2A', // 金属阴影
  metalLite:  '#8A8A8A', // 金属高光(枪栓、刺刀)
  strap:      '#6B5A3A', // 枪背带
};

// ========== 绘制工具 ==========
function roundRect(ctx, x, y, w, h, r) {
  ctx.beginPath();
  ctx.moveTo(x + r, y);
  ctx.lineTo(x + w - r, y);
  ctx.quadraticCurveTo(x + w, y, x + w, y + r);
  ctx.lineTo(x + w, y + h - r);
  ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);
  ctx.lineTo(x + r, y + h);
  ctx.quadraticCurveTo(x, y + h, x, y + h - r);
  ctx.lineTo(x, y + r);
  ctx.quadraticCurveTo(x, y, x + r, y);
  ctx.closePath();
}

// =====================================================================
// 独立枪械建模函数
// 原点 (0,0) 设定在【扳机位置】(即右手握持处),方便后续挂载
// x 轴正方向为枪口方向(向右),y 轴正方向向下
// =====================================================================
function drawRifle(ctx, x, y, rotation = 0, scale = 1) {
  ctx.save();
  ctx.translate(x, y);
  ctx.rotate(rotation);
  ctx.scale(scale, scale);

  const C = GUN_COLORS;

  // ---------------------------------------------------------
  // 1. 枪托后部(木质)
  // ---------------------------------------------------------
  ctx.fillStyle = C.wood;
  ctx.beginPath();
  ctx.moveTo(-15, -5);   // 顶部靠前
  ctx.lineTo(-50, -5);   // 顶部靠后
  ctx.lineTo(-55, 10);   // 底部靠后
  ctx.lineTo(-25, 15);   // 底部靠前(握把上方)
  ctx.closePath();
  ctx.fill();

  // 枪托阴影和高光
  ctx.fillStyle = C.woodDark;
  ctx.beginPath();
  ctx.moveTo(-15, -5);
  ctx.lineTo(-50, -5);
  ctx.lineTo(-50, 0);
  ctx.lineTo(-15, 0);
  ctx.closePath();
  ctx.fill();

  ctx.fillStyle = C.woodLite;
  ctx.fillRect(-50, 0, 35, 2);

  // 金属托底板
  ctx.fillStyle = C.metalDark;
  ctx.fillRect(-56, -6, 3, 20);

  // ---------------------------------------------------------
  // 2. 握把与扳机(木质握把)
  // ---------------------------------------------------------
  ctx.fillStyle = C.wood;
  ctx.beginPath();
  ctx.moveTo(-25, 10);
  ctx.lineTo(-15, 10);
  ctx.lineTo(-10, 35);
  ctx.lineTo(-20, 35);
  ctx.closePath();
  ctx.fill();

  ctx.fillStyle = C.woodDark;
  ctx.fillRect(-22, 10, 4, 25);

  // 扳机护圈(金属圆弧)
  ctx.strokeStyle = C.metal;
  ctx.lineWidth = 3;
  ctx.beginPath();
  ctx.arc(-10, 12, 8, 0, Math.PI);
  ctx.stroke();

  // ---------------------------------------------------------
  // 3. 枪身中部(木质前护木)
  // ---------------------------------------------------------
  ctx.fillStyle = C.wood;
  ctx.fillRect(-10, -8, 70, 16); // 从扳机前方延伸到枪管中段

  // 木质高光和阴影
  ctx.fillStyle = C.woodLite;
  ctx.fillRect(-10, -8, 70, 3);
  ctx.fillStyle = C.woodDark;
  ctx.fillRect(-10, 5, 70, 3);

  // ---------------------------------------------------------
  // 4. 枪管(金属)
  // ---------------------------------------------------------
  const barrelLength = 90;
  ctx.fillStyle = C.metal;
  ctx.fillRect(40, -6, barrelLength, 12); // 主枪管

  // 枪管高光与阴影
  ctx.fillStyle = C.metalLite;
  ctx.fillRect(40, -5, barrelLength, 3); 
  ctx.fillStyle = C.metalDark;
  ctx.fillRect(40, 4, barrelLength, 2);

  // ---------------------------------------------------------
  // 5. 机匣与枪栓(金属结构)
  // ---------------------------------------------------------
  // 机匣底座
  ctx.fillStyle = C.metalDark;
  ctx.fillRect(5, -10, 15, 20);

  // 枪栓拉柄
  ctx.fillStyle = C.metalLite;
  ctx.beginPath();
  ctx.moveTo(12, -8);
  ctx.lineTo(18, -15);
  ctx.lineTo(22, -15);
  ctx.lineTo(18, -8);
  ctx.closePath();
  ctx.fill();

  // 枪栓圆球把手
  ctx.fillStyle = C.metal;
  ctx.beginPath();
  ctx.arc(22, -15, 5, 0, Math.PI * 2);
  ctx.fill();
  
  // 枪栓高光
  ctx.fillStyle = C.metalLite;
  ctx.beginPath();
  ctx.arc(21, -16, 2, 0, Math.PI * 2);
  ctx.fill();

  // ---------------------------------------------------------
  // 6. 枪口与准星(金属)
  // ---------------------------------------------------------
  const muzzleX = 40 + barrelLength;

  // 枪口
  ctx.fillStyle = C.metalDark;
  ctx.fillRect(muzzleX - 5, -7, 5, 14);

  // 准星底座
  ctx.fillStyle = C.metal;
  ctx.fillRect(muzzleX - 15, -12, 6, 6);

  // 准星
  ctx.fillStyle = C.metalLite;
  ctx.fillRect(muzzleX - 12, -16, 2, 4);

  // ---------------------------------------------------------
  // 7. 刺刀(锋利的金属)
  // ---------------------------------------------------------
  ctx.fillStyle = C.metalLite;
  ctx.beginPath();
  ctx.moveTo(muzzleX, -4);        // 刀根下部
  ctx.lineTo(muzzleX + 30, -3);   // 刀尖下部
  ctx.lineTo(muzzleX + 32, -1);   // 刀尖
  ctx.lineTo(muzzleX + 30, 0);    // 刀尖上部
  ctx.lineTo(muzzleX, 2);         // 刀根上部
  ctx.closePath();
  ctx.fill();

  // 刺刀血槽(反光线条)
  ctx.fillStyle = '#FFFFFF';
  ctx.fillRect(muzzleX + 5, -1, 20, 1);

  // 刺刀固定环
  ctx.fillStyle = C.metalDark;
  ctx.fillRect(muzzleX - 2, -6, 4, 12);

  // ---------------------------------------------------------
  // 8. 枪背带(帆布/皮革)
  // ---------------------------------------------------------
  ctx.strokeStyle = C.strap;
  ctx.lineWidth = 4;
  ctx.beginPath();
  ctx.moveTo(-45, 5);   // 从枪托后部挂载
  ctx.quadraticCurveTo(-20, 40, 20, 20); // 自然下垂
  ctx.lineTo(30, -5);   // 连接到前护木
  ctx.stroke();

  // 背带环(金属小圆)
  ctx.fillStyle = C.metalDark;
  ctx.beginPath();
  ctx.arc(-45, 5, 3, 0, Math.PI * 2);
  ctx.fill();
  ctx.beginPath();
  ctx.arc(30, -5, 3, 0, Math.PI * 2);
  ctx.fill();

  ctx.restore();
}

// =====================================================================
// 主循环 - 静态展示 + 旋转动画
// =====================================================================
let time = 0;

function animate() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  
  time += 0.02;

  const cx = canvas.width / 2;
  const cy = canvas.height / 2;

  // 画一个简单的台面或参考线
  ctx.strokeStyle = '#2a4a3a';
  ctx.lineWidth = 2;
  ctx.beginPath();
  ctx.moveTo(0, cy + 50);
  ctx.lineTo(canvas.width, cy + 50);
  ctx.stroke();

  // 添加一些背景参考网格
  ctx.strokeStyle = 'rgba(255, 255, 255, 0.05)';
  ctx.lineWidth = 1;
  for (let i = 0; i < canvas.width; i += 50) {
    ctx.beginPath(); ctx.moveTo(i, 0); ctx.lineTo(i, canvas.height); ctx.stroke();
  }
  for (let i = 0; i < canvas.height; i += 50) {
    ctx.beginPath(); ctx.moveTo(0, i); ctx.lineTo(canvas.width, i); ctx.stroke();
  }

  // 绘制枪械
  // 注意:原点的位置在枪身中部(扳机处),所以需要向左偏移使其居中
  drawRifle(ctx, cx - 20, cy, 0, 1.5);

  // 绘制文字标注
  ctx.fillStyle = '#aaa';
  ctx.font = '12px sans-serif';
  ctx.fillText('原点 (0,0) 在扳机处', cx - 100, cy + 80);
  ctx.fillText('枪管长度: 90px', cx + 40, cy + 80);
  ctx.fillText('刺刀: 30px', cx + 150, cy + 80);

  requestAnimationFrame(animate);
}

animate();
</script>
</body>
</html>

Game Source: 汉阳造步枪 - 独立建模测试

Creator: TurboKoala83

Libraries: none

Complexity: complex (273 lines, 8.1 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-turbokoala83-mup0voqh" to link back to the original. Then publish at arcadelab.ai/publish.