9 days ago

попросил дипсик сделать 3D игру и ниче не получилось код будет в артикле


<!DOCTYPE html>

<html lang="ru">

<head>

<meta charset="UTF-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">

<title>3D Космический сборщик кристаллов</title>

<style>

body { margin: 0; overflow: hidden; font-family: 'Arial', sans-serif; }

#score {

position: absolute;

top: 20px;

right: 20px;

background: rgba(0,0,0,0.75);

color: gold;

padding: 12px 24px;

border-radius: 40px;

font-size: 28px;

font-weight: bold;

font-family: monospace;

backdrop-filter: blur(5px);

z-index: 10;

pointer-events: none;

letter-spacing: 2px;

box-shadow: 0 0 20px rgba(0,0,0,0.5);

}

#controls {

position: absolute;

bottom: 20px;

left: 20px;

background: rgba(0,0,0,0.6);

color: #ccc;

padding: 10px 18px;

border-radius: 20px;

font-size: 14px;

font-family: monospace;

backdrop-filter: blur(4px);

z-index: 10;

pointer-events: none;

}

#win-message {

position: absolute;

top: 50%;

left: 50%;

transform: translate(-50%, -50%);

background: rgba(0,0,0,0.9);

color: gold;

padding: 30px 50px;

border-radius: 30px;

text-align: center;

font-size: 32px;

font-weight: bold;

backdrop-filter: blur(10px);

z-index: 20;

display: none;

border: 2px solid gold;

white-space: nowrap;

font-family: monospace;

}

#restart {

margin-top: 20px;

background: #4CAF50;

border: none;

padding: 12px 30px;

font-size: 20px;

border-radius: 50px;

cursor: pointer;

font-weight: bold;

color: white;

transition: 0.2s;

}

#restart:hover { background: #45a049; transform: scale(1.05); }

@media (max-width: 600px) {

#score { font-size: 18px; padding: 8px 16px; top: 10px; right: 10px; }

#controls { font-size: 10px; bottom: 10px; left: 10px; }

#win-message { font-size: 20px; padding: 20px 30px; white-space: normal; width: 80%; }

}

</style>

</head>

<body>

<div id="score">💎 0 / 24</div>

<div id="controls">🎮 WASD или стрелки — двигать корабль | Собирай кристаллы</div>

<div id="win-message">

✨ ПОБЕДА! ✨<br>

<span id="final-score"></span><br>

<button id="restart">🔄 Играть снова</button>

</div>

<script type="importmap">

{

"imports": {

"three": "https://unpkg.com/[email protected]/build/three.module.js",

"three/addons/": "https://unpkg.com/[email protected]/examples/jsm/"

}

}

</script>

<script type="module">

import * as THREE from 'three';

// --- СЦЕНА, КАМЕРА, РЕНДЕР ---

const scene = new THREE.Scene();

scene.background = new THREE.Color(0x050b2a);

scene.fog = new THREE.FogExp2(0x050b2a, 0.008);

const camera = new THREE.PerspectiveCamera(55, window.innerWidth / window.innerHeight, 0.1, 1000);

camera.position.set(0, 6, 12);

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);

// --- ОСВЕЩЕНИЕ ---

// Амбиент

const ambient = new THREE.AmbientLight(0x404080);

scene.add(ambient);

// Основной направленный свет

const dirLight = new THREE.DirectionalLight(0xffffff, 1.2);

dirLight.position.set(5, 12, 8);

dirLight.castShadow = true;

dirLight.receiveShadow = true;

dirLight.shadow.mapSize.width = 1024;

dirLight.shadow.mapSize.height = 1024;

dirLight.shadow.camera.near = 0.5;

dirLight.shadow.camera.far = 25;

dirLight.shadow.camera.left = -10;

dirLight.shadow.camera.right = 10;

dirLight.shadow.camera.top = 10;

dirLight.shadow.camera.bottom = -10;

scene.add(dirLight);

// Заполняющий снизу

const fillLight = new THREE.PointLight(0x88aaff, 0.4);

fillLight.position.set(0, -3, 0);

scene.add(fillLight);

// Динамический свет на игроке

const playerGlow = new THREE.PointLight(0xffaa66, 0.9, 15);

playerGlow.castShadow = false;

scene.add(playerGlow);

// --- ЗВЁЗДЫ ---

const starGeo = new THREE.BufferGeometry();

const starCount = 2000;

const starPos = new Float32Array(starCount * 3);

for (let i = 0; i < starCount; i++) {

starPos[i*3] = (Math.random() - 0.5) * 400;

starPos[i*3+1] = (Math.random() - 0.5) * 150;

starPos[i*3+2] = (Math.random() - 0.5) * 150 - 70;

}

