Project in Three.js where the camera remains focused on the object while in a top-down perspective

I am currently working on developing a top-down game using Three.js, inspired by classic arcade games like Frogger. I am facing challenges in ensuring that the camera stays centered on the main character as it moves across the screen. I am currently utilizing MapControls.js for key controls, but I am encountering issues where the panning of the camera moves it by a fixed number of pixels, while the character's movement involves setting its position to +-10 in either the z or x directions. This disparity sometimes results in the character moving off-screen before reaching the edge of the board due to the camera having moved too far. Is there a way to align the camera along the y-axis while still maintaining the panning effect during movement?

Answer №1

Why not simply transfer the player's x and z coordinates to the camera's, or copy a portion every frame?

camera.position.lerp(player.position, 0.03);

For example, run the code, click on it, then use the arrow keys.

'use strict';

/* global THREE */

function main() {
  const canvas = document.querySelector('#c');
  const renderer = new THREE.WebGLRenderer({canvas: canvas});

  const fov = 45;
  const aspect = 2;  // the canvas default
  const near = 0.1;
  const far = 100;
  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
  // make the camera look down
  camera.position.set(0, 10, 0);
  camera.up.set(0, 0, -1);
  camera.lookAt(0, 0, 0);
  
  const scene = new THREE.Scene();
  scene.background = new THREE.Color('black');

  scene.add(new THREE.GridHelper(40, 40));
     
  let player;
  {
    const cubeSize = 1;
    const cubeGeo = new THREE.BoxBufferGeometry(cubeSize, cubeSize, cubeSize);
    const cubeMat = new THREE.MeshBasicMaterial({color: 'red'});
    player = new THREE.Mesh(cubeGeo, cubeMat);
    player.position.set(.5, .5, .5);
    scene.add(player);
  }

  function resizeRendererToDisplaySize(renderer) {
    const canvas = renderer.domElement;
    const width = canvas.clientWidth;
    const height = canvas.clientHeight;
    const needResize = canvas.width !== width || canvas.height !== height;
    if (needResize) {
      renderer.setSize(width, height, false);
    }
    return needResize;
  }

  function render() {

    if (resizeRendererToDisplaySize(renderer)) {
      const canvas = renderer.domElement;
      camera.aspect = canvas.clientWidth / canvas.clientHeight;
      camera.updateProjectionMatrix();
    }
    
    camera.position.lerp(player.position, 0.03);
    camera.position.y = 10; // keep the elevation;

    renderer.render(scene, camera);

    requestAnimationFrame(render);
  }

  requestAnimationFrame(render);
  
  window.addEventListener('keydown', (e) => {
    e.preventDefault();
    switch (e.keyCode) {
      case 38: // up
        player.position.z -= 1;
        break;
      case 40: // down
        player.position.z += 1;
        break;
      case 37: // left
        player.position.x -= 1;
        break;
      case 39: // right
        player.position.x += 1;
        break;
    }
  });
}

main();
html, body {
  margin: 0;
  height: 100%;
}
#c {
  width: 100%;
  height: 100%;
  display: block;
}
<canvas id="c"></canvas>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r98/three.min.js"></script>

Increasing the value from 0.03 to a larger number will make the camera catch up faster.

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

Transmitting data from the backend to AngularJS during page load

After diving into Angular JS for the first time, I've hit a roadblock at an essential stage. My setup consists of an AngularJS front end and Grails backend. Check out the code snippets below along with my query. URL Mapping entry: as "/graph"(cont ...

How can the AngularJS model be updated while using long polling with Ajax?

How can I update the model using ajax long polling method? To start, I will load the default list: For example: - id1 - id2 - id3 Next, I set up an ajax long polling process in the background that runs every 5 seconds. When the ajax call receives an upd ...

When the page is refreshed, the Canvas element will appear completely white and display a white rectangle (specifically on Chrome)

Currently in the process of developing a website with React and Next JS, I encountered an issue while trying to build a 3D scene using Three JS wrapped in React-Three/Fiber. Whenever I reload the website or development server on Google Chrome, I notice whi ...

Take the attention away from the canvas

Is there a way to shift focus away from the canvas and onto input fields in my HTML code? Right now, the canvas is holding onto focus even when I'm clicking on text inputs. This prevents me from typing anything into them. Ideally, I'd like for t ...

utilizing AJAX to retrieve scripts from WITHIN my own domain

