javascript - 如何检测 X 和 Z 位置是否与某个网格相交(不使用鼠标)?- 三.js
问题描述
问题背景
我正在开发一款混合了欧陆风云 4 和帝国时代 3 的游戏。该游戏是用JavaScript制作的,并使用Three.js (r109)库。截至目前,我已经用树木和反射水随机生成了低多边形地形。一开始我希望游戏生成一个海军,以一艘大帆船为代表(在下面的屏幕截图中)。我想这样做,所以当它被调用产卵时,它会在水的范围内选择一个随机位置。水网格由跨越地图大小的半透明平面THREE.Reflector
表示 -其下方有一个对象。地形也是一个平面,但已使用SimplexNoise高度图进行了更改。
问题
如何检测x和z位置是否与水网格而不是地形网格相交? THREE.Raycaster
似乎对我想做的事情很有用,但我不知道是否有更好的解决方案。如果使用 THREE.Raycaster
是最好的选择,我将如何为此目的实施它?THREE.Raycaster
我应该为我正在做的每一个对象创建一个个体吗?请记住,我不是用鼠标放置这个对象,我想用一种如上所述检查位置的方法来放置它。
解决方案
在对代码一无所知的情况下很难给出具体的建议,但听起来你需要做的就是为你的有效水面创建一个碰撞列表,然后在你想要生成一些东西时检查它。
一个非常简单的 jsfiddle 在这里。它创建一个“陆地”网格(绿色)和一个“水”网格(蓝色),将“水”网格添加到一个名为collisionList的变量中。然后它调用一个spawn函数来获取两个表面的对角坐标。该函数使用 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,那么首先生成生成点(以及世界的任何其他“功能”部分)并使用它来生成地理而不是相反的方式可能会更有效/更不容易出错。
推荐阅读
- office-ui-fabric - 如何将 OfficeUI Fabric 全局排版规则与 officeui Fabric React 应用程序一起使用?
- java - Java Spring RestFull API
- kubernetes - 我可以用更智能的 nginx 配置替换 AKS k8s 内的微服务吗?
- python - 编写一个兼容 python 2 和 3 的异步协程
- r - gtrends r 包 - 随时间变化的点击次数有时会发生变化
- python - 以 'rb' 模式打开一个 csv 文件并对其进行迭代
- c++ - 插入数据后 C++ 映射为空。
- angular - 使用 AppComponent 以外的其他组件启动应用程序时面临问题
- android-studio - android模拟器完成退出代码0
- android - 创建 apk 文件时我应该选择多少个受支持的架构