starGeo.setAttribute('position', new THREE.BufferAttribute(starPos, 3));

const stars = new THREE.Points(starGeo, new THREE.PointsMaterial({ color: 0xffffff, size: 0.2, transparent: true, opacity: 0.7 }));

scene.add(stars);

// Декоративная сетка пола

const grid = new THREE.GridHelper(40, 20, 0x88aaff, 0x3366aa);

grid.position.y = -2.8;

grid.material.transparent = true;

grid.material.opacity = 0.4;

scene.add(grid);

// Красивый светящийся круг под игроком

const ringFloor = new THREE.Mesh(

new THREE.RingGeometry(1.2, 1.8, 32),

new THREE.MeshStandardMaterial({ color: 0x44aaff, emissive: 0x2266aa, transparent: true, opacity: 0.5, side: THREE.DoubleSide })

);

ringFloor.rotation.x = -Math.PI / 2;

ringFloor.position.y = -2.7;

scene.add(ringFloor);

// --- МОДЕЛЬ ИГРОКА (улучшенный корабль) ---

const ship = new THREE.Group();

// Корпус - обтекаемый

const bodyGeo = new THREE.CylinderGeometry(0.65, 0.85, 1.3, 24);

const bodyMat = new THREE.MeshStandardMaterial({ color: 0x3a86ff, metalness: 0.85, roughness: 0.25, emissive: 0x001a44 });

const bodyMesh = new THREE.Mesh(bodyGeo, bodyMat);

bodyMesh.castShadow = true;

bodyMesh.receiveShadow = true;

bodyMesh.position.y = 0;

ship.add(bodyMesh);

// Нос (конус)

const noseGeo = new THREE.ConeGeometry(0.65, 1.0, 24);

const noseMat = new THREE.MeshStandardMaterial({ color: 0xffaa55, metalness: 0.9, emissive: 0x442200 });

const noseMesh = new THREE.Mesh(noseGeo, noseMat);

noseMesh.position.z = 0.85;

noseMesh.position.y = 0.1;

noseMesh.castShadow = true;

ship.add(noseMesh);

// Крылья

const wingGeo = new THREE.BoxGeometry(1.5, 0.12, 0.6);

const wingMat = new THREE.MeshStandardMaterial({ color: 0x2a6eff, metalness: 0.7 });

const leftWing = new THREE.Mesh(wingGeo, wingMat);

leftWing.position.set(-0.9, -0.15, 0.2);

leftWing.castShadow = true;

const rightWing = new THREE.Mesh(wingGeo, wingMat);

rightWing.position.set(0.9, -0.15, 0.2);

rightWing.castShadow = true;

ship.add(leftWing);

ship.add(rightWing);

// Хвостовые стабилизаторы

const tailGeo = new THREE.BoxGeometry(0.4, 0.5, 0.3);

const tailMat = new THREE.MeshStandardMaterial({ color: 0xff8844 });

const tail = new THREE.Mesh(tailGeo, tailMat);

tail.position.set(0, 0.3, -0.65);

tail.castShadow = true;

ship.add(tail);

// Свечение вокруг корабля (эффект двигателя)

const engineGlow = new THREE.PointLight(0xff6600, 0.8, 8);

engineGlow.position.set(0, -0.1, -0.9);

ship.add(engineGlow);

// Партиклы из двигателя (маленькие сферы)

const engineExhaust = new THREE.Mesh(

new THREE.SphereGeometry(0.2, 8, 8),

new THREE.MeshStandardMaterial({ color: 0xff8844, emissive: 0xff4400, transparent: true, opacity: 0.7 })

);

engineExhaust.position.set(0, -0.1, -1.0);

ship.add(engineExhaust);

ship.position.y = -1.6;

scene.add(ship);

let shipPos = { x: 0, z: 0 };

const speed = 6.2;

const keys = { w: false, s: false, a: false, d: false, ArrowUp: false, ArrowDown: false, ArrowLeft: false, ArrowRight: false };

// --- КРИСТАЛЛЫ (улучшенные модели) ---