In the realm of ajax scripts, I encounter a scenario where referencing something within the same domain requires passing HTML and associated javascript. Due to it being a non X-domain setup, I anticipate that this could be achievable. The aim here is to fe ...

Tips on using the ref attribute in Vue.js to focus on an input element

In my Vue.js component for 2FA, I have implemented the following structure: <template> <div :class="onwhite ? 'on-white' : ''"> <input :id="`n1`" ref="n1" v-model=&quo ...

Setting up webpack for React to utilize multiple entry points and outputs

Having some trouble configuring the server to handle multiple entries and outputs. The application utilizes Zurb Foundation, jQuery, and React. I'm aiming to exclude jQuery and foundation from the bundle.js file, while also creating a separate bundle ...

Exploring JSON and jQuery to Address Filtering Challenges

Excuse the interruption, but I need some assistance with my filters. Below is the code I'm currently working on; however, none of my attempts have been implemented yet (the dropdown menu and checkboxes remain non-functional) to make it easier for you ...

How can I target the first checkbox within a table row using jQuery?

I am seeking a way to determine if the first checkbox in a table row is selected, rather than checking all checkboxes within that particular row. Currently, I am using this code: var b = false; $j('#tb1 td input:checkbox').each(function(){ ...

Guide to Establishing a Connection to WCF Service using Ionic Project and AngularJS

Greetings, I am currently experiencing an issue tasked with connecting my Ionic project to a WCF service located on another PC (running a C# Application) within the local network. I have verified that the network connection between the PCs is functioning p ...

What should we do to resolve the uncommon use of the 'this' es-lint error? Which rule should we disable?

Recently, I encountered an issue with my Nuxt setup that is configured with el-lint and prettier. Every time I try to use 'this' within my template, it throws up an error unexpectedly. 6:15 error Unexpected usage of 'this' vue/this ...

Converting Dynamo DB stream data into Json format

I need to convert the DDB stream message into a standard JSON format. To achieve this, I am using unmarshalleddata = aws.DynamoDB.Converter.unmarshall(result.NewImage); where result.NewImage is { carrier: { S: 'SPRING' }, partnerTransacti ...

Avoiding the use of destructuring for undefined values in JavaScript can be achieved by implementing

Upon receiving the response registryReportSettings from the server: this.getRegistrySettings(registry.Id).subscribe((registryReportSettings: { extended: ReportPropertiesRequest }) => { const { objectProperties, reportProperties, textProperties } = reg ...

Is it possible to execute appendChild in the context of JS-DOM-creation?

Hey there, I'm a newbie trying my hand at DOM creation. I've encountered a strange issue with appendChild - the first and second tries work fine, but I'm completely stuck on the third attempt. Here's my HTML: <html> <head> ...

The JQuery TextNTags plugin eliminates tag formatting once the trigger syntax has been modified

I have incorporated the JQuery TextNTags plugin into my web application. Here is the original code snippet: $.browser = { webkit: true }; $(function () { $('textarea.tagged_text').textntags({ triggers: {'!': { ...

Encountering a build error in Next.js 13 when attempting to fetch an API route within a server component

I encountered an issue while building my next app (yarn run build). To troubleshoot, I created a new clean project and tested it. The problem seems to be with my route (/api/categories/route.ts) export async function GET() { return new Response(JSON.str ...

What is the method for identifying the name of a CSS Variable currently in use?

Consider this code snippet: /* css */ :root { --text-color: #666666; } input { color: var(--text-color); } In Javascript, how can I determine the name of the CSS custom property (variable) being utilized? // javascript console.log(document.querySel ...

Eliminating any spaces in the password prior to finalizing the form submission

After submitting the Form, I am trying to remove all spaces from the Password field. This is my current code: $(document).on("submit", "form#user-login", function(e){ e.preventDefault(); var emailAdd = $("#edit-pass").val().replace(/ / ...

Use jQuery to open and close HTML tags efficiently

It seems like the task I have at hand may not be as simple as I had hoped, so here I am seeking some reassurance. I am aiming to switch out an image with a closing div, then the image itself, followed by another opening div. Let me illustrate this with a ...

Replace the indexOf() method to be called on a null value

I have discovered a way to override functions in JavaScript, such as indexOf(), like this: var indexOf = String.prototype.indexOf; String.prototype.indexOf = function(){ //MY CUSTOM CODE HERE return indexOf.call(this, arguments); }; By doing this ...