🎮ArcadeLab

复刻监控人1.0

by TurboKoala83
186 lines6.5 KB🛠️ Three.js (3D graphics)
▶ Play
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>复刻监控人1.0</title>
  <style>
    body { margin: 0; overflow: hidden; background: #2a2a2a; font-family: sans-serif; }
    #info {
      position: absolute; top: 10px; left: 10px; color: #fff;
      background: rgba(0,0,0,0.6); padding: 10px; border-radius: 8px;
      font-size: 13px; z-index: 10; pointer-events: none;
    }
    #btn {
      position: absolute; bottom: 20px; left: 50%; transform: translateX(-50%);
      padding: 14px 28px; background: #4CAF50; color: #fff; border: none;
      border-radius: 30px; font-size: 16px; z-index: 10; cursor: pointer;
      font-weight: bold;
    }
    #btn:active { background: #388E3C; }
  </style>
</head>
<body>
<div id="info">🖱️ 拖动旋转 | 双指缩放<br>点击下方按钮导出 .obj</div>
<button id="btn">📦 导出 OBJ 模型</button>

<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/exporters/OBJExporter.js"></script>

<script>
// === 场景基础 ===
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x2a2a2a);

const camera = new THREE.PerspectiveCamera(45, innerWidth/innerHeight, 0.1, 100);
camera.position.set(0, 1.8, 3.5);

const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(innerWidth, innerHeight);
renderer.shadowMap.enabled = true;
document.body.appendChild(renderer.domElement);

const controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.target.set(0, 1.2, 0);
controls.update();

// === 灯光 ===
scene.add(new THREE.AmbientLight(0xffffff, 0.65));
const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);
dirLight.position.set(5, 8, 5);
dirLight.castShadow = true;
scene.add(dirLight);

// === 材质定义 (Roblox风格:纯色、硬边、塑料感) ===
const matBlack = new THREE.MeshStandardMaterial({ color: 0x1a1a1a, roughness: 0.8 }); // 西装黑
const matWhite = new THREE.MeshStandardMaterial({ color: 0xeeeeee, roughness: 0.4 }); // 摄像头白
const matDarkGrey = new THREE.MeshStandardMaterial({ color: 0x333333, roughness: 0.5 }); // 镜头外壳
const matLens = new THREE.MeshStandardMaterial({ color: 0x111111, roughness: 0.1, metalness: 0.8, emissive: 0x2244ff, emissiveIntensity: 0.2 }); // 镜头玻璃
const matShirt = new THREE.MeshStandardMaterial({ color: 0xffffff, roughness: 0.6 }); // 衬衫
const matTie = new THREE.MeshStandardMaterial({ color: 0x1a1a2e, roughness: 0.7 }); // 领带深蓝/黑

// === 角色组 ===
const cameraman = new THREE.Group();

// --- 1. 躯干 (加宽加厚,接近你的截图) ---
const body = new THREE.Mesh(new THREE.BoxGeometry(0.55, 0.75, 0.3), matBlack);
body.position.set(0, 1.0, 0);
body.castShadow = true;
cameraman.add(body);

// --- 2. 双腿 (典型的Roblox粗方块) ---
const legGeo = new THREE.BoxGeometry(0.22, 0.65, 0.22);
const legL = new THREE.Mesh(legGeo, matBlack);
legL.position.set(-0.14, 0.33, 0);
legL.castShadow = true;
cameraman.add(legL);

const legR = new THREE.Mesh(legGeo, matBlack);
legR.position.set(0.14, 0.33, 0);
legR.castShadow = true;
cameraman.add(legR);

// --- 3. 双臂 (粗壮的方块,稍微向外张开) ---
const armGeo = new THREE.BoxGeometry(0.18, 0.7, 0.18);
const armL = new THREE.Mesh(armGeo, matBlack);
armL.position.set(-0.38, 0.95, 0);
armL.rotation.z = 0.08;
armL.castShadow = true;
cameraman.add(armL);