class Crystal {

constructor(x, z) {

this.group = new THREE.Group();

// Основной кристалл - октаэдр с блеском

const geom = new THREE.OctahedronGeometry(0.65);

const material = new THREE.MeshStandardMaterial({ color: 0xff44cc, metalness: 0.9, roughness: 0.2, emissive: 0x551133 });

this.core = new THREE.Mesh(geom, material);

this.core.castShadow = true;

this.group.add(this.core);

// Внутреннее свечение

const innerGlow = new THREE.Mesh(

new THREE.SphereGeometry(0.45, 16, 16),

new THREE.MeshBasicMaterial({ color: 0xff88dd, transparent: true, opacity: 0.5 })

);

this.group.add(innerGlow);

// Вращающиеся кольца

const ringGeo = new THREE.TorusGeometry(0.85, 0.06, 24, 60);

const ringMat = new THREE.MeshStandardMaterial({ color: 0xffaa77, emissive: 0x663300 });

this.ring = new THREE.Mesh(ringGeo, ringMat);

this.ring.rotation.x = Math.PI / 2;

this.group.add(this.ring);

// Второе кольцо под углом

const ring2Geo = new THREE.TorusGeometry(0.75, 0.05, 24, 60);

const ring2Mat = new THREE.MeshStandardMaterial({ color: 0xff88aa, emissive: 0x441133 });

this.ring2 = new THREE.Mesh(ring2Geo, ring2Mat);

this.ring2.rotation.z = Math.PI / 3;

this.group.add(this.ring2);

this.group.position.set(x, -1.8, z);

scene.add(this.group);

this.spinSpeed = 0.015 + Math.random() * 0.02;

this.floatOffset = Math.random() * Math.PI * 2;

}

update(time) {

this.group.rotation.y += this.spinSpeed;

this.group.rotation.x = Math.sin(time * 2 + this.floatOffset) * 0.2;

this.ring.rotation.z += 0.03;

this.ring2.rotation.x += 0.02;

this.ring2.rotation.y += 0.01;

}

}

let crystals = [];

let score = 0;

const totalCrystals = 24;

const scoreDiv = document.getElementById('score');

const winDiv = document.getElementById('win-message');

const finalSpan = document.getElementById('final-score');

function spawnCrystals() {

crystals.forEach(c => scene.remove(c.group));

crystals = [];

for (let i = 0; i < totalCrystals; i++) {

let x, z, ok;

do {

x = (Math.random() - 0.5) * 26;

z = (Math.random() - 0.5) * 22;

ok = Math.abs(x) < 2.8 && Math.abs(z) < 2.8 ? false : true;

} while (!ok);

crystals.push(new Crystal(x, z));

}

}

function updateScoreUI() {

scoreDiv.innerHTML = `💎 ${score} / ${totalCrystals}`;

if (score === totalCrystals) {

finalSpan.innerHTML = `Ты собрал все ${totalCrystals} кристаллов! ✨`;

winDiv.style.display = 'block';

}

}

// Эффект сбора (вспышка + частицы)

function createCollectEffect(pos) {

const particleCount = 30;

const particles = [];

for (let i = 0; i < particleCount; i++) {

const particle = new THREE.Mesh(

new THREE.SphereGeometry(0.1, 6, 6),

new THREE.MeshStandardMaterial({ color: 0xffaa66, emissive: 0xff6600 })

);

particle.position.copy(pos);

particle.userData = {

vel: new THREE.Vector3(

(Math.random() - 0.5) * 3,

Math.random() * 2.5,

(Math.random() - 0.5) * 3

),

life: 1.0

};

scene.add(particle);

particles.push(particle);

}

function animateParts() {

let alive = false;

particles.forEach(p => {

if (p.userData.life > 0) {

alive = true;

p.userData.life -= 0.05;

p.material.opacity = p.userData.life;

p.material.transparent = true;

p.position.x += p.userData.vel.x * 0.12;

p.position.y += p.userData.vel.y * 0.12;

p.position.z += p.userData.vel.z * 0.12;

p.userData.vel.y -= 0.1;

p.scale.setScalar(p.userData.life);

} else {

scene.remove(p);

}

});

if (alive) requestAnimationFrame(animateParts);

}

animateParts();

}

// Проверка столкновений

function checkCollisions() {

const shipWorld = ship.position;

for (let i = 0; i < crystals.length; i++) {

const c = crystals[i];

const dx = shipWorld.x - c.group.position.x;

const dz = shipWorld.z - c.group.position.z;

const dist = Math.sqrt(dx*dx + dz*dz);

if (dist < 1.2) {

createCollectEffect(c.group.position);

scene.remove(c.group);

crystals.splice(i,1);

score++;

updateScoreUI();

i--;

}

}

}

// --- УПРАВЛЕНИЕ (ИСПРАВЛЕНО!) ---

window.addEventListener('keydown', (e) => {

const key = e.key;

if (keys.hasOwnProperty(key)) {

keys[key] = true;

e.preventDefault();

}

});

window.addEventListener('keyup', (e) => {

const key = e.key;

if (keys.hasOwnProperty(key)) keys[key] = false;

});

let lastTime = performance.now();

