我正在使用Three.js制作无尽的亚军风格游戏。游戏的场景和想法的基本设置是一条漫长的道路,汽车向你走来,你必须躲避。我仍然处于创造这个游戏的早期阶段,所以我的第一个问题是我需要英雄角色(谁正在躲避汽车)看起来他正在向前移动,同时让汽车看起来像他们正朝着英雄角色移动(更快)。
我的想法是创建道路条形物体(道路中间的白线),然后让它们以一定的速度移动到(0,0)的英雄角色。
我已经成功创建了一个路障对象并将其定位在道路的最后面(RoadStrip.mesh.position.z = -5000;
)。这是我的代码:
var objectRoadStrip = function() {
this.mesh = new THREE.Object3D();
this.mesh.name = "roadStrip";
geomRoadStrip = new THREE.BoxGeometry(20, 11, 300);
matRoadStrip = new THREE.MeshPhongMaterial({color: Colors.white});
RoadStrip = new THREE.Mesh(geomRoadStrip, matRoadStrip);
RoadStrip.name = 'roadStripName';
this.mesh.add(RoadStrip);
}
function createRoadStrip() {
new objectRoadStrip();
RoadStrip.position.y = -72.5;
RoadStrip.position.z = -5000;
scene.add(RoadStrip);
}
在render()
函数中,循环遍历每一帧并且最后调用以确保相机和场景每帧更新的函数,我能够沿{{1}向前成功移动此条带每次z
被调用时,10
轴都会被调整。我还添加了一些代码,以便在render()
触摸(0,0)时,它会从场景中删除。见下文:
RoadStrip
我还将以下代码添加到function render(){
// moves RoadStrip towards (0,0). When it reaches z = -150, remove that strip from the scene
if (RoadStrip.position.z <= -150) {
RoadStrip.position.z += 10;
} else {
scene.remove(RoadStrip);
}
renderer.render(scene, camera);
requestAnimationFrame(render);
}
函数中,该函数在创建场景时创建init()
,并且每10秒继续创建一个RoadStrip
(大致每次都是RoadStrip
到达(0,0)。
RoadStrip
这类似于我想要的效果,但请阅读下面的问题部分,我会解释我真正需要的内容。
问题
我需要每隔x秒产生一个createRoadStrip();
setInterval( function() {
createRoadStrip();
}, 10000);
(一旦我让它工作,仍然要决定,但现在让我们说3秒)。每个RoadStrip
需要独立地{(1}}移动到(0,0)。当RoadStrip
实例到达(0,0)时,它应该从场景中删除,但是其他z += 10
应该继续生成,而不是每3秒在原始位置(RoadStrip
)。
我的尝试/解决方案想法
我已经对此进行了大量阅读,通过其他人的代码搜索无尽的亚军游戏以及阅读SO答案,但似乎没有任何效果。以下是我尝试过的一些事情,或者我认为可行的一些事情,但我做得不对/不好好理解:
RoadStrips
内调用z = -5000
函数,而是每隔3秒将一个createRoadStrip()
对象推送到一个数组,然后调用该数组然后按setInterval
向RoadStrip
轴移动数组。z
更改为少于2秒而不是10秒。这导致+= 10
按预期在setInterval
轴上移动2秒,但当然,在2秒后产生了另一个RoadStrip
,因此第一个Z
停止了沿着RoadStrip
轴移动,新的移动(也持续2秒),这个过程无限重复。这非常接近我的需要,但我需要每个RoadStrip
继续移动,并在到达(0,0)时从场景中移除感谢您抽出宝贵时间阅读我的问题,我期待您的解决方案!
答案 0 :(得分:1)
感谢@ prisoner849和他对this线程的链接,我设法找到了问题的解决方案,所以我在这里为所有遇到同样问题的人写一个答案!
我通读了这个帖子并找到了this JSFiddle的链接,其中包含了一个类似于我想要实现的动画的成功动画,我强烈建议完全研究that JSFiddle的代码了解如何创造无尽的跑步效果。
以下是如何执行此操作的详细说明:
不是无限地创建对象并让它们向前动画直到它们到达终点并消失(就像我原先认为的那样是正确的解决方案),你必须创建一个对象数组并对其进行动画处理。
以下是我执行此操作的代码:
var roadStripArray = []
function objectRoadStrip() {
for (var i = 0; i < 100; i++) {
geomRoadStrip = new THREE.BoxGeometry(20, 11, 500);
matRoadStrip = new THREE.MeshPhongMaterial({color: Colors.white});
RoadStrip = new THREE.Mesh(geomRoadStrip, matRoadStrip);
RoadStrip.position.set(0, -72.5, -150 - i * 1250);
RoadStrip.receiveShadow = true;
scene.add(RoadStrip);
roadStripArray.push(RoadStrip);
}
}
for
循环的代码为i < 100
,因为我的路很长,因此需要大量的条带
此代码:
RoadStrip.position.set(0, -72.5, 0 - i * 1250);
将每个条带的位置设置为彼此不同,数字1250
是每个条带之间的距离
创建对象后,您必须在render()
函数中为它们设置动画。您必须将它们设置为沿Z
轴移动,然后创建一个if
语句,其中显示&#34;如果任何条带到达终点(您希望它消失的位置),请重置它#39;回到起点的位置(即我的道路起点)。这意味着您不断循环遍历对象数组,因此无法无限创建它们。
以下是为条带设置动画的代码:
// loop that runs every frame to render scene and camera
var clock = new THREE.Clock();
var time = 0;
var delta = 0;
var direction = new THREE.Vector3(0, 0, 1);
var speed = 2000; // units a second - 2 seconds
function render(){
requestAnimationFrame(render);
delta = clock.getDelta();
time += delta;
roadStripArray.forEach(function(RoadStrip){
RoadStrip.position.addScaledVector(direction, speed * delta);
if (RoadStrip.position.z >= 10000) {
RoadStrip.position.z = -10000;
} else {
}
});
renderer.render(scene, camera);
}
移动每个条带的代码是:
RoadStrip.position.addScaledVector(direction, speed * delta);
您可以阅读有关.addScaledVector here的更多信息,但实际上这是为条带设置动画的代码。
if
语句然后检查条带是否触及10000
(即道路的尽头),如果是,则将该条带的位置设置为-10000
。然后该条带沿着Z
轴向末端移动。
我们将这一切包装在forEach
函数中,以循环遍历数组中的每个RoadStrip
,并以相同的方式为它们设置动画。我们需要单独制作动画,以便我们可以检测到其中一个到达路的尽头。
谢谢,希望这有帮助!
答案 1 :(得分:0)
通常这种场景最好采用某种类似粒子系统的方法处理:你不要在场景中连续插入/删除对象,而是在初始化期间创建一组对象,让我们说玩家一次只能看到10条道路条纹,你的游戏逻辑总是移动那10条条纹,根据需要更新位置,一旦条带离开视野,它就会在开始时再循环,依此类推。我不认为您会找到一个完全符合您要求的固定解决方案,您需要提供最适合您游戏的更新逻辑。
我有自定义粒子系统there的示例。一旦粒子超出范围,当系统需要发射新粒子时,它就可用于系统。池中的粒子数总是不变的,用户可以在此定义,仅用于测试目的。可以使用类似的方法来操纵无限条纹。该代码的repo可以在https://github.com/leefsmp/Particle-System获得,但你可以找到许多其他的粒子系统实现,这个实现有点特定于我的需求。
希望有所帮助。