const armR = new THREE.Mesh(armGeo, matBlack);
armR.position.set(0.38, 0.95, 0);
armR.rotation.z = -0.08;
armR.castShadow = true;
cameraman.add(armR);

// --- 4. 头部 (根据你的截图,是一个大白色方块,前方有突出的镜头) ---
const headGroup = new THREE.Group();
headGroup.position.set(0, 1.6, 0);

// 4.1 头部主方块 (稍微宽一点,像你的截图)
const headMain = new THREE.Mesh(new THREE.BoxGeometry(0.55, 0.4, 0.55), matWhite);
headMain.castShadow = true;
headGroup.add(headMain);

// 4.2 头部上方的一个小突起 (模仿你截图中不规则的摄像头外形)
const headTop = new THREE.Mesh(new THREE.BoxGeometry(0.3, 0.1, 0.3), matWhite);
headTop.position.set(0, 0.25, -0.1);
headGroup.add(headTop);

// 4.3 正面镜头筒 (圆柱体,突出在正面)
const lensHousing = new THREE.Mesh(new THREE.CylinderGeometry(0.1, 0.1, 0.15, 16), matDarkGrey);
lensHousing.position.set(0, -0.05, 0.3);
lensHousing.rotation.x = Math.PI / 2;
headGroup.add(lensHousing);

// 4.4 镜头内部 (发光玻璃)
const lensGlass = new THREE.Mesh(new THREE.CylinderGeometry(0.07, 0.07, 0.05, 16), matLens);
lensGlass.position.set(0, -0.05, 0.38);
lensGlass.rotation.x = Math.PI / 2;
headGroup.add(lensGlass);

// 4.5 屏幕/黑色面板 (正面下方)
const screenPanel = new THREE.Mesh(new THREE.BoxGeometry(0.2, 0.15, 0.05), matDarkGrey);
screenPanel.position.set(0, 0.1, 0.28);
headGroup.add(screenPanel);

cameraman.add(headGroup);

// --- 5. 衬衫领口与领带 ---
const collar = new THREE.Mesh(new THREE.BoxGeometry(0.3, 0.08, 0.05), matShirt);
collar.position.set(0, 1.38, 0.16);
cameraman.add(collar);

const tie = new THREE.Mesh(new THREE.BoxGeometry(0.06, 0.3, 0.02), matTie);
tie.position.set(0, 1.2, 0.16);
cameraman.add(tie);

// --- 6. 领带结 ---
const tieKnot = new THREE.Mesh(new THREE.BoxGeometry(0.08, 0.08, 0.04), matTie);
tieKnot.position.set(0, 1.33, 0.17);
cameraman.add(tieKnot);

// --- 7. 地面 ---
const ground = new THREE.Mesh(
  new THREE.CircleGeometry(2.5, 32),
  new THREE.MeshStandardMaterial({ color: 0x444444, roughness: 1 })
);
ground.rotation.x = -Math.PI / 2;
ground.position.y = 0;
ground.receiveShadow = true;
scene.add(ground);

scene.add(cameraman);

// === 导出 OBJ 功能 ===
document.getElementById('btn').addEventListener('click', () => {
  const exporter = new THREE.OBJExporter();
  const result = exporter.parse(cameraman);
  const blob = new Blob([result], { type: 'text/plain' });
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = 'my_cameraman.obj';
  a.click();
  URL.revokeObjectURL(url);
});

// === 渲染循环 ===
function animate() {
  requestAnimationFrame(animate);
  controls.update();
  renderer.render(scene, camera);
}
animate();

// === 窗口适配 ===
addEventListener('resize', () => {
  camera.aspect = innerWidth / innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(innerWidth, innerHeight);
});
</script>
</body>
</html>

Game Source: 复刻监控人1.0

Creator: TurboKoala83

Libraries: three

Complexity: moderate (186 lines, 6.5 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: 1-0-turbokoala83" to link back to the original. Then publish at arcadelab.ai/publish.