Three.js - 每x秒生成一个对象并向前移动每个对象(沿Z)

时间:2018-02-06 11:42:52

标签: javascript three.js

我正在使用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答案,但似乎没有任何效果。以下是我尝试过的一些事情,或者我认为可行的一些事情,但我做得不对/不好好理解:

  1. 想法:不是在RoadStrips内调用z = -5000函数,而是每隔3秒将一个createRoadStrip()对象推送到一个数组,然后调用该数组然后按setIntervalRoadStrip轴移动数组。
  2. 可能的解决方案帮助:我尝试将z更改为少于2秒而不是10秒。这导致+= 10按预期在setInterval轴上移动2秒,但当然,在2秒后产生了另一个RoadStrip,因此第一个Z停止了沿着RoadStrip轴移动,新的移动(也持续2秒),这个过程无限重复。这非常接近我的需要,但我需要每个RoadStrip继续移动,并在到达(0,0)时从场景中移除
  3. 感谢您抽出宝贵时间阅读我的问题,我期待您的解决方案!

    类似风格游戏的示例: FirstSecond

2 个答案:

答案 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获得,但你可以找到许多其他的粒子系统实现,这个实现有点特定于我的需求。

希望有所帮助。

enter image description here