создай игру на javascript css html в точь в точь к...

Criado em: 9 de junho de 2025

Respondido usando O3 por Chat01

Pergunta

создай игру на javascript css html в точь в точь как Minecraft

Pensamento

Creating a simplified version

The user wants a game like Minecraft, but building a full game is too complex for a single response. Also, replicating Minecraft could raise copyright concerns, even if there's no explicit policy against it. I can’t give a full game, but I could suggest a minimalistic version with a voxel-based sandbox using Three.js, block placement, and pointer lock. I’ll need to disclaim that this is a simplified version due to the complexity. Also, I see they’ve disabled the canvas tool, which limits some options.

Thought for 10 seconds

Resposta

Ниже — минимальный «voxel-sandbox» на HTML + CSS + JS. Он воспроизводит базовые механики Minecraft-подобной игры: первое лицо, бег (W-A-S-D), прыжок (пробел), разрушение блока (ЛКМ) и установка нового (ПКМ). Это не полный клон (оригинал — десятки тысяч строк кода), но хорошая отправная точка: логику рендеринга и управления можно расширять бесконечно.

⚠️ Браузеры блокируют модульные скрипты при открытии файла напрямую. Запустите простой сервер (например, python -m http.server) и откройте http://localhost:8000.


📄 index.html

html
<!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8" /> <title>Voxel Sandbox</title> <link rel="stylesheet" href="style.css" /> <!-- Three.js с CDN (r168) --> <script type="module" src="main.js"></script> </head> <body> <div id="blockInfo">Выбран блок: dirt (ПКМ — поставить)</div> <div id="crosshair"></div> </body> </html>

🎨 style.css

