我正在使用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)时将其从场景中删除


感谢您抽出宝贵的时间阅读我的问题,期待您的解决方案!

类似风格游戏的示例:FirstSecond

最佳答案

感谢@ 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,并以相同的方式为它们设置动画。我们需要分别对它们进行动画处理,以便我们可以检测其中之一何时到达路的尽头。

谢谢,希望对您有所帮助!

10-05 22:33