Create a new object in Three.js every x seconds and continuously move each object forward in the Z-axis direction

I am currently developing a Three.js endless runner game where the player controls a character dodging cars on a moving road. At this early stage of development, my main challenge is to make the hero character appear to be moving forward while creating the illusion that the cars are approaching the hero at a faster speed.

To achieve this effect, I decided to implement road strip objects that move towards the hero character's position (0, 0) at a specified velocity.

After successfully creating a road strip object and placing it at the back of the road (

RoadStrip.mesh.position.z = -5000;
), here is the code snippet:

// Code for creating a road strip object
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 to create a road strip
function createRoadStrip() {
    new objectRoadStrip();
    RoadStrip.position.y = -72.5;
    RoadStrip.position.z = -5000;

    scene.add(RoadStrip);
}

In the render() function, I can animate the road strip to move towards (0, 0) on the z axis by 10 units on each frame. Additionally, the road strip is removed from the scene once it reaches the hero character's position:

// Road strip animation in the render function
function render(){
    if (RoadStrip.position.z <= -150) {
        RoadStrip.position.z += 10;
    } else {
        scene.remove(RoadStrip);
    }

    renderer.render(scene, camera);
    requestAnimationFrame(render);
}

Furthermore, I have integrated the creation of a new road strip object every 10 seconds in the init() function:

// Creating a new road strip every 10 seconds
createRoadStrip();
setInterval( function() {
    createRoadStrip();
}, 10000);

While this approach simulates the desired effect, read the following section where I outline the actual problem and possible solutions.

The Problem

I aim to continuously spawn road strip objects every x seconds (e.g., 3 seconds) independently moving towards (0, 0) along the z axis. Once a road strip reaches (0, 0), it should be removed, while new road strips continue to spawn at the original position (z = -5000).

My Attempts / Solution Ideas

In exploring potential solutions, I considered pushing road strip objects to an array every x seconds and updating their positions in the array to achieve continuous movement. However, implementing this idea has proven to be challenging.

  1. Idea: Instead of using setInterval, push road strip objects to an array at intervals and update their positions.
  2. Possible solution help: Adjusting the interval for creating new road strips caused inconsistent movement patterns. Each road strip stops moving once a new one is created, disrupting the continuous motion effect.

If you have insights or solutions to help overcome this challenge, I would greatly appreciate your input. Thank you!

Examples of similar style games: First, Second.

Answer №1

Gratitude goes out to @prisoner849 for sharing a link to this thread. It led me to the solution for the issue at hand, and now I'm documenting my findings here for future reference!

While delving into the thread, I stumbled upon a link to this JSFiddle, which showcases a successful animation similar to what I was aiming for. I highly recommend dissecting the code from that JSFiddle to fully grasp how to create an endless runner effect.

Step-by-step Guide:

Instead of creating objects infinitely and animating them forward until they vanish upon reaching the end point (my initial assumption), the key is to create an array of objects and animate that array.

Here's the implementation:

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);
    }

}

The for loop defines i < 100 as my road requires numerous strips due to its length.

The line:

RoadStrip.position.set(0, -72.5, 0 - i * 1250);

assigns distinct positions to each strip, with 1250 representing the distance between each strip.

Following the object creation, you must animate them in the render() function. They should move along the Z axis, and an if statement is crucial to reset the strip's position upon reaching the endpoint, preventing endless object creation.

Animation Code:

// 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;
        }
    });
    renderer.render(scene, camera);
}

The line that moves each strip is:

RoadStrip.position.addScaledVector(direction, speed * delta);

More about .addScaledVector here, which is the essence of the strip animation.

