#javascript #three.js
Вопрос:
Предыстория вопроса
Я работаю над игрой, представляющей собой смесь Europa Universalis 4 и Age of Empires 3. Игра сделана на JavaScript и использует Three.js (r109) библиотека. На данный момент я создал случайно сгенерированную низкополигональную местность с деревьями и отражающей водой. В начале я хочу, чтобы в игре появился флот, представленный галеоном (на скриншоте ниже). Я хочу сделать так, чтобы, когда его вызовут на нерест, он выбрал случайное место в пределах воды. Водная сетка представлена полупрозрачной плоскостью размером с карту-с THREE.Reflector
объектом под ней. Рельеф также является плоскостью, но был изменен с помощью карты высоты симплексного шума.
вопрос
Как определить, пересекается ли позиция x и z с сеткой воды, а не с сеткой местности? THREE.Raycaster
кажется, это полезно для того, что я пытаюсь сделать, но я не хочу знать, есть ли лучшее решение. Если использование THREE.Raycaster
является лучшим вариантом, как бы я реализовал его для этой цели? Должен ли я создавать индивидуальность THREE.Raycaster
для каждого объекта, с которым я это делаю? Имейте в виду, что я не размещаю этот объект с помощью мыши, я хочу разместить его с помощью метода, который проверяет положение, как указано выше.
Ответ №1:
Трудно дать конкретный совет, ничего не зная о вашем коде, но похоже, что все, что вам нужно сделать, это создать список столкновений для ваших допустимых водных поверхностей, а затем проверить это, когда вы захотите что-то создать.
Здесь находится очень простой jsfiddle. Он создает сетку «земля» (зеленая) и сетку «вода» (синяя), добавляет сетку «вода» в переменную под названием collisionList. Затем он вызывает функцию порождения для координат по диагонали на обеих поверхностях. Функция использует raycaster, чтобы проверить, находятся ли координаты над сеткой «вода», и создает красный куб, если это так.
Вот код:
window.onload = function() {
var camera = null, land = null, water = null, renderer = null, lights;
var collisionList;
var d, n, scene = null, animID;
n = document.getElementById('canvas');
function load() {
var height = 600, width = 800;
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(60, width/height, 1, 1000);
camera.position.set(0, 0, -10);
camera.lookAt(new THREE.Vector3(0, 0, 0));
scene.add(camera);
lights = [];
lights[0] = new THREE.PointLight(0xffffff, 1, 0);
lights[1] = new THREE.PointLight(0xffffff, 1, 0);
lights[2] = new THREE.PointLight(0xffffff, 1, 0);
lights[0].position.set(0, 200, 0);
lights[1].position.set(100, 200, 100);
lights[2].position.set(-100, -200, -100);
scene.add(lights[0]);
scene.add(lights[1]);
scene.add(lights[2]);
water = new THREE.Mesh(new THREE.PlaneGeometry(7, 7, 10),
new THREE.MeshStandardMaterial({
color: 0x0000ff,
side: THREE.DoubleSide,
}));
water.position.set(0, 0, 0);
scene.add(water);
land = new THREE.Mesh(new THREE.PlaneGeometry(12, 12, 10),
new THREE.MeshStandardMaterial({
color: 0x00ff00,
side: THREE.DoubleSide,
}));
land.position.set(0, 0, 1);
scene.add(land);
renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);
n.appendChild(renderer.domElement);
collisionList = [ water ];
for(var i = -6; i < 6; i )
spawn(i);
animate();
}
function spawn(x) {
var dir, intersect, mesh, ray, v;
v = new THREE.Vector3(x, x, -1);
dir = new THREE.Vector3(0, 0, 1);
ray = new THREE.Raycaster(v, dir.normalize(), 0, 100);
intersect = ray.intersectObjects(collisionList);
if(intersect.length <= 0)
return;
mesh = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1, 1, 1, 1),
new THREE.MeshStandardMaterial({ color: 0xff0000 }));
mesh.position.set(x, x, 0);
scene.add(mesh);
}
function animate() {
if(!scene) return;
animID = requestAnimationFrame(animate);
render();
update();
}
function render() {
if(!scene || !camera || !renderer) return;
renderer.render(scene, camera);
}
function update() {
if(!scene || !camera) return;
}
load();
Что касается того, является ли это разумным способом сделать это, это действительно зависит от дизайна остальной части вашей игры.
Если ваш мир является procgen, то может быть более эффективным/менее подверженным ошибкам сначала генерировать точки появления (и любые другие «функциональные» части мира) и использовать их для создания географии, а не наоборот.
Комментарии:
1. Я заставил элементы вашей скрипки работать для моей игры. Идеальное решение для того, о чем я просил. Извините, что не дал свой код, я просто не думал, что это будет полезно из-за того, что я прошу быть довольно общим. Но все же вы дали мне ответ и решение, в которых я нуждался.