css
body, html { margin: 0; overflow: hidden; background: #87ceeb; /* небо */ font-family: system-ui, sans-serif; } /* белый крестик по центру */ #crosshair { position: fixed; top: 50%; left: 50%; width: 14px; height: 14px; margin-left: -7px; margin-top: -7px; pointer-events: none; } #crosshair::before, #crosshair::after { content: ''; position: absolute; background: #fff; } #crosshair::before { /* вертикаль */ left: 6px; top: 0; width: 2px; height: 14px; } #crosshair::after { /* горизонталь */ top: 6px; left: 0; width: 14px; height: 2px; } #blockInfo { position: absolute; top: 10px; left: 10px; color: #fff; text-shadow: 0 0 4px #000; user-select: none; }

💡 main.js

js
import * as THREE from "https://unpkg.com/[email protected]/build/three.module.js"; import { PointerLockControls } from "https://unpkg.com/[email protected]/examples/jsm/controls/PointerLockControls.js"; const worldSize = 32; // 32×32 блоков по X-Z const blockSize = 1; // 1 ед. = 1 блок const textureLoader = new THREE.TextureLoader(); const texDirt = textureLoader.load("https://i.imgur.com/1eE5N9I.png"); // простая текстура const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(75, innerWidth / innerHeight, 0.1, 1000); camera.position.set(worldSize / 2, 5, worldSize / 2); const renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(innerWidth, innerHeight); document.body.appendChild(renderer.domElement); // Свет const light = new THREE.DirectionalLight(0xffffff, 1); light.position.set(100, 200, 100); scene.add(light, new THREE.AmbientLight(0xffffff, 0.4)); // Контролы «поймать курсор» const controls = new PointerLockControls(camera, document.body); document.addEventListener("click", () => controls.lock()); controls.addEventListener("lock", () => (blockInfo.style.display = "none")); controls.addEventListener("unlock", () => (blockInfo.style.display = "block")); // Создание одного куба const cubeGeo = new THREE.BoxGeometry(blockSize, blockSize, blockSize); const cubeMat = new THREE.MeshLambertMaterial({ map: texDirt }); function makeCube(x, y, z) { const mesh = new THREE.Mesh(cubeGeo, cubeMat); mesh.position.set(x + 0.5, y + 0.5, z + 0.5); // центр-по-блоку return mesh; } // Карта блоков: храним строки «x:y:z» → Mesh const blocks = new Map(); // Генерация плоскости 32×32, высота = 0 for (let x = 0; x < worldSize; x++) { for (let z = 0; z < worldSize; z++) { const cube = makeCube(x, 0, z); scene.add(cube); blocks.set(`${x}:0:${z}`, cube); } } // Рэйкаст для выбора блока const raycaster = new THREE.Raycaster(); const mouse = new THREE.Vector2(0, 0); // центр экрана function getBlockIntersection() { raycaster.setFromCamera(mouse, camera); const intersects = raycaster.intersectObjects([...blocks.values()]); return intersects[0] ?? null; } // Управление ходьбой const keys = {}; document.addEventListener("keydown", (e) => (keys[e.code] = true)); document.addEventListener("keyup", (e) => (keys[e.code] = false)); const velocity = new THREE.Vector3(); const speed = 10; const gravity = 30; let canJump = false; // Главный цикл const clock = new THREE.Clock(); function animate() { requestAnimationFrame(animate); const dt = Math.min(clock.getDelta(), 0.1); // Ходьба if (controls.isLocked) { velocity.x -= velocity.x * 10.0 * dt; velocity.z -= velocity.z * 10.0 * dt; velocity.y -= gravity * dt; const forward = keys["KeyW"] ? 1 : keys["KeyS"] ? -1 : 0; const strafe = keys["KeyD"] ? 1 : keys["KeyA"] ? -1 : 0; if (forward || strafe) { const dir = new THREE.Vector3(); controls.getDirection(dir); dir.y = 0; dir.normalize(); const right = new THREE.Vector3().crossVectors(dir, camera.up); velocity.addScaledVector(dir, forward * speed * dt); velocity.addScaledVector(right, strafe * speed * dt); } if (canJump && keys["Space"]) { velocity.y = 12; canJump = false; } controls.moveRight(velocity.x * dt); controls.moveForward(velocity.z * dt); camera.position.y += velocity.y * dt; // «коллизия» с землёй if (camera.position.y < 2) { velocity.y = 0; camera.position.y = 2; canJump = true; } } renderer.render(scene, camera); } animate(); // ЛКМ — удалить блок document.addEventListener("mousedown", (e) => { if (!controls.isLocked) return; const hit = getBlockIntersection(); if (!hit) return; if (e.button === 0) { // left click const key = keyFromPosition(hit.object.position); scene.remove(hit.object); blocks.delete(key); } else if (e.button === 2) { // right click // ставим новый блок на соседнюю позицию const normal = hit.face.normal; const pos = hit.object.position.clone().add(normal); const key = keyFromPosition(pos); // не ставить, если уже занят if (!blocks.has(key)) { const cube = makeCube(pos.x - 0.5, pos.y - 0.5, pos.z - 0.5); scene.add(cube); blocks.set(key, cube); } } }); // запрет контекстного меню для ПКМ document.addEventListener("contextmenu", (e) => e.preventDefault()); function keyFromPosition(v) { const x = Math.floor(v.x); const y = Math.floor(v.y); const z = Math.floor(v.z); return `${x}:${y}:${z}`; } // адаптация к ресайзу addEventListener("resize", () => { camera.aspect = innerWidth / innerHeight; camera.updateProjectionMatrix(); renderer.setSize(innerWidth, innerHeight); });

Как расширять дальше

ИдеяЧто менять
Разнообразные блокиИспользуйте THREE.MeshBasicMaterial с разными текстурами; храните тип блока в карте, обновляйте #blockInfo.
Сохранение мираСериализуйте blocks → JSON / IndexedDB, грузите при старте.
Генерация биомовПерлин-шум (noisejs) для высоты + карта биомов, создавайте блоки в цикле вместо плоскости.
Инвентарь и крафтДобавьте UI (HTML + CSS) и логику в JS (масив предметов, рецепты).
Мобы, физика»Подключите движок (Cannon.js, Ammo.js) или пишите простую логику столкновений и ИИ.

Успехов в доработке! Если понадобится помощь с конкретными функциями — спрашивайте.

Compartilhar esta Q&A