The if statement checks if the strip reaches 10000 (the road's end), resetting its position to -10000 if so. The strip then moves back on the Z axis.

The forEach function iterates through each RoadStrip in the array for consistent animation. Individual animation is necessary to detect when a strip reaches the road's end.

Hoping this guide proves helpful!

Answer №2

One effective way to manage a scenario like this is to use a particle system approach. Instead of constantly adding and removing objects from the scene, you can create a predefined set of objects at the beginning. For example, if the player can only see 10 road stripes at a time, you can continuously move and update the positions of those 10 stripes. When a stripe goes out of view, it can be recycled at the start of the sequence. There may not be a ready-made solution that fits your exact needs, so you may need to design the update logic that works best for your game.

Here is an example of a custom particle system that operates in a similar manner, where particles are reused when they go out of scope. The number of particles in the system remains constant and can be adjusted by the user for testing purposes. A similar technique could be applied to manage an infinite set of stripes. You can view the code repository for this particle system here. While this implementation may be tailored to specific requirements, there are many other particle system implementations available that may suit your needs.

I hope this information is helpful.

https://i.sstatic.net/zaWy1.png

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

I am looking to utilize React and Next.js to map my array from an object. The component is a function employing hooks

I am attempting to map an array within an object and encountering some challenges. The structure of the object is as follows: const data = {data: (6) [{…}, {…}, {…}, {…}, {…}, {…}], page: 2, per_page: 6, total: 12, total_pages: 2} I have been ...

In search of assistance with a persistent react.js error plaguing my work

I keep encountering an error whenever I run npm start on a new project. Does anyone have any insight on how to resolve this issue? The problem might lie within the project dependency tree rather than being a bug in Create React App. Here is what you can ...

The form control is missing a specified name attribute, causing an error with the value accessor

<input type="email" class="form-control passname" [(ngModel)]="emailID" name="Passenger Email ID" placeholder="email" required pattern="^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$"/> <div class="shake-tool ...

Creating a mouse drawing in three.js that appears at a consistent distance from the camera plane

I am working on developing a 3D "doodler" that is open sourced. It allows for free-hand drawing as well as drawing at the intersection of previous line segments, which is indicated by a plane facing the camera and orbit control projection. I'm curren ...

Using jQuery to validate the existence of a link

Within my pagination div, I have links to the previous page and next page. The link to the previous page is structured as follows: <span id="previous"><a href="www.site.com/page/1" >Previous</a>. However, on the first page, there will be ...

Executing a callback in Node.js after a loop is complete

As a newcomer to Node, I have been facing difficulties with the asynchronous nature of the platform while attempting to append data in a for loop of API calls. function emotionsAPI(data, next){ for(let url in data) { if(data.hasOwnProperty(url ...

Data Extracted from JSON Response to Save as Variable

I'm currently facing an issue with retrieving an ID from a JSON call and I'm unsure of what the problem might be. I have set up a Callback function to assign a global variable, but it doesn't seem to be working as expected. OBJECTIVE: To qu ...

For every iteration, verify the presence of the image

I am currently working on a foreach loop to iterate over the data returned by an ajax call. Within this loop, I am checking if each record has an associated image. Code for Checking Image Existence: function checkImageExists(url, callback) { var img ...

Attempting to replace the checkbox image resulted in no changes

<?php require 'includes/configs.inc.php'; ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title><?php $site_name ?></titl ...

Having trouble closing my toggle and experiencing issues with the transition not functioning properly

Within my Next.js project, I have successfully implemented a custom hook and component. The functionality works smoothly as each section opens independently without interfering with others, which is great. However, there are two issues that I am facing. Fi ...

What is the best way to transfer the window object from the current tab to the extension?

I am looking to retrieve user storage data (local and session) from a specific tab, similar to what is shown in this app (see screen below). From my understanding, I need to access the window object of the active tab. While I have obtained the object, I a ...

Issue with the functionality of Jquery scrolling through thumbnail images animation

I have encountered an issue related to the previous question that I posted here. After successfully implementing the provided solution, it initially seemed to be working. However, when I clicked the next button and reached the 3rd click, the jQuery scrolli ...

Displaying entries of input data

I have an application that includes a modal window with filters, but I am looking to add another type of filter. However, I am struggling with implementing it in React and would appreciate any help with the code or recommended links. Essentially, I want t ...

Encountered an issue when attempting to access a file on the desktop using Node.js

Here is the code I am using to read a simple file from my desktop: module.exports = function (app) { app.get('/aa', function(req, res) { fs = require('fs'); fs.readFile('‪C:\\Users\\t5678 ...

Trouble locating the ID selector within a nested Backbone view

Within this code snippet, I am utilizing the element controller pattern to display a collection of products. The main view template is rendering properly, showing all elements and the div selector "#cart-wrapper". However, when the main view calls the nest ...

What is the best way to delete a property from an object in an array using Mongoose? This is crucial!

Doc - const array = [ { user: new ObjectId("627913922ae9a8cb7a368326"), name: 'Name1', balance: 0, _id: new ObjectId("627913a92ae9a8cb7a36832e") }, { user: new ObjectId("6278b20657cadb3b9a62a50e"), name: 'Name ...

How to ensure your content is always visible on Mobile Safari iOS 8 by making sure it stays

Although minimal-ui is no longer supported on iOS8, I've encountered an issue with some fixed content at the bottom of a webpage. The page height is set to 100vh to cover the entire viewport, but some of the content at the bottom is extending below t ...

Alert displayed on console during transition from MaterialUI lab

Whenever I try to run my MUI application, an error pops up in the console It seems you may have forgotten to include the ref parameter in your forwardRef render function. import { LoadingButton } from "@mui/lab"; const LoadData = ({loading,sig ...

Employ the 'this' attribute within _.map

I am facing an issue where I need to call a setState function within a _.map loop in React. However, the loop is losing the reference to 'this' and therefore I cannot use setState as this becomes undefined. cargaDinamica(){ _.map(this.stat ...

What is the process for updating JSON using TextFields?

I am currently facing an issue with my TextFields displayed within a material-ui dialog. These TextFields are initially populated by JSON data, which you can see in the example below. The problem is that once the TextFields are populated, I am unable to up ...