function updateMovement(delta) {

let moveX = 0, moveZ = 0;

if (keys.w || keys.ArrowUp) moveZ -= 1;

if (keys.s || keys.ArrowDown) moveZ += 1;

if (keys.a || keys.ArrowLeft) moveX -= 1;

if (keys.d || keys.ArrowRight) moveX += 1;

if (moveX !== 0 || moveZ !== 0) {

const len = Math.hypot(moveX, moveZ);

moveX /= len;

moveZ /= len;

}

let newX = ship.position.x + moveX * speed * delta;

let newZ = ship.position.z + moveZ * speed * delta;

// Границы арены

newX = Math.min(14, Math.max(-14, newX));

newZ = Math.min(12, Math.max(-12, newZ));

ship.position.x = newX;

ship.position.z = newZ;

// Поворот корабля

if (moveX !== 0 || moveZ !== 0) {

const angle = Math.atan2(moveX, moveZ);

ship.rotation.y = angle;

}

// Наклоны и динамика

ship.rotation.z = moveX * 0.35;

ship.rotation.x = -moveZ * 0.25;

// Эффект двигателя (пульсация)

const intensity = (Math.abs(moveX) + Math.abs(moveZ)) * 0.8 + 0.3;

engineGlow.intensity = 0.6 + intensity * 0.8;

// Световой шар следует за игроком

playerGlow.position.set(ship.position.x, -1, ship.position.z);

// Камера плавно следует

const targetCam = {

x: ship.position.x * 0.4,

y: 6 + Math.abs(ship.position.x) * 0.08,

z: ship.position.z + 7

};

camera.position.x += (targetCam.x - camera.position.x) * 0.08;

camera.position.y += (targetCam.y - camera.position.y) * 0.08;

camera.position.z += (targetCam.z - camera.position.z) * 0.08;

camera.lookAt(ship.position);

// Кольцо под игроком

ringFloor.position.x = ship.position.x;

ringFloor.position.z = ship.position.z;

}

// --- АНИМАЦИИ ---

let time = 0;

function animateStarsAndEffects() {

time += 0.016;

stars.rotation.y += 0.0008;

stars.rotation.x += 0.0004;

// Мерцание выхлопа

const exhaustMesh = ship.children.find(c => c.geometry && c.position.z === -1.0);

if (exhaustMesh) {

exhaustMesh.scale.setScalar(0.8 + Math.sin(Date.now() * 0.02) * 0.3);

}

}

// --- ПЕРЕЗАПУСК ---

document.getElementById('restart').addEventListener('click', () => {

// очистить старые кристаллы

crystals.forEach(c => scene.remove(c.group));

crystals = [];

score = 0;

ship.position.set(0, -1.6, 0);

camera.position.set(0, 6, 12);

ship.rotation.set(0,0,0);

spawnCrystals();

updateScoreUI();

winDiv.style.display = 'none';

});

// --- ЗАПУСК ---

spawnCrystals();

updateScoreUI();

function gameLoop() {

const now = performance.now();

let delta = Math.min(0.033, (now - lastTime) / 1000);

lastTime = now;

updateMovement(delta);

checkCollisions();

crystals.forEach(c => c.update(time));

animateStarsAndEffects();

renderer.render(scene, camera);

requestAnimationFrame(gameLoop);

}

gameLoop();

window.addEventListener('resize', () => {

camera.aspect = window.innerWidth / window.innerHeight;

camera.updateProjectionMatrix();

renderer.setSize(window.innerWidth, window.innerHeight);

});

console.log('✅ Игра запущена! Управление WASD / стрелки работает');

</script>

</body>

</html>



0 comments

Loading...

Next up

This Satuday we invite to watch another #speedpainting of our artist Daniel Faiad.

How great is this scene of #Pecaminosa?

#ScreenShotSaturday | #IndieDev | #DigitalArt

"Thanks guys for endless hours of fun." 👍

(My first fan art. Read the article, please.)

#sonic #mario #photoshop

Here's a peaceful little forest scene for this #screenshotsaturday, from the beginning of the game.

Enemies can also suddenly spawn through Realm Rifts. These Rift Spawns are going to be stronger than the ones wandering around. TBD on the enemies... #screenshotsaturday #godstear #madewithunity

Another house i made long time ago.

Today I was setting up the location of the first boss. His name is "Father" and he is the first of the Patagonians. His task is to guard the road to the House.🛡🗡 Bookmark pre-launch page🔖🔖🔖

https://www.kickstarter.com/projects/rdvindiegame/the-patagonian…

Shadow The Hedgehog X pixel art

The whole squad is here!

Interested? Follow me!

Microsoft Windows XP Unprofessional (windows logo prototype)

a drawing I did because I was bored😪. But I love how it turned out.😊