我正在使用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()
函数(该函数循环遍历每帧并最后一次调用以确保相机和场景更新每帧)中,我能够成功地将该条带沿z
轴沿10
向前移动每次调用render()
时。我还添加了一些代码,以便在RoadStrip
触摸(0,0)时将其从场景中删除。请参阅以下内容: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()
函数添加了以下代码,该函数在创建场景时创建了RoadStrip
,并继续每10秒创建一次RoadStrip
(大约每次RoadStrip
达到(0,0 )。createRoadStrip();
setInterval( function() {
createRoadStrip();
}, 10000);
这与我要达到的效果类似,但是请阅读下面的“问题”部分,在其中解释我的真正需求。
问题
我需要连续每x秒产生一个
RoadStrip
秒(一旦确定,它仍然可以决定,但是现在可以说3秒)。每个RoadStrip
需要分别通过z += 10
向(0,0)移动。当RoadStrip
实例达到(0,0)时,应将其从场景中删除,但无论每3秒在原始位置(RoadStrips
),其他z = -5000
都应继续生成。我的尝试/解决方案构想
我已经做了大量的阅读工作,从其他人无休止的亚军游戏中寻找代码,并阅读了SO答案,但似乎没有任何效果。以下是我尝试过的一些方法,或者一些我认为可行的方法,但我做得不好/对以下内容没有很好的理解:
想法:不用在
createRoadStrip()
中调用setInterval
函数,而是每3秒将RoadStrip
对象推到一个数组,然后调用该数组并沿z
轴将数组移动+= 10
。可能的解决方案帮助:我尝试将
setInterval
更改为少于2秒而不是10秒。这导致RoadStrip
像预期的那样沿Z
轴移动2秒钟,但是,当然,在2秒钟后又产生了另一个RoadStrip
,因此第一个RoadStrip
停止沿Z
轴移动,而新的反而做了(也持续了2秒钟),并且此过程无限重复。这非常接近我的需要,但是我需要每个RoadStrip
继续移动,并在到达(0,0)时将其从场景中删除感谢您抽出宝贵的时间阅读我的问题,期待您的解决方案!
类似风格游戏的示例:First,Second。
最佳答案
感谢@ 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
语句,其中说:“如果任何条带到达终点(您希望其消失的位置),请将其位置重新设置为起点(即(对于我来说,这是道路的起点)。这意味着您不断循环遍历对象数组,因此不会无限创建它们。这是带状动画的代码:
// 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
,并以相同的方式为它们设置动画。我们需要分别对它们进行动画处理,以便我们可以检测其中之一何时到达路的尽头。谢谢,希望对您有所帮助!