关于 DeepSeek 新模型的一些构想猜测,很强,但应该不会是咱们所想要的
- 内容介绍
- 文章标签
- 相关推荐
你像咱们站内的佬,不说百分百吧,但是90%以上都是需要一个编程大模型
咱们的期待放在类似于什么上,它的 V4出来了,能够和 opus4.6 打平,在编程能力上是那种真正意义上的打平,不是跑分打平
但是深度求索这家公司的战略从来不是走主流,不管是 R1 还是 V3,就是所有人都在 A 方向上做,他在 B 方向上打出来一个大的;就他很喜欢搞别人不搞的方向;但是这也就意味着咱们的主要需求,大概率不会被它覆盖
以下是一些资料整理,Gemini的,已截图:
image642×644 62.7 KB
image647×485 44.5 KB
image648×344 36.8 KB
所以,我有一个猜测,做出来仍然很强,震惊四座,但根本不是咱们所预想所需要的,编码大模型,因为他很喜欢首创和走新路
当然,也有另外一种可能性,人家走新路,然后成功的把编码大模型打下来了,这样是最好,但是我感觉大概率不会
网友解答:--【壹】--:
他其实想走别的路,但编码也是这条路上的必经点,所以编码也不会太差。
比如之前有人让验证下这个提示词
用three.js实现一个类似于mc的小游戏,玩家可以通过wasd走动、视野里只需要随机加载普通泥土块、玩家能够放置摧毁方块,把完整代码给我,我希望复制到html文件中就能够运行
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>泥土方块世界 · 简易MC风格</title>
<style>
body {
margin: 0;
overflow: hidden;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
#info {
position: absolute;
top: 20px;
left: 20px;
background: rgba(20, 20, 20, 0.7);
color: #eee;
padding: 12px 20px;
border-radius: 8px;
pointer-events: none;
backdrop-filter: blur(4px);
border-left: 4px solid #8B5E3C;
box-shadow: 0 4px 15px rgba(0,0,0,0.3);
z-index: 100;
}
#controls {
position: absolute;
bottom: 30px;
left: 20px;
background: rgba(0, 0, 0, 0.5);
color: #ddd;
padding: 10px 18px;
border-radius: 30px;
font-size: 14px;
pointer-events: none;
backdrop-filter: blur(4px);
z-index: 100;
}
#crosshair {
position: absolute;
top: 50%;
left: 50%;
width: 20px;
height: 20px;
transform: translate(-50%, -50%);
border: 2px solid rgba(255, 255, 255, 0.9);
border-radius: 2px;
background: transparent;
box-shadow: 0 0 8px rgba(0,0,0,0.5);
pointer-events: none;
z-index: 200;
}
#crosshair::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 4px;
height: 4px;
background: white;
border-radius: 50%;
transform: translate(-50%, -50%);
box-shadow: 0 0 6px black;
}
#instruction {
position: absolute;
bottom: 30px;
right: 20px;
background: rgba(0,0,0,0.5);
color: #ffd966;
padding: 10px 18px;
border-radius: 30px;
font-size: 14px;
backdrop-filter: blur(4px);
pointer-events: none;
z-index: 100;
}
#blocker {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 300;
pointer-events: auto;
}
#instructions-popup {
background: #2d2d2d;
color: white;
padding: 30px 40px;
border-radius: 16px;
text-align: center;
box-shadow: 0 10px 30px black;
border: 1px solid #8B5E3C;
}
#instructions-popup h2 {
margin-top: 0;
color: #e6c9a8;
}
#instructions-popup button {
margin-top: 20px;
padding: 12px 28px;
font-size: 18px;
font-weight: bold;
background: #5a8c5a;
color: white;
border: none;
border-radius: 40px;
cursor: pointer;
box-shadow: 0 4px 0 #2d4a2d;
transition: 0.1s;
}
#instructions-popup button:hover {
background: #6fa86f;
transform: translateY(-2px);
box-shadow: 0 6px 0 #2d4a2d;
}
#instructions-popup button:active {
transform: translateY(2px);
box-shadow: 0 2px 0 #2d4a2d;
}
</style>
</head>
<body>
<div id="info">
<h2>🌍 泥土方块世界</h2>
<p>随机生成的泥土 · 建造与破坏</p>
</div>
<div id="controls">
<span style="margin-right: 20px;">🡑🡐🡓🡒 WASD 移动</span>
<span style="margin-right: 20px;">🐭 鼠标视角</span>
<span>␣ 空格跳跃</span>
</div>
<div id="instruction">
<span style="background:#333; padding:4px 10px; border-radius:20px;">🖱️ 左键摧毁 · 右键放置</span>
</div>
<div id="crosshair"></div>
<div id="blocker">
<div id="instructions-popup">
<h2>🪨 进入泥土世界</h2>
<p>WASD 移动 · 鼠标环顾四周<br>左键挖掉方块 · 右键放置泥土<br>空格跳跃 · 随机生成的泥土块等你改造</p>
<button id="start-button">点击开始 / 锁定鼠标</button>
<p style="font-size:12px; opacity:0.7; margin-top:15px;">按 ESC 可退出指针锁定</p>
</div>
</div>
<!-- 引入 Three.js 核心库 -->
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@0.128.0/build/three.module.js",
"three/addons/": "https://unpkg.com/three@0.128.0/examples/jsm/"
}
}
</script>
<script type="module">
import * as THREE from 'three';
import { PointerLockControls } from 'three/addons/controls/PointerLockControls.js';
// --- 初始化场景、相机、渲染器 ---
const scene = new THREE.Scene();
scene.background = new THREE.Color(0xaaccff);
scene.fog = new THREE.FogExp2(0xaaccff, 0.015);
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(2, 2.5, 8);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
document.body.appendChild(renderer.domElement);
// --- 光照系统 ---
scene.add(new THREE.AmbientLight(0x404060, 0.6));
const sunLight = new THREE.DirectionalLight(0xfff5d1, 1.2);
sunLight.position.set(20, 30, 10);
sunLight.castShadow = true;
sunLight.receiveShadow = true;
sunLight.shadow.mapSize.width = 1024;
sunLight.shadow.mapSize.height = 1024;
const d = 30;
sunLight.shadow.camera.left = -d;
sunLight.shadow.camera.right = d;
sunLight.shadow.camera.top = d;
sunLight.shadow.camera.bottom = -d;
sunLight.shadow.camera.near = 1;
sunLight.shadow.camera.far = 50;
sunLight.shadow.bias = -0.001;
scene.add(sunLight);
const fillLight = new THREE.PointLight(0xccddff, 0.5);
fillLight.position.set(-10, 15, 20);
scene.add(fillLight);
const backLight = new THREE.PointLight(0xffccaa, 0.3);
backLight.position.set(-5, 10, -20);
scene.add(backLight);
// --- 装饰云朵 ---
function addClouds() {
const cloudMat = new THREE.MeshStandardMaterial({ color: 0xffffff, transparent: true, opacity: 0.7, roughness: 0.1, emissive: new THREE.Color(0xeeeeee) });
const cloudGroup = new THREE.Group();
const pos = [ [-15, 18, -10], [10, 20, 5], [-5, 22, 15], [18, 16, -15] ];
pos.forEach((p) => {
const cloud = new THREE.Mesh(new THREE.SphereGeometry(2.5, 7, 7), cloudMat);
cloud.position.set(p[0], p[1], p[2]);
cloud.receiveShadow = false;
cloud.castShadow = false;
cloudGroup.add(cloud);
const cloud2 = new THREE.Mesh(new THREE.SphereGeometry(2, 7, 7), cloudMat);
cloud2.position.set(p[0]+2.5, p[1]-0.5, p[2]+1.5);
cloudGroup.add(cloud2);
const cloud3 = new THREE.Mesh(new THREE.SphereGeometry(2.2, 7, 7), cloudMat);
cloud3.position.set(p[0]-2, p[1]+0.3, p[2]-1.8);
cloudGroup.add(cloud3);
});
scene.add(cloudGroup);
}
addClouds();
// --- 程序化泥土纹理 ---
function createDirtTexture() {
const canvas = document.createElement('canvas');
canvas.width = 64;
canvas.height = 64;
const ctx = canvas.getContext('2d');
ctx.fillStyle = '#8B5E3C';
ctx.fillRect(0, 0, 64, 64);
for (let i = 0; i < 600; i++) {
const x = Math.floor(Math.random() * 64);
const y = Math.floor(Math.random() * 64);
const size = Math.random() * 3 + 1;
const bright = Math.random() > 0.5 ? '#A8754A' : '#6F4E2E';
ctx.fillStyle = bright;
ctx.fillRect(x, y, size, size);
}
ctx.fillStyle = '#4D3620';
for (let i = 0; i < 200; i++) {
ctx.fillRect(Math.floor(Math.random()*64), Math.floor(Math.random()*64), 2, 2);
}
ctx.fillStyle = '#C19A6B';
for (let i = 0; i < 100; i++) {
ctx.fillRect(Math.floor(Math.random()*64), Math.floor(Math.random()*64), 1, 1);
}
const texture = new THREE.CanvasTexture(canvas);
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set(1, 1);
return texture;
}
const dirtTexture = createDirtTexture();
const dirtMaterial = new THREE.MeshStandardMaterial({
map: dirtTexture,
roughness: 0.9,
metalness: 0.05,
color: 0xffffff
});
// --- 方块管理 ---
const blockMap = new Map();
function getBlockKey(x, y, z) {
return `${Math.round(x)},${Math.round(y)},${Math.round(z)}`;
}
function addBlock(x, y, z) {
const key = getBlockKey(x, y, z);
if (blockMap.has(key)) return false;
const geometry = new THREE.BoxGeometry(1, 1, 1);
const mesh = new THREE.Mesh(geometry, dirtMaterial.clone());
mesh.position.set(x, y, z);
mesh.castShadow = true;
mesh.receiveShadow = true;
scene.add(mesh);
blockMap.set(key, mesh);
return true;
}
function removeBlock(x, y, z) {
const key = getBlockKey(x, y, z);
const mesh = blockMap.get(key);
if (mesh) {
scene.remove(mesh);
blockMap.delete(key);
return true;
}
return false;
}
function hasBlock(x, y, z) {
return blockMap.has(getBlockKey(x, y, z));
}
// --- 生成初始世界 ---
function generateWorld() {
// 地面平台
for (let x = -12; x <= 12; x++) {
for (let z = -12; z <= 12; z++) {
addBlock(x, 0, z);
}
}
// 随机土堆
for (let i = 0; i < 180; i++) {
const x = Math.floor(Math.random() * 20 - 10);
const z = Math.floor(Math.random() * 20 - 10);
if (Math.abs(x) < 2 && Math.abs(z) < 3) continue;
const height = Math.floor(Math.random() * 4) + 1;
for (let h = 1; h <= height; h++) {
if (Math.random() > 0.7 && h > 2) continue;
addBlock(x, h, z);
}
}
// 额外散落
for (let i = 0; i < 40; i++) {
const x = Math.floor(Math.random() * 24 - 12);
const z = Math.floor(Math.random() * 24 - 12);
const y = Math.floor(Math.random() * 3) + 1;
if (!hasBlock(x, y, z) && y > 0) {
addBlock(x, y, z);
}
}
// 清空出生点附近
for (let dx = -1; dx <= 1; dx++) {
for (let dz = -1; dz <= 1; dz++) {
for (let dy = 0; dy <= 2; dy++) {
const key = getBlockKey(dx, dy, dz+2);
if (blockMap.has(key)) {
const m = blockMap.get(key);
scene.remove(m);
blockMap.delete(key);
}
}
}
}
}
generateWorld();
// --- 玩家控制 ---
let moveForward = false;
let moveBackward = false;
let moveLeft = false;
let moveRight = false;
let canJump = false;
const playerVelocity = new THREE.Vector3();
const playerDirection = new THREE.Vector3();
const playerSpeed = 5.0;
const jumpStrength = 6.0;
const gravity = 12.0;
const playerWidth = 0.6;
const playerHeight = 1.8;
const playerEyeHeight = 1.6;
const pointerLockControls = new PointerLockControls(camera, document.body);
const blocker = document.getElementById('blocker');
const startButton = document.getElementById('start-button');
startButton.addEventListener('click', () => {
pointerLockControls.lock();
});
pointerLockControls.addEventListener('lock', () => {
blocker.style.display = 'none';
});
pointerLockControls.addEventListener('unlock', () => {
blocker.style.display = 'flex';
});
const onKeyDown = (e) => {
switch(e.code) {
case 'KeyW': moveForward = true; break;
case 'KeyS': moveBackward = true; break;
case 'KeyA': moveLeft = true; break;
case 'KeyD': moveRight = true; break;
case 'Space':
if (canJump) {
playerVelocity.y = jumpStrength;
canJump = false;
}
e.preventDefault();
break;
default: break;
}
};
const onKeyUp = (e) => {
switch(e.code) {
case 'KeyW': moveForward = false; break;
case 'KeyS': moveBackward = false; break;
case 'KeyA': moveLeft = false; break;
case 'KeyD': moveRight = false; break;
default: break;
}
};
document.addEventListener('keydown', onKeyDown);
document.addEventListener('keyup', onKeyUp);
// --- 碰撞检测 ---
function checkCollision(x, y, z) {
const halfW = playerWidth / 2;
const minX = x - halfW;
const maxX = x + halfW;
const minY = y;
const maxY = y + playerHeight;
const minZ = z - halfW;
const maxZ = z + halfW;
const startX = Math.floor(minX) - 1;
const endX = Math.floor(maxX) + 1;
const startY = Math.floor(minY) - 1;
const endY = Math.floor(maxY) + 1;
const startZ = Math.floor(minZ) - 1;
const endZ = Math.floor(maxZ) + 1;
for (let bx = startX; bx <= endX; bx++) {
for (let by = startY; by <= endY; by++) {
for (let bz = startZ; bz <= endZ; bz++) {
if (hasBlock(bx, by, bz)) {
const bMinX = bx - 0.5;
const bMaxX = bx + 0.5;
const bMinY = by - 0.5;
const bMaxY = by + 0.5;
const bMinZ = bz - 0.5;
const bMaxZ = bz + 0.5;
if (maxX <= bMinX || minX >= bMaxX) continue;
if (maxY <= bMinY || minY >= bMaxY) continue;
if (maxZ <= bMinZ || minZ >= bMaxZ) continue;
return true;
}
}
}
}
return false;
}
// 移动处理(已修正左右方向)
function applyMovement(deltaTime) {
playerDirection.z = Number(moveForward) - Number(moveBackward);
playerDirection.x = Number(moveRight) - Number(moveLeft);
playerDirection.normalize();
// 获取相机前方方向(水平)
const cameraDir = new THREE.Vector3();
camera.getWorldDirection(cameraDir);
cameraDir.y = 0;
cameraDir.normalize();
// 计算真正的右侧向量(forward × up 的顺序得到右向量)
const cameraRight = new THREE.Vector3();
cameraRight.crossVectors(cameraDir, camera.up).normalize();
// 组合移动向量
const moveX = playerDirection.x * cameraRight.x + playerDirection.z * cameraDir.x;
const moveZ = playerDirection.x * cameraRight.z + playerDirection.z * cameraDir.z;
const speed = playerSpeed * deltaTime;
let newVelX = moveX * speed;
let newVelZ = moveZ * speed;
playerVelocity.y -= gravity * deltaTime;
const currentPos = camera.position.clone();
const footY = currentPos.y - playerEyeHeight;
// X轴移动
let newPosX = currentPos.x + newVelX;
if (!checkCollision(newPosX, footY, currentPos.z)) {
camera.position.x = newPosX;
}
// Z轴移动
let newPosZ = currentPos.z + newVelZ;
if (!checkCollision(camera.position.x, footY, newPosZ)) {
camera.position.z = newPosZ;
}
// Y轴移动(重力/跳跃)
let newFootY = footY + playerVelocity.y * deltaTime;
const newCameraY = newFootY + playerEyeHeight;
if (!checkCollision(camera.position.x, newFootY, camera.position.z)) {
camera.position.y = newCameraY;
canJump = false;
} else {
if (playerVelocity.y < 0) {
canJump = true;
}
playerVelocity.y = 0;
}
// 地面检测
const finalFootY = camera.position.y - playerEyeHeight;
const belowY = finalFootY - 0.1;
let onGround = false;
for (let bx = Math.floor(camera.position.x - 0.5); bx <= Math.floor(camera.position.x + 0.5); bx++) {
for (let bz = Math.floor(camera.position.z - 0.5); bz <= Math.floor(camera.position.z + 0.5); bz++) {
if (hasBlock(bx, Math.floor(belowY), bz)) {
onGround = true;
break;
}
}
}
canJump = onGround;
if (onGround && playerVelocity.y < 0) playerVelocity.y = 0;
}
// --- 射线交互(放置/摧毁)---
const raycaster = new THREE.Raycaster();
function handleBlockInteraction(event) {
if (!pointerLockControls.isLocked) return;
raycaster.setFromCamera({ x: 0, y: 0 }, camera);
const blocks = Array.from(blockMap.values());
const intersects = raycaster.intersectObjects(blocks);
if (intersects.length > 0) {
const intersect = intersects[0];
const blockMesh = intersect.object;
const blockPos = blockMesh.position;
const normal = intersect.face.normal.clone();
const placePos = blockPos.clone().add(normal);
if (event.button === 0) {
// 左键摧毁
removeBlock(blockPos.x, blockPos.y, blockPos.z);
} else if (event.button === 2) {
// 右键放置
const px = Math.round(placePos.x);
const py = Math.round(placePos.y);
const pz = Math.round(placePos.z);
if (!hasBlock(px, py, pz)) {
// 避免放在玩家体内
const halfW = playerWidth/2;
const pMinX = px - 0.5;
const pMaxX = px + 0.5;
const pMinY = py - 0.5;
const pMaxY = py + 0.5;
const pMinZ = pz - 0.5;
const pMaxZ = pz + 0.5;
const playerMinX = camera.position.x - halfW;
const playerMaxX = camera.position.x + halfW;
const playerMinY = camera.position.y - playerEyeHeight;
const playerMaxY = camera.position.y - playerEyeHeight + playerHeight;
const playerMinZ = camera.position.z - halfW;
const playerMaxZ = camera.position.z + halfW;
const overlap = !(pMaxX <= playerMinX || pMinX >= playerMaxX ||
pMaxY <= playerMinY || pMinY >= playerMaxY ||
pMaxZ <= playerMinZ || pMinZ >= playerMaxZ);
if (!overlap) {
addBlock(px, py, pz);
}
}
}
}
}
window.addEventListener('mousedown', (e) => {
handleBlockInteraction(e);
e.preventDefault();
});
window.addEventListener('contextmenu', e => e.preventDefault());
// --- 动画循环 ---
const clock = new THREE.Clock();
function animate() {
const deltaTime = Math.min(clock.getDelta(), 0.1);
if (pointerLockControls.isLocked) {
applyMovement(deltaTime);
}
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
animate();
// --- 窗口自适应 ---
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
</script>
</body>
</html>
你像咱们站内的佬,不说百分百吧,但是90%以上都是需要一个编程大模型
咱们的期待放在类似于什么上,它的 V4出来了,能够和 opus4.6 打平,在编程能力上是那种真正意义上的打平,不是跑分打平
但是深度求索这家公司的战略从来不是走主流,不管是 R1 还是 V3,就是所有人都在 A 方向上做,他在 B 方向上打出来一个大的;就他很喜欢搞别人不搞的方向;但是这也就意味着咱们的主要需求,大概率不会被它覆盖
以下是一些资料整理,Gemini的,已截图:
image642×644 62.7 KB
image647×485 44.5 KB
image648×344 36.8 KB
所以,我有一个猜测,做出来仍然很强,震惊四座,但根本不是咱们所预想所需要的,编码大模型,因为他很喜欢首创和走新路
当然,也有另外一种可能性,人家走新路,然后成功的把编码大模型打下来了,这样是最好,但是我感觉大概率不会
网友解答:--【壹】--:
他其实想走别的路,但编码也是这条路上的必经点,所以编码也不会太差。
比如之前有人让验证下这个提示词
用three.js实现一个类似于mc的小游戏,玩家可以通过wasd走动、视野里只需要随机加载普通泥土块、玩家能够放置摧毁方块,把完整代码给我,我希望复制到html文件中就能够运行
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>泥土方块世界 · 简易MC风格</title>
<style>
body {
margin: 0;
overflow: hidden;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
#info {
position: absolute;
top: 20px;
left: 20px;
background: rgba(20, 20, 20, 0.7);
color: #eee;
padding: 12px 20px;
border-radius: 8px;
pointer-events: none;
backdrop-filter: blur(4px);
border-left: 4px solid #8B5E3C;
box-shadow: 0 4px 15px rgba(0,0,0,0.3);
z-index: 100;
}
#controls {
position: absolute;
bottom: 30px;
left: 20px;
background: rgba(0, 0, 0, 0.5);
color: #ddd;
padding: 10px 18px;
border-radius: 30px;
font-size: 14px;
pointer-events: none;
backdrop-filter: blur(4px);
z-index: 100;
}
#crosshair {
position: absolute;
top: 50%;
left: 50%;
width: 20px;
height: 20px;
transform: translate(-50%, -50%);
border: 2px solid rgba(255, 255, 255, 0.9);
border-radius: 2px;
background: transparent;
box-shadow: 0 0 8px rgba(0,0,0,0.5);
pointer-events: none;
z-index: 200;
}
#crosshair::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 4px;
height: 4px;
background: white;
border-radius: 50%;
transform: translate(-50%, -50%);
box-shadow: 0 0 6px black;
}
#instruction {
position: absolute;
bottom: 30px;
right: 20px;
background: rgba(0,0,0,0.5);
color: #ffd966;
padding: 10px 18px;
border-radius: 30px;
font-size: 14px;
backdrop-filter: blur(4px);
pointer-events: none;
z-index: 100;
}
#blocker {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 300;
pointer-events: auto;
}
#instructions-popup {
background: #2d2d2d;
color: white;
padding: 30px 40px;
border-radius: 16px;
text-align: center;
box-shadow: 0 10px 30px black;
border: 1px solid #8B5E3C;
}
#instructions-popup h2 {
margin-top: 0;
color: #e6c9a8;
}
#instructions-popup button {
margin-top: 20px;
padding: 12px 28px;
font-size: 18px;
font-weight: bold;
background: #5a8c5a;
color: white;
border: none;
border-radius: 40px;
cursor: pointer;
box-shadow: 0 4px 0 #2d4a2d;
transition: 0.1s;
}
#instructions-popup button:hover {
background: #6fa86f;
transform: translateY(-2px);
box-shadow: 0 6px 0 #2d4a2d;
}
#instructions-popup button:active {
transform: translateY(2px);
box-shadow: 0 2px 0 #2d4a2d;
}
</style>
</head>
<body>
<div id="info">
<h2>🌍 泥土方块世界</h2>
<p>随机生成的泥土 · 建造与破坏</p>
</div>
<div id="controls">
<span style="margin-right: 20px;">🡑🡐🡓🡒 WASD 移动</span>
<span style="margin-right: 20px;">🐭 鼠标视角</span>
<span>␣ 空格跳跃</span>
</div>
<div id="instruction">
<span style="background:#333; padding:4px 10px; border-radius:20px;">🖱️ 左键摧毁 · 右键放置</span>
</div>
<div id="crosshair"></div>
<div id="blocker">
<div id="instructions-popup">
<h2>🪨 进入泥土世界</h2>
<p>WASD 移动 · 鼠标环顾四周<br>左键挖掉方块 · 右键放置泥土<br>空格跳跃 · 随机生成的泥土块等你改造</p>
<button id="start-button">点击开始 / 锁定鼠标</button>
<p style="font-size:12px; opacity:0.7; margin-top:15px;">按 ESC 可退出指针锁定</p>
</div>
</div>
<!-- 引入 Three.js 核心库 -->
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@0.128.0/build/three.module.js",
"three/addons/": "https://unpkg.com/three@0.128.0/examples/jsm/"
}
}
</script>
<script type="module">
import * as THREE from 'three';
import { PointerLockControls } from 'three/addons/controls/PointerLockControls.js';
// --- 初始化场景、相机、渲染器 ---
const scene = new THREE.Scene();
scene.background = new THREE.Color(0xaaccff);
scene.fog = new THREE.FogExp2(0xaaccff, 0.015);
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(2, 2.5, 8);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
document.body.appendChild(renderer.domElement);
// --- 光照系统 ---
scene.add(new THREE.AmbientLight(0x404060, 0.6));
const sunLight = new THREE.DirectionalLight(0xfff5d1, 1.2);
sunLight.position.set(20, 30, 10);
sunLight.castShadow = true;
sunLight.receiveShadow = true;
sunLight.shadow.mapSize.width = 1024;
sunLight.shadow.mapSize.height = 1024;
const d = 30;
sunLight.shadow.camera.left = -d;
sunLight.shadow.camera.right = d;
sunLight.shadow.camera.top = d;
sunLight.shadow.camera.bottom = -d;
sunLight.shadow.camera.near = 1;
sunLight.shadow.camera.far = 50;
sunLight.shadow.bias = -0.001;
scene.add(sunLight);
const fillLight = new THREE.PointLight(0xccddff, 0.5);
fillLight.position.set(-10, 15, 20);
scene.add(fillLight);
const backLight = new THREE.PointLight(0xffccaa, 0.3);
backLight.position.set(-5, 10, -20);
scene.add(backLight);
// --- 装饰云朵 ---
function addClouds() {
const cloudMat = new THREE.MeshStandardMaterial({ color: 0xffffff, transparent: true, opacity: 0.7, roughness: 0.1, emissive: new THREE.Color(0xeeeeee) });
const cloudGroup = new THREE.Group();
const pos = [ [-15, 18, -10], [10, 20, 5], [-5, 22, 15], [18, 16, -15] ];
pos.forEach((p) => {
const cloud = new THREE.Mesh(new THREE.SphereGeometry(2.5, 7, 7), cloudMat);
cloud.position.set(p[0], p[1], p[2]);
cloud.receiveShadow = false;
cloud.castShadow = false;
cloudGroup.add(cloud);
const cloud2 = new THREE.Mesh(new THREE.SphereGeometry(2, 7, 7), cloudMat);
cloud2.position.set(p[0]+2.5, p[1]-0.5, p[2]+1.5);
cloudGroup.add(cloud2);
const cloud3 = new THREE.Mesh(new THREE.SphereGeometry(2.2, 7, 7), cloudMat);
cloud3.position.set(p[0]-2, p[1]+0.3, p[2]-1.8);
cloudGroup.add(cloud3);
});
scene.add(cloudGroup);
}
addClouds();
// --- 程序化泥土纹理 ---
function createDirtTexture() {
const canvas = document.createElement('canvas');
canvas.width = 64;
canvas.height = 64;
const ctx = canvas.getContext('2d');
ctx.fillStyle = '#8B5E3C';
ctx.fillRect(0, 0, 64, 64);
for (let i = 0; i < 600; i++) {
const x = Math.floor(Math.random() * 64);
const y = Math.floor(Math.random() * 64);
const size = Math.random() * 3 + 1;
const bright = Math.random() > 0.5 ? '#A8754A' : '#6F4E2E';
ctx.fillStyle = bright;
ctx.fillRect(x, y, size, size);
}
ctx.fillStyle = '#4D3620';
for (let i = 0; i < 200; i++) {
ctx.fillRect(Math.floor(Math.random()*64), Math.floor(Math.random()*64), 2, 2);
}
ctx.fillStyle = '#C19A6B';
for (let i = 0; i < 100; i++) {
ctx.fillRect(Math.floor(Math.random()*64), Math.floor(Math.random()*64), 1, 1);
}
const texture = new THREE.CanvasTexture(canvas);
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set(1, 1);
return texture;
}
const dirtTexture = createDirtTexture();
const dirtMaterial = new THREE.MeshStandardMaterial({
map: dirtTexture,
roughness: 0.9,
metalness: 0.05,
color: 0xffffff
});
// --- 方块管理 ---
const blockMap = new Map();
function getBlockKey(x, y, z) {
return `${Math.round(x)},${Math.round(y)},${Math.round(z)}`;
}
function addBlock(x, y, z) {
const key = getBlockKey(x, y, z);
if (blockMap.has(key)) return false;
const geometry = new THREE.BoxGeometry(1, 1, 1);
const mesh = new THREE.Mesh(geometry, dirtMaterial.clone());
mesh.position.set(x, y, z);
mesh.castShadow = true;
mesh.receiveShadow = true;
scene.add(mesh);
blockMap.set(key, mesh);
return true;
}
function removeBlock(x, y, z) {
const key = getBlockKey(x, y, z);
const mesh = blockMap.get(key);
if (mesh) {
scene.remove(mesh);
blockMap.delete(key);
return true;
}
return false;
}
function hasBlock(x, y, z) {
return blockMap.has(getBlockKey(x, y, z));
}
// --- 生成初始世界 ---
function generateWorld() {
// 地面平台
for (let x = -12; x <= 12; x++) {
for (let z = -12; z <= 12; z++) {
addBlock(x, 0, z);
}
}
// 随机土堆
for (let i = 0; i < 180; i++) {
const x = Math.floor(Math.random() * 20 - 10);
const z = Math.floor(Math.random() * 20 - 10);
if (Math.abs(x) < 2 && Math.abs(z) < 3) continue;
const height = Math.floor(Math.random() * 4) + 1;
for (let h = 1; h <= height; h++) {
if (Math.random() > 0.7 && h > 2) continue;
addBlock(x, h, z);
}
}
// 额外散落
for (let i = 0; i < 40; i++) {
const x = Math.floor(Math.random() * 24 - 12);
const z = Math.floor(Math.random() * 24 - 12);
const y = Math.floor(Math.random() * 3) + 1;
if (!hasBlock(x, y, z) && y > 0) {
addBlock(x, y, z);
}
}
// 清空出生点附近
for (let dx = -1; dx <= 1; dx++) {
for (let dz = -1; dz <= 1; dz++) {
for (let dy = 0; dy <= 2; dy++) {
const key = getBlockKey(dx, dy, dz+2);
if (blockMap.has(key)) {
const m = blockMap.get(key);
scene.remove(m);
blockMap.delete(key);
}
}
}
}
}
generateWorld();
// --- 玩家控制 ---
let moveForward = false;
let moveBackward = false;
let moveLeft = false;
let moveRight = false;
let canJump = false;
const playerVelocity = new THREE.Vector3();
const playerDirection = new THREE.Vector3();
const playerSpeed = 5.0;
const jumpStrength = 6.0;
const gravity = 12.0;
const playerWidth = 0.6;
const playerHeight = 1.8;
const playerEyeHeight = 1.6;
const pointerLockControls = new PointerLockControls(camera, document.body);
const blocker = document.getElementById('blocker');
const startButton = document.getElementById('start-button');
startButton.addEventListener('click', () => {
pointerLockControls.lock();
});
pointerLockControls.addEventListener('lock', () => {
blocker.style.display = 'none';
});
pointerLockControls.addEventListener('unlock', () => {
blocker.style.display = 'flex';
});
const onKeyDown = (e) => {
switch(e.code) {
case 'KeyW': moveForward = true; break;
case 'KeyS': moveBackward = true; break;
case 'KeyA': moveLeft = true; break;
case 'KeyD': moveRight = true; break;
case 'Space':
if (canJump) {
playerVelocity.y = jumpStrength;
canJump = false;
}
e.preventDefault();
break;
default: break;
}
};
const onKeyUp = (e) => {
switch(e.code) {
case 'KeyW': moveForward = false; break;
case 'KeyS': moveBackward = false; break;
case 'KeyA': moveLeft = false; break;
case 'KeyD': moveRight = false; break;
default: break;
}
};
document.addEventListener('keydown', onKeyDown);
document.addEventListener('keyup', onKeyUp);
// --- 碰撞检测 ---
function checkCollision(x, y, z) {
const halfW = playerWidth / 2;
const minX = x - halfW;
const maxX = x + halfW;
const minY = y;
const maxY = y + playerHeight;
const minZ = z - halfW;
const maxZ = z + halfW;
const startX = Math.floor(minX) - 1;
const endX = Math.floor(maxX) + 1;
const startY = Math.floor(minY) - 1;
const endY = Math.floor(maxY) + 1;
const startZ = Math.floor(minZ) - 1;
const endZ = Math.floor(maxZ) + 1;
for (let bx = startX; bx <= endX; bx++) {
for (let by = startY; by <= endY; by++) {
for (let bz = startZ; bz <= endZ; bz++) {
if (hasBlock(bx, by, bz)) {
const bMinX = bx - 0.5;
const bMaxX = bx + 0.5;
const bMinY = by - 0.5;
const bMaxY = by + 0.5;
const bMinZ = bz - 0.5;
const bMaxZ = bz + 0.5;
if (maxX <= bMinX || minX >= bMaxX) continue;
if (maxY <= bMinY || minY >= bMaxY) continue;
if (maxZ <= bMinZ || minZ >= bMaxZ) continue;
return true;
}
}
}
}
return false;
}
// 移动处理(已修正左右方向)
function applyMovement(deltaTime) {
playerDirection.z = Number(moveForward) - Number(moveBackward);
playerDirection.x = Number(moveRight) - Number(moveLeft);
playerDirection.normalize();
// 获取相机前方方向(水平)
const cameraDir = new THREE.Vector3();
camera.getWorldDirection(cameraDir);
cameraDir.y = 0;
cameraDir.normalize();
// 计算真正的右侧向量(forward × up 的顺序得到右向量)
const cameraRight = new THREE.Vector3();
cameraRight.crossVectors(cameraDir, camera.up).normalize();
// 组合移动向量
const moveX = playerDirection.x * cameraRight.x + playerDirection.z * cameraDir.x;
const moveZ = playerDirection.x * cameraRight.z + playerDirection.z * cameraDir.z;
const speed = playerSpeed * deltaTime;
let newVelX = moveX * speed;
let newVelZ = moveZ * speed;
playerVelocity.y -= gravity * deltaTime;
const currentPos = camera.position.clone();
const footY = currentPos.y - playerEyeHeight;
// X轴移动
let newPosX = currentPos.x + newVelX;
if (!checkCollision(newPosX, footY, currentPos.z)) {
camera.position.x = newPosX;
}
// Z轴移动
let newPosZ = currentPos.z + newVelZ;
if (!checkCollision(camera.position.x, footY, newPosZ)) {
camera.position.z = newPosZ;
}
// Y轴移动(重力/跳跃)
let newFootY = footY + playerVelocity.y * deltaTime;
const newCameraY = newFootY + playerEyeHeight;
if (!checkCollision(camera.position.x, newFootY, camera.position.z)) {
camera.position.y = newCameraY;
canJump = false;
} else {
if (playerVelocity.y < 0) {
canJump = true;
}
playerVelocity.y = 0;
}
// 地面检测
const finalFootY = camera.position.y - playerEyeHeight;
const belowY = finalFootY - 0.1;
let onGround = false;
for (let bx = Math.floor(camera.position.x - 0.5); bx <= Math.floor(camera.position.x + 0.5); bx++) {
for (let bz = Math.floor(camera.position.z - 0.5); bz <= Math.floor(camera.position.z + 0.5); bz++) {
if (hasBlock(bx, Math.floor(belowY), bz)) {
onGround = true;
break;
}
}
}
canJump = onGround;
if (onGround && playerVelocity.y < 0) playerVelocity.y = 0;
}
// --- 射线交互(放置/摧毁)---
const raycaster = new THREE.Raycaster();
function handleBlockInteraction(event) {
if (!pointerLockControls.isLocked) return;
raycaster.setFromCamera({ x: 0, y: 0 }, camera);
const blocks = Array.from(blockMap.values());
const intersects = raycaster.intersectObjects(blocks);
if (intersects.length > 0) {
const intersect = intersects[0];
const blockMesh = intersect.object;
const blockPos = blockMesh.position;
const normal = intersect.face.normal.clone();
const placePos = blockPos.clone().add(normal);
if (event.button === 0) {
// 左键摧毁
removeBlock(blockPos.x, blockPos.y, blockPos.z);
} else if (event.button === 2) {
// 右键放置
const px = Math.round(placePos.x);
const py = Math.round(placePos.y);
const pz = Math.round(placePos.z);
if (!hasBlock(px, py, pz)) {
// 避免放在玩家体内
const halfW = playerWidth/2;
const pMinX = px - 0.5;
const pMaxX = px + 0.5;
const pMinY = py - 0.5;
const pMaxY = py + 0.5;
const pMinZ = pz - 0.5;
const pMaxZ = pz + 0.5;
const playerMinX = camera.position.x - halfW;
const playerMaxX = camera.position.x + halfW;
const playerMinY = camera.position.y - playerEyeHeight;
const playerMaxY = camera.position.y - playerEyeHeight + playerHeight;
const playerMinZ = camera.position.z - halfW;
const playerMaxZ = camera.position.z + halfW;
const overlap = !(pMaxX <= playerMinX || pMinX >= playerMaxX ||
pMaxY <= playerMinY || pMinY >= playerMaxY ||
pMaxZ <= playerMinZ || pMinZ >= playerMaxZ);
if (!overlap) {
addBlock(px, py, pz);
}
}
}
}
}
window.addEventListener('mousedown', (e) => {
handleBlockInteraction(e);
e.preventDefault();
});
window.addEventListener('contextmenu', e => e.preventDefault());
// --- 动画循环 ---
const clock = new THREE.Clock();
function animate() {
const deltaTime = Math.min(clock.getDelta(), 0.1);
if (pointerLockControls.isLocked) {
applyMovement(deltaTime);
}
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
animate();
// --- 窗口自适应 ---
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
</script>
</body>
</html>

